diff --git a/src/examples/mnist/MNIST_SP.cpp b/src/examples/mnist/MNIST_SP.cpp index 35c46fae1b..46458a06b0 100644 --- a/src/examples/mnist/MNIST_SP.cpp +++ b/src/examples/mnist/MNIST_SP.cpp @@ -67,12 +67,12 @@ class MNIST { public: UInt verbosity = 1; - const UInt train_dataset_iterations = 2u; //epochs somewhat help, at linear time + const UInt train_dataset_iterations = 1u; //epochs somewhat help, at linear time void setup() { - input.initialize({28, 28,1}); + input.initialize({28, 28, 1}); columns.initialize({28, 28, 8}); //1D vs 2D no big difference, 2D seems more natural for the problem. Speed-----, Results+++++++++; #columns HIGHEST impact. sp.initialize( /* inputDimensions */ input.dimensions, @@ -88,7 +88,7 @@ void setup() { /* synPermConnected */ 0.5f, //no difference, let's leave at 0.5 in the middle /* minPctOverlapDutyCycles */ 0.2f, //speed of re-learning? /* dutyCyclePeriod */ 1402, - /* boostStrength */ 2.0f, // Boosting does help, but entropy is high, on MNIST it does not matter, for learning with TM prefer boosting off (=0.0), or "neutral"=1.0 + /* boostStrength */ 7.0f, // Boosting does help, but entropy is high, on MNIST it does not matter, for learning with TM prefer boosting off (=0.0), or "neutral"=1.0 /* seed */ 4u, /* spVerbosity */ 1u, /* wrapAround */ true); // does not matter (helps slightly) diff --git a/src/htm/algorithms/Connections.cpp b/src/htm/algorithms/Connections.cpp index 15f3fd4032..1f8d150d96 100644 --- a/src/htm/algorithms/Connections.cpp +++ b/src/htm/algorithms/Connections.cpp @@ -395,7 +395,8 @@ void Connections::computeActivity( vector &numActiveConnectedSynapsesForSegment, const vector &activePresynapticCells) { - NTA_ASSERT(numActiveConnectedSynapsesForSegment.size() == segments_.size()); + NTA_ASSERT(numActiveConnectedSynapsesForSegment.size() == segments_.size()) << "The output vector size must match "<< segments_.size(); + NTA_ASSERT(activePresynapticCells.size() < segments_.size()) << "Input is larger than our number of segments!"; if( timeseries_ ) { // Before each cycle of computation move the currentUpdates to the previous @@ -406,7 +407,7 @@ void Connections::computeActivity( // Iterate through all connected synapses. for (const auto& cell : activePresynapticCells) { - if (connectedSegmentsForPresynapticCell_.count(cell)) { + if (connectedSegmentsForPresynapticCell_.count(cell) > 0) { //there are connected segments for(const auto& segment : connectedSegmentsForPresynapticCell_.at(cell)) { ++numActiveConnectedSynapsesForSegment[segment]; } diff --git a/src/htm/algorithms/Connections.hpp b/src/htm/algorithms/Connections.hpp index cb0a6ef8ab..75dca0a994 100644 --- a/src/htm/algorithms/Connections.hpp +++ b/src/htm/algorithms/Connections.hpp @@ -391,11 +391,11 @@ class Connections : public Serializable * @param numActiveConnectedSynapsesForSegment * An output vector for active connected synapse counts per segment. * - * @param numActivePotentialSynapsesForSegment + * @param (optional) numActivePotentialSynapsesForSegment * An output vector for active potential synapse counts per segment. * * @param activePresynapticCells - * Active cells in the input. + * Active cells in the input as a sparse indices. */ void computeActivity(std::vector &numActiveConnectedSynapsesForSegment, std::vector &numActivePotentialSynapsesForSegment, diff --git a/src/htm/algorithms/SpatialPooler.cpp b/src/htm/algorithms/SpatialPooler.cpp index 5ee4a46ac6..1557e2d285 100644 --- a/src/htm/algorithms/SpatialPooler.cpp +++ b/src/htm/algorithms/SpatialPooler.cpp @@ -839,44 +839,81 @@ void SpatialPooler::inhibitColumns_(const vector &overlaps, } } +static int missed = 0; void SpatialPooler::inhibitColumnsGlobal_(const vector &overlaps, - Real density, - vector &activeColumns) const { + const Real density, + SDR_sparse_t &activeColumns) const { NTA_ASSERT(!overlaps.empty()); NTA_ASSERT(density > 0.0f && density <= 1.0f); activeColumns.clear(); - const UInt numDesired = (UInt)(density * numColumns_); + const UInt numDesired = static_cast(density*numColumns_); NTA_CHECK(numDesired > 0) << "Not enough columns (" << numColumns_ << ") " << "for desired density (" << density << ")."; // Sort the columns by the amount of overlap. First make a list of all of the // column indexes. + int zero = 0; + int same = 0; + int sub = 0; activeColumns.reserve(numColumns_); - for(UInt i = 0; i < numColumns_; i++) - activeColumns.push_back(i); + for(UInt i = 0; i < numColumns_; i++) { + activeColumns.push_back(i); //TODO use iota when debug is over: std::iota(activeColumns.begin(), activeColumns.end(), 0); //0,1,2,..,numColumns_-1 + //some statistics + if(overlaps[i] < Epsilon) {zero++; continue;} + if(overlaps[i] < stimulusThreshold_) sub++; + if(i==numColumns_-2) break; + if(fabs(overlaps[i]-overlaps[i+1]) < Epsilon) same++; + } + // Compare the column indexes by their overlap. - auto compare = [&overlaps](const UInt &a, const UInt &b) -> bool - {return (overlaps[a] == overlaps[b]) ? a > b : overlaps[a] > overlaps[b];}; //for determinism if overlaps match (tieBreaker does not solve that), - //otherwise we'd return just `return overlaps[a] > overlaps[b]`. + auto compare = [&overlaps, &same](const UInt a, const UInt b) -> bool { + if(overlaps[a] == overlaps[b]) return a > b; + else return overlaps[a] > overlaps[b] and overlaps[a] > 6.0f; + }; // Do a partial sort to divide the winners from the losers. This sort is // faster than a regular sort because it stops after it partitions the // elements about the Nth element, with all elements on their correct side of // the Nth element. - std::nth_element( +/* + std::nth_element( activeColumns.begin(), activeColumns.begin() + numDesired, activeColumns.end(), compare); + */ // Remove the columns which lost the competition. - activeColumns.resize(numDesired); +//! activeColumns.resize(numDesired); // Finish sorting the winner columns by their overlap. std::sort(activeColumns.begin(), activeColumns.end(), compare); // Remove sub-threshold winners while( !activeColumns.empty() && - overlaps[activeColumns.back()] < stimulusThreshold_) + overlaps[activeColumns.back()] < stimulusThreshold_) { activeColumns.pop_back(); + } + + //FIXME not numDesired + if(iterationNum_ < 1000) return; //need time for learning + if(activeColumns.size() != numDesired) { + missed++; + int missing = max(0, (int)numDesired - (int)activeColumns.size()); + int ok = numColumns_ - sub - zero; + if(ok > (int)numDesired and missing > 0) + cout << "missed\t" << missed << "-times; by " << missing << "\tof " << numDesired + << " ;\tsame % " << (Real)same/numColumns_*100 << "; \tzero % " << ((Real)zero/numColumns_)*100 + << "\tsub threshold % " << (Real)sub/numColumns_*100 << "\n"; + + int same2=0; + for(size_t i = 0; i < activeColumns.size()-2; i++) { + if(activeColumns[i] == activeColumns[i+1]) same2++; + } + cout << "have same " << same2 << endl; //FIXME there are no same! + + } + //FIXME same values ok? + //FIXME sparse overlaps from conn + //FIXME conn perm inc/dec multiplied by *err (sigmoid)? } diff --git a/src/htm/algorithms/SpatialPooler.hpp b/src/htm/algorithms/SpatialPooler.hpp index 3f2d1cbe33..667a3b9b94 100644 --- a/src/htm/algorithms/SpatialPooler.hpp +++ b/src/htm/algorithms/SpatialPooler.hpp @@ -941,7 +941,8 @@ class SpatialPooler : public Serializable @param activeColumns an int array containing the indices of the active columns. */ - void inhibitColumnsGlobal_(const vector &overlaps, Real density, + void inhibitColumnsGlobal_(const vector &overlaps, + const Real density, vector &activeColumns) const; /** @@ -970,7 +971,8 @@ class SpatialPooler : public Serializable @param activeColumns an int array containing the indices of the active columns. */ - void inhibitColumnsLocal_(const vector &overlaps, Real density, + void inhibitColumnsLocal_(const vector &overlaps, + const Real density, vector &activeColumns) const; /** diff --git a/src/htm/utils/Topology.hpp b/src/htm/utils/Topology.hpp index 35ac443992..a8a1dbca16 100644 --- a/src/htm/utils/Topology.hpp +++ b/src/htm/utils/Topology.hpp @@ -32,18 +32,18 @@ namespace htm { /** - * Topology_t is a function which returns the pool of potential synapses for a - * given cell. + * Topology_t is a function which returns the pool of potential synapses (input field) + * for a given cell C. * - * Argument 1: is an SDR representing the postsynaptic cell. Topology functions + * @param cell an SDR representing the postsynaptic cell C. Topology functions * return the inputs which may connect to this cell. This SDR contains a single * true bit. * - * Argument 2: is the dimensions of the presynaptic cells. + * @param inputDimension the dimensions of the presynaptic cells. * - * Argument 3: is a random number generator to use for reproducible results. + * @param rng a random number generator to use for reproducible results. * - * Returns: an SDR containing all presynaptic cells which are allowed to connect + * @returns SDR containing all presynaptic cells which are allowed to connect * to the postsynaptic cell. The dimensions of this SDR must equal argument 2. * * Example Usage: @@ -62,7 +62,9 @@ namespace htm { * }; * } */ -typedef std::function&, Random&)> Topology_t; +typedef std::function& inputDimensions, + Random& rng)> Topology_t; /** * @param potentialRadius: This parameter determines the extent of the