Skip to content

Commit c877b27

Browse files
Fix TM repeating inputs issue.
1 parent 34a6853 commit c877b27

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

bindings/py/tests/algorithms/temporal_memory_test.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,23 @@ def testGetMethods(self):
247247
self.assertEqual(parameters1["tm"]["maxSynapsesPerSegment"], maxSynapsesPerSegment, "using Method (getMaxSynapsesPerSegment) failed")
248248
self.assertEqual(True, checkInputs, "using Method (getCheckInputs) failed")
249249

250+
def testStaticInputs(self):
251+
""" Check that repeating the same input results in the same output. """
252+
cols = 100
253+
tm = TM([cols])
254+
# Train on a square wave.
255+
inp_a = SDR(cols).randomize( .2 )
256+
inp_b = SDR(cols).randomize( .2 )
257+
for i in range(10): tm.compute( inp_a, True )
258+
for i in range(10): tm.compute( inp_b, True )
259+
# Test that it reached a steady state.
260+
self.assertEqual(tm.anomaly, 0.0)
261+
out_1 = tm.getActiveCells()
262+
tm.compute( inp_b, True )
263+
self.assertEqual(tm.anomaly, 0.0)
264+
out_2 = tm.getActiveCells()
265+
self.assertTrue(all(out_1.sparse == out_2.sparse))
266+
250267
def _print(txt):
251268
if debugPrint:
252269
print(txt)

src/htm/algorithms/TemporalMemory.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,9 @@ void TemporalMemory::activatePredictedColumn_(
190190

191191

192192
void TemporalMemory::burstColumn_(
193-
const UInt column,
194-
vector<Segment>::const_iterator columnMatchingSegmentsBegin,
195-
vector<Segment>::const_iterator columnMatchingSegmentsEnd,
193+
const UInt column,
194+
const vector<Segment>::const_iterator columnMatchingSegmentsBegin,
195+
const vector<Segment>::const_iterator columnMatchingSegmentsEnd,
196196
const SDR &prevActiveCells,
197197
const vector<CellIdx> &prevWinnerCells,
198198
const bool learn) {
@@ -208,19 +208,28 @@ void TemporalMemory::burstColumn_(
208208
numActivePotentialSynapsesForSegment_[b]);
209209
});
210210

211-
const CellIdx winnerCell =
212-
(bestMatchingSegment != columnMatchingSegmentsEnd)
213-
? connections.cellForSegment(*bestMatchingSegment)
214-
: getLeastUsedCell_(column); //TODO replace (with random?) this is extremely costly, removing makes TM 6x faster!
215-
211+
CellIdx winnerCell;
212+
if(bestMatchingSegment != columnMatchingSegmentsEnd) {
213+
winnerCell = connections.cellForSegment(*bestMatchingSegment);
214+
}
215+
else {
216+
// Check for previous winner cells in this minicolumn.
217+
const auto prevWinnerPtr = std::lower_bound(prevWinnerCells.begin(), prevWinnerCells.end(), column,
218+
[&](const CellIdx cell, const UInt col) { return columnForCell(cell) < col; });
219+
if(prevWinnerPtr != prevWinnerCells.end() && columnForCell(*prevWinnerPtr) == column) {
220+
winnerCell = *prevWinnerPtr;
221+
}
222+
else {
223+
winnerCell = getLeastUsedCell_(column);
224+
}
225+
}
216226
winnerCells_.push_back(winnerCell);
217227

218-
// Learn.
219228
if (learn) {
220229
if (bestMatchingSegment != columnMatchingSegmentsEnd) {
221230
// Learn on the best matching segment.
222231
connections_.adaptSegment(*bestMatchingSegment, prevActiveCells,
223-
permanenceIncrement_, permanenceDecrement_, true, minThreshold_); //TODO consolidate SP.stimulusThreshold_ & TM.minThreshold_ into Conn.stimulusThreshold ? (replacing segmentThreshold arg used in some methods in Conn)
232+
permanenceIncrement_, permanenceDecrement_, true, minThreshold_);
224233

225234
const Int32 nGrowDesired = maxNewSynapseCount_ - numActivePotentialSynapsesForSegment_[*bestMatchingSegment];
226235
if (nGrowDesired > 0) {

0 commit comments

Comments
 (0)