Skip to content

Commit

Permalink
Merge pull request numenta#376 from htm-community/rm-sdrc-result
Browse files Browse the repository at this point in the history
Remove Class SDRClassifierResult
  • Loading branch information
breznak authored Apr 8, 2019
2 parents fa4948b + 95a0367 commit df495f0
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 293 deletions.
8 changes: 4 additions & 4 deletions bindings/py/cpp_src/bindings/algorithms/py_SDRClassifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ PyBind11 bindings for SDRClassifier class
namespace nupic_ext
{
namespace py = pybind11;
using namespace std;
using namespace nupic;
using namespace nupic::algorithms::sdr_classifier;
using nupic::types::PDF;

void init_SDR_Classifier(py::module& m)
{
Expand All @@ -67,7 +67,7 @@ using nupic::types::PDF;

py::dict dict;

for (map<Int, PDF*>::const_iterator it = result.begin(); it != result.end(); ++it)
for (map<Int, PDF>::const_iterator it = result.begin(); it != result.end(); ++it)
{
std::string key = "actualValues";

Expand All @@ -77,9 +77,9 @@ using nupic::types::PDF;
}

py::list value;
for (UInt i = 0; i < it->second->size(); ++i)
for (UInt i = 0; i < it->second.size(); ++i)
{
value.append(it->second->at(i));
value.append(it->second.at(i));
}

dict[key.c_str()] = value;
Expand Down
2 changes: 0 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,6 @@ set(regions_files
)

set(types_files
nupic/types/ClassifierResult.cpp
nupic/types/ClassifierResult.hpp
nupic/types/Exception.hpp
nupic/types/Types.hpp
nupic/types/Serializable.hpp
Expand Down
6 changes: 3 additions & 3 deletions src/examples/mnist/MNIST_SP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ using namespace nupic;

using nupic::algorithms::spatial_pooler::SpatialPooler;
using nupic::algorithms::sdr_classifier::SDRClassifier;
using nupic::types::ClassifierResult;
using nupic::algorithms::sdr_classifier::ClassifierResult;

class MNIST {

Expand Down Expand Up @@ -157,8 +157,8 @@ void test() {
/* infer */ true,
result);
// Check results
const auto cls = result.getClass();
if(cls == label) score += 1;
if(clsr.getClassification( result[0] ) == label)
score += 1;
n_samples += 1;
if( verbosity && i % 1000 == 0 ) cout << "." << flush;
}
Expand Down
77 changes: 40 additions & 37 deletions src/nupic/algorithms/SDRClassifier.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/* ---------------------------------------------------------------------
* Numenta Platform for Intelligent Computing (NuPIC)
* Copyright (C) 2016, Numenta, Inc. Unless you have an agreement
* with Numenta, Inc., for a separate license for this software code, the
* following terms and conditions apply:
* Copyright (C) 2016, Numenta, Inc.
* 2019, David McDougall
*
* Unless you have an agreement with Numenta, Inc., for a separate license for
* this software code, the following terms and conditions apply:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License version 3 as
Expand All @@ -17,8 +19,7 @@
* along with this program. If not, see http://www.gnu.org/licenses.
*
* http://numenta.org/licenses/
* ---------------------------------------------------------------------
*/
* --------------------------------------------------------------------- */

#include <cmath> //exp
#include <deque>
Expand All @@ -37,17 +38,16 @@
#include <nupic/utils/Log.hpp>


namespace nupic {
namespace algorithms {
namespace sdr_classifier {

using namespace nupic;
using namespace nupic::algorithms::sdr_classifier;
using namespace std;

/**
* get(x,y) accessor interface for Matrix; handles sparse (missing) values
* @return return value stored at map[row][col], or defaultVal if such field does not exist
**/
Real64 get_(const Matrix& m, const UInt row, const UInt col, const Real64 defaultVal=0.0) {

UInt SDRClassifier::getClassification( const PDF & data ) const
{ return max_element( data.begin(), data.end() ) - data.begin(); }


Real64 SDRClassifier::get_(const Matrix& m, const UInt row, const UInt col, const Real64 defaultVal) const {
try {
return m.at(row).at(col);
} catch(std::exception& ex ) {
Expand Down Expand Up @@ -172,7 +172,7 @@ void SDRClassifier::compute(UInt recordNum, const vector<UInt> &patternNZ,
Matrix& w = weightMatrix_.at(nSteps);
NTA_ASSERT(alpha_ > 0.0);
for (const auto& bit : learnPatternNZ) {
for(UInt i = 0; i < error.size(); i++) {
for(size_t i = 0; i < error.size(); i++) {
const auto val = get_(w, bit, i) + alpha_ * error[i];
if(val == 0) continue;
w[bit][i] = val;
Expand All @@ -185,35 +185,42 @@ void SDRClassifier::compute(UInt recordNum, const vector<UInt> &patternNZ,

void SDRClassifier::infer_(const vector<UInt> &patternNZ,
const vector<Real64> &actValue,
ClassifierResult &result) {
// add the actual values to the return value. For buckets that haven't
ClassifierResult &result)
{
// Add the actual values to the return value. For buckets that haven't
// been seen yet, the actual value doesn't matter since it will have
// zero likelihood.
vector<Real64> *actValueVector =
result.createVector(-1, (UInt)actualValues_.size(), 0.0);
for (UInt i = 0; i < (UInt)actualValues_.size(); ++i) {
vector<Real64> &actValueVector = result[ACTUAL_VALUES];
actValueVector.reserve( actualValues_.size() );

for( size_t i = 0; i < actualValues_.size(); ++i ) {
if (actualValuesSet_[i]) {
(*actValueVector)[i] = actualValues_[i];
} else {
actValueVector.push_back( actualValues_[i] );
}
else {
// if doing 0-step ahead prediction, we shouldn't use any
// knowledge of the classification input during inference
if (steps_.at(0) == 0) {
(*actValueVector)[i] = 0;
} else {
(*actValueVector)[i] = actValue[0];
if( steps_.at(0) == 0 ) {
actValueVector.push_back( 0.0f );
}
else {
actValueVector.push_back( actValue[0] );
}
}
}

for (auto nSteps = steps_.begin(); nSteps != steps_.end(); ++nSteps) {
vector<Real64>* likelihoods = result.createVector(*nSteps, maxBucketIdx_ + 1, 0.0);
for (const auto& bit : patternNZ) {
for( auto nSteps = steps_.begin(); nSteps != steps_.end(); ++nSteps )
{
vector<Real64> &likelihoods = result[ *nSteps ];
likelihoods.assign( maxBucketIdx_ + 1, 0.0f );

for( const auto& bit : patternNZ ) {
const Matrix& w = weightMatrix_.at(*nSteps);
for(UInt i =0; i< (UInt)likelihoods->size(); i++) {
likelihoods->at(i) += get_(w, bit, i);
for( size_t i = 0; i < likelihoods.size(); i++ ) {
likelihoods.at(i) += get_(w, bit, i);
}
}
softmax_(likelihoods->begin(), likelihoods->end());
softmax_( likelihoods.begin(), likelihoods.end() );
}
}

Expand All @@ -238,7 +245,7 @@ vector<Real64> SDRClassifier::calculateError_(const vector<UInt> &bucketIdxList,
targetDistribution[bucketIdxList[i]] = 1.0 / numCategories;

NTA_ASSERT(likelihoods.size() == targetDistribution.size());
for(UInt i = 0; i < likelihoods.size(); i++) {
for(size_t i = 0; i < likelihoods.size(); i++) {
likelihoods[i] = targetDistribution[i] - likelihoods[i];
}
return likelihoods;
Expand Down Expand Up @@ -500,7 +507,3 @@ bool SDRClassifier::operator==(const SDRClassifier &other) const {
return true;
}


} // namespace sdr_classifier
} // namespace algorithms
} // namespace nupic
80 changes: 53 additions & 27 deletions src/nupic/algorithms/SDRClassifier.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/* ---------------------------------------------------------------------
* Numenta Platform for Intelligent Computing (NuPIC)
* Copyright (C) 2016, Numenta, Inc. Unless you have an agreement
* with Numenta, Inc., for a separate license for this software code, the
* following terms and conditions apply:
* Copyright (C) 2016, Numenta, Inc.
* 2019, David McDougall
*
* Unless you have an agreement with Numenta, Inc., for a separate license for
* this software code, the following terms and conditions apply:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License version 3 as
Expand All @@ -17,8 +19,7 @@
* along with this program. If not, see http://www.gnu.org/licenses.
*
* http://numenta.org/licenses/
* ---------------------------------------------------------------------
*/
* --------------------------------------------------------------------- */

/** @file
* Definitions for the SDRClassifier.
Expand All @@ -33,36 +34,50 @@
#include <string>
#include <vector>

#include <nupic/types/ClassifierResult.hpp>
#include <nupic/types/Types.hpp>
#include <nupic/types/Serializable.hpp>

namespace nupic {
namespace algorithms {
namespace sdr_classifier {
using namespace std;
using nupic::types::ClassifierResult;


const UInt sdrClassifierVersion = 2;

/**
* 2d map used to store the data.
* write with Matrix m; m[i][j] = 1.0; //map will always allocate for new i,j index
* access/read with get_(&m, i, j): as it handles missing values i,j and returns 0.0 for them
* PDF - Probability Density Function, distribution of likelihood of values
*/
using PDF = std::vector<Real64>;

/**
* The key is the step, for predicting multiple time steps into the future.
* The key ACTUAL_VALUES contains an estimate of the actual values.
* The value is a PDF(probability density function, list of probabilities of outcomes)
* of the result being in each bucket.
*/
typedef std::map<UInt, std::map<UInt, Real64>> Matrix; //Matrix[r][c] = 0.0d
const Int ACTUAL_VALUES = -1;
using ClassifierResult = std::map<Int, PDF>;


class SDRClassifier : public Serializable
{
// Make test class friend so it can unit test private members directly
friend class SDRClassifierTest;

/**
* 2d map used to store the data.
* write with Matrix m; m[i][j] = 1.0; //map will always allocate for new i,j index
* access/read with get_(&m, i, j): as it handles missing values i,j and returns 0.0 for them
*/
using Matrix = std::map<UInt, std::map<UInt, Real64>>; //Matrix[r][c] = 0.0d


public:
/**
* Constructor for use when deserializing.
*/
SDRClassifier() {}
void initialize(const vector<UInt> &steps, Real64 alpha, Real64 actValueAlpha,
void initialize(const std::vector<UInt> &steps, Real64 alpha, Real64 actValueAlpha,
UInt verbosity);

/**
Expand All @@ -74,7 +89,7 @@ class SDRClassifier : public Serializable
* values for each bucket.
* @param verbosity The logging verbosity.
*/
SDRClassifier(const vector<UInt> &steps, Real64 alpha, Real64 actValueAlpha,
SDRClassifier(const std::vector<UInt> &steps, Real64 alpha, Real64 actValueAlpha,
UInt verbosity);

/**
Expand All @@ -99,11 +114,16 @@ class SDRClassifier : public Serializable
* values for key 0 correspond to the actual values to
* used when predicting each bucket.
*/
virtual void compute(UInt recordNum, const vector<UInt> &patternNZ,
const vector<UInt> &bucketIdxList,
const vector<Real64> &actValueList, bool category,
virtual void compute(UInt recordNum, const std::vector<UInt> &patternNZ,
const std::vector<UInt> &bucketIdxList,
const std::vector<Real64> &actValueList, bool category,
bool learn, bool infer, ClassifierResult &result);

/**
* Returns the class with the greatest probablility.
*/
UInt getClassification( const PDF & ) const;

/**
* Gets the version number
*/
Expand Down Expand Up @@ -141,18 +161,24 @@ class SDRClassifier : public Serializable

private:
// Helper function for inference mode
void infer_(const vector<UInt> &patternNZ, const vector<Real64> &actValue,
void infer_(const std::vector<UInt> &patternNZ, const std::vector<Real64> &actValue,
ClassifierResult &result);

// Helper function to compute the error signal in learning mode
vector<Real64> calculateError_(const vector<UInt> &bucketIdxList,
const vector<UInt> patternNZ, UInt step);
std::vector<Real64> calculateError_(const std::vector<UInt> &bucketIdxList,
const std::vector<UInt> patternNZ, UInt step);

// softmax function
void softmax_(vector<Real64>::iterator begin, vector<Real64>::iterator end);
void softmax_(std::vector<Real64>::iterator begin, std::vector<Real64>::iterator end);

/**
* get(x,y) accessor interface for Matrix; handles sparse (missing) values
* @return return value stored at map[row][col], or defaultVal if such field does not exist
**/
Real64 get_(const Matrix& m, const UInt row, const UInt col, const Real64 defaultVal=0.0) const;

// The list of prediction steps to learn and infer.
vector<UInt> steps_;
std::vector<UInt> steps_;

// The alpha used to decay the duty cycles in the BitHistorys.
Real64 alpha_;
Expand All @@ -165,11 +191,11 @@ class SDRClassifier : public Serializable

// Stores the input pattern history, starting with the previous input
// and containing _maxSteps total input patterns.
deque<vector<UInt>> patternNZHistory_;
deque<UInt> recordNumHistory_;
std::deque<std::vector<UInt>> patternNZHistory_;
std::deque<UInt> recordNumHistory_;

// Weight matrices for the classifier (one per prediction step)
map<UInt, Matrix> weightMatrix_;
std::map<UInt, Matrix> weightMatrix_;

// The highest input bit that the classifier has seen so far.
UInt maxInputIdx_;
Expand All @@ -179,11 +205,11 @@ class SDRClassifier : public Serializable

// The current actual values used for each bucket index. The index of
// the actual value matches the index of the bucket.
vector<Real64> actualValues_;
std::vector<Real64> actualValues_;

// A boolean that distinguishes between actual values that have been
// seen and those that have not.
vector<bool> actualValuesSet_;
std::vector<bool> actualValuesSet_;

// Version and verbosity.
UInt version_;
Expand Down
Loading

0 comments on commit df495f0

Please sign in to comment.