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
8 changes: 4 additions & 4 deletions src/examples/mnist/MNIST_SP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ class MNIST {

void setup() {

input.initialize({28 * 28});
columns.initialize({10 * 1000});
input.initialize({28, 28, 1});
columns.initialize({28, 28, 8});
sp.initialize(
/* inputDimensions */ input.dimensions,
/* columnDimensions */ columns.dimensions,
/* potentialRadius */ 999999u, // No topology, all to all connections.
/* potentialPct */ 0.65f,
/* potentialRadius */ 7u, // No topology, all to all connections.
/* potentialPct */ 0.1f,
/* globalInhibition */ true,
/* localAreaDensity */ 0.05f, // % active bits
/* numActiveColumnsPerInhArea */ -1,
Expand Down
3 changes: 2 additions & 1 deletion 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 Down
4 changes: 2 additions & 2 deletions src/htm/algorithms/Connections.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,11 +392,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
40 changes: 31 additions & 9 deletions src/htm/algorithms/SpatialPooler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,10 +847,12 @@ 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);

Expand All @@ -860,34 +862,54 @@ void SpatialPooler::inhibitColumnsGlobal_(const vector<Real> &overlaps,
overlaps_[i] += tieBreaker_[i];

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.
activeColumns.reserve(numColumns_);
for(UInt i = 0; i < numColumns_; i++)
activeColumns.push_back(i);
activeColumns.resize(numColumns_);
std::iota(activeColumns.begin(), activeColumns.end(), 0); //0,1,2,..,numColumns_-1

int same_overlap = 0;
// 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];};
auto compare = [&overlaps_, &same_overlap](const UInt &a, const UInt &b) -> bool
{
if (overlaps_[a] == overlaps_[b]) {
same_overlap++;
return a > b; //but we also need this for deterministic results
Copy link
Member Author

Choose a reason for hiding this comment

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

problem 1: we are removing columns with the same overlap from the top n selection.

} else {
return overlaps_[a] > overlaps_[b]; //this is the main "sort columns by overlaps"
}
};
// 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);
Copy link
Member Author

@breznak breznak Jul 6, 2019

Choose a reason for hiding this comment

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

Problem 2: here we crop to numDesired, but too early..

*/
// 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_)
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.


activeColumns.resize(std::min(numDesired, (UInt)activeColumns.size()));

//FIXME not numDesired
if(iterationNum_ > 1000) { //need time for learning
if(activeColumns.size() != numDesired) {
missed++;
cout << "missed " << missed << " by " << (numDesired - activeColumns.size()) << " of " << numDesired << " same "<< same_overlap << "\n";
}
}
}


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 @@ -943,7 +943,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 @@ -972,7 +973,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