Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SP fix global inhibition returns less than numDesired columns #542

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
6 changes: 3 additions & 3 deletions src/examples/mnist/MNIST_SP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions src/htm/algorithms/Connections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,8 @@ void Connections::computeActivity(
vector<SynapseIdx> &numActiveConnectedSynapsesForSegment,
const vector<CellIdx> &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
Expand All @@ -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];
}
Expand Down
4 changes: 2 additions & 2 deletions src/htm/algorithms/Connections.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SynapseIdx> &numActiveConnectedSynapsesForSegment,
std::vector<SynapseIdx> &numActivePotentialSynapsesForSegment,
Expand Down
59 changes: 48 additions & 11 deletions src/htm/algorithms/SpatialPooler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,44 +839,81 @@ void SpatialPooler::inhibitColumns_(const vector<Real> &overlaps,
}
}

static int missed = 0;

void SpatialPooler::inhibitColumnsGlobal_(const vector<Real> &overlaps,
Real density,
vector<UInt> &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<UInt>(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();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

..since this loop further discards weak columns.

}

//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)?
}


Expand Down
6 changes: 4 additions & 2 deletions src/htm/algorithms/SpatialPooler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -941,7 +941,8 @@ class SpatialPooler : public Serializable
@param activeColumns
an int array containing the indices of the active columns.
*/
void inhibitColumnsGlobal_(const vector<Real> &overlaps, Real density,
void inhibitColumnsGlobal_(const vector<Real> &overlaps,
const Real density,
vector<UInt> &activeColumns) const;

/**
Expand Down Expand Up @@ -970,7 +971,8 @@ class SpatialPooler : public Serializable
@param activeColumns
an int array containing the indices of the active columns.
*/
void inhibitColumnsLocal_(const vector<Real> &overlaps, Real density,
void inhibitColumnsLocal_(const vector<Real> &overlaps,
const Real density,
vector<UInt> &activeColumns) const;

/**
Expand Down
16 changes: 9 additions & 7 deletions src/htm/utils/Topology.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -62,7 +62,9 @@ namespace htm {
* };
* }
*/
typedef std::function<SDR (const SDR&, const std::vector<UInt>&, Random&)> Topology_t;
typedef std::function<SDR (const SDR& cell,
const std::vector<UInt>& inputDimensions,
Random& rng)> Topology_t;

/**
* @param potentialRadius: This parameter determines the extent of the
Expand Down