From 2c27f30000249c32c8ec2b66bcdb4561545f7d12 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Mon, 28 Mar 2011 12:12:15 -0400 Subject: [PATCH 01/39] use a new threshold for input cell activation during imagination --- src/carver/htm/input.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/carver/htm/input.py b/src/carver/htm/input.py index 681b47c..0105016 100644 --- a/src/carver/htm/input.py +++ b/src/carver/htm/input.py @@ -3,6 +3,8 @@ @author: Jason Carver ''' +from carver.htm.synapse import SYNAPSES_PER_SEGMENT +from carver.htm.segment import SEGMENT_ACTIVATION_THRESHOLD class InputCell(object): ''' @@ -45,8 +47,14 @@ def stimulate(self, amount): def override(self): self.overrideInput = True - #TODO move magic number 0.8 into .properties file, or make htm understand float - self.stimulationPast = 1 if self.stimulation > 0.8 else 0 + + percentSynapsesForActivation = float(SEGMENT_ACTIVATION_THRESHOLD)/SYNAPSES_PER_SEGMENT + + if self.stimulation >= percentSynapsesForActivation: + self.stimulationPast = 1 + else: + self.stimulationPast = 0 + self.__resetStimulation() From 9ee17f7f70a95ee1dc6d6c64bc3b5a21b002d00d Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Mon, 28 Mar 2011 12:13:24 -0400 Subject: [PATCH 02/39] execute a step of imagination, when running htm.imagineNext --- src/carver/htm/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/carver/htm/__init__.py b/src/carver/htm/__init__.py index e9e583a..be270c4 100644 --- a/src/carver/htm/__init__.py +++ b/src/carver/htm/__init__.py @@ -83,9 +83,10 @@ def initialize_input(self, data, compressionFactor=1.0): #Actually, just let the first synapses grow on their own in temporal 1 def imagineNext(self): - 'project down estimates for next time step to the input cells' + 'project down estimates for next time step to the input cells, and step through' self._imagineStimulate(self.columns) - return self._imagineOverride(self._inputCells) + self._imagineOverride(self._inputCells) + self.__executeOne(False) @classmethod def _imagineStimulate(cls, columns): From 0fcff95d22127afec8b9ff98e2cd5293d19e66bf Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Mon, 28 Mar 2011 12:14:16 -0400 Subject: [PATCH 03/39] test temporal recognition, using imagination (incomplete) --- src/carver/tests/recognition_temporal.py | 141 +++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 src/carver/tests/recognition_temporal.py diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py new file mode 100644 index 0000000..d68827e --- /dev/null +++ b/src/carver/tests/recognition_temporal.py @@ -0,0 +1,141 @@ +''' +Created on Dec 7, 2010 + +@author: Jason Carver +''' +import unittest +from carver.htm import HTM +from carver.htm.ui.excite_history import ExciteHistory +from carver.htm.io.objectrecognize import ObjectRecognize +from carver.htm.io.translate_input import TranslateInput +from PIL import Image +from carver.htm.io.image_builder import ImageBuilder +from carver.htm.segment import SEGMENT_ACTIVATION_THRESHOLD +from carver.htm.synapse import SYNAPSES_PER_SEGMENT + +class TestRecognitionTemporal(unittest.TestCase): + + + def setUp(self): + self.left_block = [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [1,1,1,1,0,0,0,0,0,0,0,0,0,0], + [1,1,1,1,0,0,0,0,0,0,0,0,0,0], + [1,1,1,1,0,0,0,0,0,0,0,0,0,0], + [1,1,1,1,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + ] + self.right_block = [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,1,1,1,1], + [0,0,0,0,0,0,0,0,0,0,1,1,1,1], + [0,0,0,0,0,0,0,0,0,0,1,1,1,1], + [0,0,0,0,0,0,0,0,0,0,1,1,1,1], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + ] + self.top_block = [ + [0,0,0,0,0,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + ] + self.bottom_block = [ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,0,0,0,0,0,0,0,0,0], + [0,0,0,0,0,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,1,1,1,1,0,0,0,0,0], + [0,0,0,0,0,1,1,1,1,0,0,0,0,0], + ] + + def tearDown(self): + pass + + def testTemporalTest(self): + h = HTM(cellsPerColumn=3) + h.initialize_input(self.left_block) + + #show a whole left->right pass, 5 times + steps = 14*5*10 + goright = TranslateInput(self.left_block, shift=(1,0)) + h.execute(goright.dataGenerator(), ticks=steps-1) + + #show a whole right->left pass, 5 times + goleft = TranslateInput(self.right_block, shift=(-1,0)) + h.execute(goleft.dataGenerator(), ticks=steps-1) + + #show a whole top->bottom pass, 5 times + godown = TranslateInput(self.top_block, shift=(0,1)) + h.execute(godown.dataGenerator(), ticks=steps-1) + + #show a whole bottom->top pass, 5 times + goup = TranslateInput(self.bottom_block, shift=(0,-1)) + h.execute(goup.dataGenerator(), ticks=steps-1) + + #TODO test imagination + #do three steps of block starting left and moving right + h.execute(dataGenerator=goright.dataGenerator(), ticks=3, + learning=False) + + #imagine 9 more steps +# for _ in xrange(10): +# h.imagineNext() + + #downstream the last step to project back into the input, + #see if you have a block that is on the right side + h._imagineStimulate(h.columns) + allStimulation = [cell.stimulation for row in h._inputCells for cell in row] + maxStim = max(allStimulation) + + white = (255,255,255) + black = (0,0,0) + percentSynapsesForActivation = float(SEGMENT_ACTIVATION_THRESHOLD)/SYNAPSES_PER_SEGMENT + def stimToRGB(stim): + percentStimulated = stim/maxStim + activated = percentStimulated >= percentSynapsesForActivation + if activated: + return (255,int(percentStimulated*255),255) + else: + return (0,int(percentStimulated*255),0) + + img = ImageBuilder([h.width, h.length], stimToRGB) + img.setData(allStimulation) + img.show() + +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.testInit'] + unittest.main() From 4bd381b5affbf1bb9e3fd17848701a40cd848668 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Mon, 28 Mar 2011 15:39:45 -0400 Subject: [PATCH 04/39] fix shift so that it's moving the right direction --- src/carver/tests/recognition_temporal.py | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index d68827e..3170347 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -90,20 +90,20 @@ def testTemporalTest(self): h.initialize_input(self.left_block) #show a whole left->right pass, 5 times - steps = 14*5*10 - goright = TranslateInput(self.left_block, shift=(1,0)) + steps = 14*5 + goright = TranslateInput(self.left_block, shift=(0,1)) h.execute(goright.dataGenerator(), ticks=steps-1) #show a whole right->left pass, 5 times - goleft = TranslateInput(self.right_block, shift=(-1,0)) + goleft = TranslateInput(self.right_block, shift=(0,-1)) h.execute(goleft.dataGenerator(), ticks=steps-1) #show a whole top->bottom pass, 5 times - godown = TranslateInput(self.top_block, shift=(0,1)) + godown = TranslateInput(self.top_block, shift=(1,0)) h.execute(godown.dataGenerator(), ticks=steps-1) #show a whole bottom->top pass, 5 times - goup = TranslateInput(self.bottom_block, shift=(0,-1)) + goup = TranslateInput(self.bottom_block, shift=(-1,0)) h.execute(goup.dataGenerator(), ticks=steps-1) #TODO test imagination @@ -112,25 +112,25 @@ def testTemporalTest(self): learning=False) #imagine 9 more steps -# for _ in xrange(10): +# for _ in xrange(3): # h.imagineNext() #downstream the last step to project back into the input, #see if you have a block that is on the right side h._imagineStimulate(h.columns) - allStimulation = [cell.stimulation for row in h._inputCells for cell in row] - maxStim = max(allStimulation) + allStimulation = [(cell.stimulation, cell.wasActive) for row in h._inputCells for cell in row] + maxStim = max(allStimulation)[0] white = (255,255,255) black = (0,0,0) percentSynapsesForActivation = float(SEGMENT_ACTIVATION_THRESHOLD)/SYNAPSES_PER_SEGMENT - def stimToRGB(stim): + def stimToRGB(cellTuple): + (stim, active) = cellTuple percentStimulated = stim/maxStim - activated = percentStimulated >= percentSynapsesForActivation - if activated: - return (255,int(percentStimulated*255),255) - else: - return (0,int(percentStimulated*255),0) + red = 255 if active else 0 + green = int(percentStimulated*255) + blue = 255 if percentStimulated >= percentSynapsesForActivation else 0 + return (red, green, blue) img = ImageBuilder([h.width, h.length], stimToRGB) img.setData(allStimulation) From 8e2198efc2c0d5b00cd59d9815e01a4473756a81 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Mon, 28 Mar 2011 18:07:24 -0400 Subject: [PATCH 05/39] only imagine the immediate next step --- src/carver/htm/__init__.py | 2 +- src/carver/htm/column.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/carver/htm/__init__.py b/src/carver/htm/__init__.py index 71c03b9..2e7bb62 100644 --- a/src/carver/htm/__init__.py +++ b/src/carver/htm/__init__.py @@ -94,7 +94,7 @@ def imagineNext(self): def _imagineStimulate(cls, columns): 'testable step one of imagineNext' for col in columns: - if col.predicting: + if col.predictingNext: down_scale = len(col.synapsesConnected) activityPerSynapse = float(1) / down_scale diff --git a/src/carver/htm/column.py b/src/carver/htm/column.py index 1f92aa1..25023a7 100644 --- a/src/carver/htm/column.py +++ b/src/carver/htm/column.py @@ -131,9 +131,10 @@ def kth_neighbor(self, k): return allNeighbors[index] @property - def predicting(self): - for cell in self.cells: - if cell.predicting: + def predictingNext(self): + 'is this column expected to get excited next?' + for segment in self.cells.segments: + if segment.nextStep and segment.active: return True return False From 8e84b711d53e82a1cb626cf5e2be0b5bbd5b2243 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Mon, 28 Mar 2011 18:13:33 -0400 Subject: [PATCH 06/39] bugfix when looking to see if any columns cells are predicting --- src/carver/htm/column.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/carver/htm/column.py b/src/carver/htm/column.py index 25023a7..cb3b7a5 100644 --- a/src/carver/htm/column.py +++ b/src/carver/htm/column.py @@ -133,9 +133,10 @@ def kth_neighbor(self, k): @property def predictingNext(self): 'is this column expected to get excited next?' - for segment in self.cells.segments: - if segment.nextStep and segment.active: - return True + for cell in self.cells: + for segment in cell.segments: + if segment.nextStep and segment.active: + return True return False def __eq__(self, another): From 448106d8ae735082d9e279700006e6ee8d50a4b9 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Mon, 28 Mar 2011 18:50:47 -0400 Subject: [PATCH 07/39] show previous input and imagined activation in separate images --- src/carver/htm/io/image_builder.py | 4 ++++ src/carver/tests/recognition_temporal.py | 16 +++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/carver/htm/io/image_builder.py b/src/carver/htm/io/image_builder.py index 32a8f50..92f62a4 100644 --- a/src/carver/htm/io/image_builder.py +++ b/src/carver/htm/io/image_builder.py @@ -51,3 +51,7 @@ def cellActiveBW(cls, cell): return (255,255,255) else: return (0,0,0) + + @classmethod + def showNow(cls, htm): + cls(htm).show() diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 3170347..1670a28 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -9,7 +9,7 @@ from carver.htm.io.objectrecognize import ObjectRecognize from carver.htm.io.translate_input import TranslateInput from PIL import Image -from carver.htm.io.image_builder import ImageBuilder +from carver.htm.io.image_builder import ImageBuilder, InputCellsDisplay from carver.htm.segment import SEGMENT_ACTIVATION_THRESHOLD from carver.htm.synapse import SYNAPSES_PER_SEGMENT @@ -111,6 +111,8 @@ def testTemporalTest(self): h.execute(dataGenerator=goright.dataGenerator(), ticks=3, learning=False) + InputCellsDisplay.showNow(h) + #imagine 9 more steps # for _ in xrange(3): # h.imagineNext() @@ -118,18 +120,18 @@ def testTemporalTest(self): #downstream the last step to project back into the input, #see if you have a block that is on the right side h._imagineStimulate(h.columns) - allStimulation = [(cell.stimulation, cell.wasActive) for row in h._inputCells for cell in row] - maxStim = max(allStimulation)[0] + allStimulation = [cell.stimulation for row in h._inputCells for cell in row] + maxStim = max(allStimulation) white = (255,255,255) black = (0,0,0) percentSynapsesForActivation = float(SEGMENT_ACTIVATION_THRESHOLD)/SYNAPSES_PER_SEGMENT - def stimToRGB(cellTuple): - (stim, active) = cellTuple + def stimToRGB(stim): percentStimulated = stim/maxStim - red = 255 if active else 0 + triggered = percentStimulated >= percentSynapsesForActivation + red = 255 if triggered else 0 green = int(percentStimulated*255) - blue = 255 if percentStimulated >= percentSynapsesForActivation else 0 + blue = 255 if triggered else 0 return (red, green, blue) img = ImageBuilder([h.width, h.length], stimToRGB) From db0766ab4749e99a28ef0321820081488c3cfe6b Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 00:26:58 -0400 Subject: [PATCH 08/39] show better information about columns during temporal recognition --- src/carver/htm/io/image_builder.py | 6 +++++- src/carver/tests/recognition_temporal.py | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/carver/htm/io/image_builder.py b/src/carver/htm/io/image_builder.py index e65ed98..be4e894 100644 --- a/src/carver/htm/io/image_builder.py +++ b/src/carver/htm/io/image_builder.py @@ -51,8 +51,12 @@ def showNow(cls, htm): @classmethod def colStateColor(cls, column): - if column.active: + if column.active and column.predictedNext: #correct return (0,255,0) + elif column.active: #false negative + return (255,0,0) + elif column.predictedNext: #false positive + return (180,0,180) #purple else: return (0,0,0) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 1670a28..16f6114 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -9,7 +9,8 @@ from carver.htm.io.objectrecognize import ObjectRecognize from carver.htm.io.translate_input import TranslateInput from PIL import Image -from carver.htm.io.image_builder import ImageBuilder, InputCellsDisplay +from carver.htm.io.image_builder import ImageBuilder, InputCellsDisplay,\ + ColumnDisplay from carver.htm.segment import SEGMENT_ACTIVATION_THRESHOLD from carver.htm.synapse import SYNAPSES_PER_SEGMENT @@ -109,7 +110,7 @@ def testTemporalTest(self): #TODO test imagination #do three steps of block starting left and moving right h.execute(dataGenerator=goright.dataGenerator(), ticks=3, - learning=False) + learning=False, postTick=ColumnDisplay.showNow) InputCellsDisplay.showNow(h) From fd0786cc18d4eb436564eb9fd3a28ae6349a46c1 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 01:54:13 -0400 Subject: [PATCH 09/39] merge from master --- src/carver/htm/__init__.py | 19 ++++++++++++++++++- src/carver/htm/cell.py | 23 +++++++++++++++++++++-- src/carver/htm/column.py | 24 +++++++++++++++++++++--- src/htm.default.properties | 2 +- src/numenta/htm.py | 2 +- 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/src/carver/htm/__init__.py b/src/carver/htm/__init__.py index 2e7bb62..93d3ba5 100644 --- a/src/carver/htm/__init__.py +++ b/src/carver/htm/__init__.py @@ -150,12 +150,29 @@ def __executeOne(self, learning): from numenta.htm import pool_spatial, pool_temporal for cell in self.cells: - cell.clockTick() + cell.clockTick() pool_spatial(self) self._updateSegments = pool_temporal(self, self._updateSegments, learning=True) + #non-Numenta optimization: + #track whether cell is predicted next + #penalize near segments for failing immediately + for cell in self.cells: + penalize = not cell.active and cell.predictedNext + + #mark prediction of immediate next step + for segment in cell.segmentsNear: + if segment.active: + cell.predictingNext = True + + if penalize: + segment.adapt_down() + while segment in self._updateSegments[cell]: + self._updateSegments[cell].remove(segment) + + def updateMatrix(self, newData): for x in xrange(len(newData)): for y in xrange(len(newData[x])): diff --git a/src/carver/htm/cell.py b/src/carver/htm/cell.py index a38afc2..0fc8ed3 100644 --- a/src/carver/htm/cell.py +++ b/src/carver/htm/cell.py @@ -26,6 +26,8 @@ def __init__(self): self.__predicted = False #read-only self.learning = False self.__wasLearning = False #read-only + self.predictingNext = False + self.__predictedNext = False #read-only self.segments = [Segment() for i in xrange(SEGMENTS_PER_CELL)] @@ -41,12 +43,29 @@ def wasLearning(self): def predicted(self): return self.__predicted + @property + def predictedNext(self): + return self.__predictedNext + + @property + def segmentsNear(self): + return self.__segmentsFilterNextStep(True) + + @property + def segmentsFar(self): + return self.__segmentsFilterNextStep(False) + + def __segmentsFilterNextStep(self, nextStep): + return filter(lambda seg: seg.nextStep == nextStep, self.segments) + def clockTick(self): self.__predicted = self.predicting self.__wasActive = self.active self.__wasLearning = self.learning + self.__predictedNext = self.predictingNext self.predicting = False + self.predictingNext = False self.active = False self.learning = False @@ -92,9 +111,9 @@ def __createSynapses(self, segment, cells, maxSynapses, filterFunc): def __hash__(self): return 1 #TODO: make hashable - def activeSegment(self): + def activeSegmentNear(self): 'prefer distal, return hits from segments connected to other cells that were active' - for seg in self.segments: + for seg in self.segmentsNear: if seg.active: return seg diff --git a/src/carver/htm/column.py b/src/carver/htm/column.py index 56d6998..441044f 100644 --- a/src/carver/htm/column.py +++ b/src/carver/htm/column.py @@ -133,12 +133,30 @@ def kth_neighbor(self, k): index = min(k-1,len(allNeighbors)-1) return allNeighbors[index] + @property + def predicting(self): + for cell in self.cells: + if cell.predicting: + return True + return False + + @property + def predictedNext(self): + 'was this column expected to get excited next?' + for cell in self.cells: + if cell.predictedNext: + return True + return False + @property def predictingNext(self): - 'is this column expected to get excited next?' + ''' + is this column expected to get excited next? + @requires: cells' active state is already set + ''' for cell in self.cells: - for segment in cell.segments: - if segment.nextStep and segment.active: + for seg in cell.segmentsNear: + if seg.activeNext: return True return False diff --git a/src/htm.default.properties b/src/htm.default.properties index a9370ea..b589a7d 100644 --- a/src/htm.default.properties +++ b/src/htm.default.properties @@ -8,7 +8,7 @@ input_bias_std_dev = 0.25 #std_dev as a percentage of the whole input [constants] -desiredLocalActivity = 10 +desiredLocalActivity = 3 #how many synapses must fire on a segment for it to even be considered for learning min_synapses_per_segment_threshold = 8 diff --git a/src/numenta/htm.py b/src/numenta/htm.py index d6c0875..647fae2 100644 --- a/src/numenta/htm.py +++ b/src/numenta/htm.py @@ -106,7 +106,7 @@ def _temporal_phase1(htm, learning, updateSegments): learningCellChosen = False for cell in col.cells: if cell.predicted: - seg = cell.activeSegment() + seg = cell.activeSegmentNear() #distal dendrite segments = sequence memory if seg and seg.distal: From 74d3c4928c1bb3bfb04a0bbd3f7b6bed06b4373a Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 01:54:36 -0400 Subject: [PATCH 10/39] predict next step more accurately during imagination --- src/carver/htm/segment.py | 15 +++++++++++++++ src/carver/htm/synapse.py | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/src/carver/htm/segment.py b/src/carver/htm/segment.py index d5f86d0..7bef7f4 100644 --- a/src/carver/htm/segment.py +++ b/src/carver/htm/segment.py @@ -43,6 +43,14 @@ def synapses_firing(self, requireConnection=True): ''' return filter(lambda synapse: synapse.is_firing(requireConnection=requireConnection), self.synapses) + + def synapses_will_fire(self, requireConnection=True): + ''' + @param requireConnection: only include synapse if the synapse is connected + @return an iterable of firing synapses + ''' + return filter(lambda synapse: synapse.will_fire(requireConnection=requireConnection), + self.synapses) def increase_permanences(self, byAmount): 'increase permanence on all synapses' @@ -63,6 +71,13 @@ def active(self): ''' return len(self.synapses_firing()) >= SEGMENT_ACTIVATION_THRESHOLD + @property + def activeNext(self): + ''' + Will the segment fire? Based on current cell active status + ''' + return len(self.synapses_will_fire()) >= SEGMENT_ACTIVATION_THRESHOLD + @property def activeFromLearningCells(self): learningSynapses = filter(lambda synapse: synapse.is_firing() and synapse.isInputLearning, diff --git a/src/carver/htm/synapse.py b/src/carver/htm/synapse.py index 279c19e..f14ecd8 100644 --- a/src/carver/htm/synapse.py +++ b/src/carver/htm/synapse.py @@ -38,6 +38,12 @@ def is_firing(self, requireConnection=True): ''' return self.input.wasActive and (self.connected or not requireConnection) + def will_fire(self, requireConnection=True): + ''' + Will input fire? Only valid for distal segments to other htm cells + ''' + return self.input.active and (self.connected or not requireConnection) + def isInputLearning(self): if not hasattr(input, 'learning'): return False From 4deb6908718a8a9a14267ee31ce4acf6d6978bbf Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 03:53:49 -0400 Subject: [PATCH 11/39] merge cleanup --- src/carver/htm/__init__.py | 17 ----------------- src/carver/htm/column.py | 8 -------- 2 files changed, 25 deletions(-) diff --git a/src/carver/htm/__init__.py b/src/carver/htm/__init__.py index d24244d..87ad27d 100644 --- a/src/carver/htm/__init__.py +++ b/src/carver/htm/__init__.py @@ -175,23 +175,6 @@ def __executeOne(self, learning): self._updateSegments[cell].remove(segment) - #non-Numenta optimization: - #track whether cell is predicted next - #penalize near segments for failing immediately - for cell in self.cells: - penalize = not cell.active and cell.predictedNext - - #mark prediction of immediate next step - for segment in cell.segmentsNear: - if segment.active: - cell.predictingNext = True - - if penalize: - segment.adapt_down() - while segment in self._updateSegments[cell]: - self._updateSegments[cell].remove(segment) - - def updateMatrix(self, newData): for x in xrange(len(newData)): for y in xrange(len(newData[x])): diff --git a/src/carver/htm/column.py b/src/carver/htm/column.py index 4cf996c..61cc912 100644 --- a/src/carver/htm/column.py +++ b/src/carver/htm/column.py @@ -148,14 +148,6 @@ def predictedNext(self): return True return False - @property - def predictedNext(self): - 'was this column expected to get excited next?' - for cell in self.cells: - if cell.predictedNext: - return True - return False - @property def predictingNext(self): ''' From 67e041cccc5052a25c865c0c73928d3605e67c12 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 03:54:07 -0400 Subject: [PATCH 12/39] cache the predictingNext value to let it be set manually or calculated --- src/carver/htm/cell.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/carver/htm/cell.py b/src/carver/htm/cell.py index 0fc8ed3..273fe67 100644 --- a/src/carver/htm/cell.py +++ b/src/carver/htm/cell.py @@ -26,7 +26,7 @@ def __init__(self): self.__predicted = False #read-only self.learning = False self.__wasLearning = False #read-only - self.predictingNext = False + self.__predictingNext = None #cached-val self.__predictedNext = False #read-only self.segments = [Segment() for i in xrange(SEGMENTS_PER_CELL)] @@ -55,6 +55,24 @@ def segmentsNear(self): def segmentsFar(self): return self.__segmentsFilterNextStep(False) + @property + def predictingNext(self): + if self.__predictingNext is not None: + return self.__predictingNext + + cache = False + for segment in self.segmentsNear: + if segment.active: + cache = True + break + + self.__predictingNext = cache + return self.__predictingNext + + @predictingNext.setter + def predictingNext(self, value): + self.__predictingNext = value + def __segmentsFilterNextStep(self, nextStep): return filter(lambda seg: seg.nextStep == nextStep, self.segments) From aa65cbc8926b2285b6603650c0f8dc9db0f6fdb4 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 04:11:09 -0400 Subject: [PATCH 13/39] fix stuck cell state cache --- src/carver/htm/cell.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/carver/htm/cell.py b/src/carver/htm/cell.py index 273fe67..b902ca9 100644 --- a/src/carver/htm/cell.py +++ b/src/carver/htm/cell.py @@ -26,7 +26,7 @@ def __init__(self): self.__predicted = False #read-only self.learning = False self.__wasLearning = False #read-only - self.__predictingNext = None #cached-val + self.predictingNext = None #cached-val self.__predictedNext = False #read-only self.segments = [Segment() for i in xrange(SEGMENTS_PER_CELL)] @@ -83,7 +83,7 @@ def clockTick(self): self.__predictedNext = self.predictingNext self.predicting = False - self.predictingNext = False + self.predictingNext = None self.active = False self.learning = False From 6c37fd5f1c641ec901d4a30dfa0aa6875ba9317f Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 04:49:51 -0400 Subject: [PATCH 14/39] hide more image generation in recognition_temporal.py --- src/carver/tests/recognition_temporal.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 16f6114..e2bdee2 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -110,13 +110,15 @@ def testTemporalTest(self): #TODO test imagination #do three steps of block starting left and moving right h.execute(dataGenerator=goright.dataGenerator(), ticks=3, - learning=False, postTick=ColumnDisplay.showNow) + learning=False) #postTick=ColumnDisplay.showNow InputCellsDisplay.showNow(h) #imagine 9 more steps -# for _ in xrange(3): +# for _ in xrange(9): # h.imagineNext() +# +# InputCellsDisplay.showNow(h) #downstream the last step to project back into the input, #see if you have a block that is on the right side From 58fe38ad333958f6af72c0f090bd182bbf5f6c14 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 05:27:46 -0400 Subject: [PATCH 15/39] add clarifying comments --- src/carver/tests/recognition_temporal.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index e2bdee2..a3b1e66 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -107,10 +107,12 @@ def testTemporalTest(self): goup = TranslateInput(self.bottom_block, shift=(-1,0)) h.execute(goup.dataGenerator(), ticks=steps-1) - #TODO test imagination + #TODO: test imagination automaticall + #do three steps of block starting left and moving right h.execute(dataGenerator=goright.dataGenerator(), ticks=3, - learning=False) #postTick=ColumnDisplay.showNow + learning=False, postTick=ColumnDisplay.showNow) + #the displays here should be mostly green and black, but a bit of purple and red is ok InputCellsDisplay.showNow(h) From 2656b10624386826a3ebd13a90be0ce5fc6349a9 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 05:31:43 -0400 Subject: [PATCH 16/39] ignore local config file --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 43c28e7..ef90bb9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ .project .pydevproject -.settings/* \ No newline at end of file +.settings/* +src/htm.properties + +*.pyc \ No newline at end of file From 40aab334f52e361d38531f642f2f5b2417942ce6 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 06:21:30 -0400 Subject: [PATCH 17/39] refactor imagination/stimulation in HTM --- src/carver/htm/__init__.py | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/carver/htm/__init__.py b/src/carver/htm/__init__.py index 7b125b1..2957bf4 100644 --- a/src/carver/htm/__init__.py +++ b/src/carver/htm/__init__.py @@ -92,33 +92,31 @@ def imagineNext(self): self._imagineStimulate(self.columns) self._imagineOverride(self._inputCells) self.__executeOne(False) - + @classmethod - def _imagineStimulate(cls, columns): - 'testable step one of imagineNext' + def stimulateFromColumns(cls, columns, columnFilter): for col in columns: - if col.predictingNext: + if columnFilter(col): down_scale = len(col.synapsesConnected) activityPerSynapse = float(1) / down_scale for synapse in col.synapsesConnected: synapse.input.stimulate(activityPerSynapse) + + @classmethod + def _imagineStimulate(cls, columns): + 'testable step one of imagineNext' + cls.stimulateFromColumns(columns, lambda col: col.predictingNext) @classmethod def _imagineOverride(cls, inputCells): 'testable step two of imagineNext' - #flatten cell matrix - allInputs = [] + cls.normalize_input_stimulation(inputCells) + for row in inputCells: for cell in row: - allInputs.append(cell) - - maxStim = max(map(lambda inCell: inCell.stimulation, allInputs)) - if maxStim: - for inCell in allInputs: - inCell.stimulation /= maxStim - inCell.override() + cell.override() def executeOnce(self, data, learning=True, postTick=None): ''' @@ -242,6 +240,18 @@ def average_receptive_field_size(self): for syn in c.synapsesConnected: radii.append(((c.x-syn.input.x)**2 + (c.y-syn.input.y)**2)**0.5) return sum(radii)/len(radii) + + @classmethod + def _max_input_stimulation(cls, inputCells): + return max(max(map(lambda cell: cell.stimulation, inputCells))) + + @classmethod + def normalize_input_stimulation(cls, inputCells): + maxStim = cls._max_input_stimulation(inputCells) + if maxStim: + for row in inputCells: + for cell in row: + cell.stimulation /= maxStim class UpdateSegments(DictDefault): From 930ef9f4a3f76e81df50d42b764698bebe6f441c Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Tue, 29 Mar 2011 06:45:16 -0400 Subject: [PATCH 18/39] convenience function to show input activation vs column stimulation for spatial column activation pattern --- src/carver/htm/io/image_builder.py | 63 +++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/src/carver/htm/io/image_builder.py b/src/carver/htm/io/image_builder.py index be4e894..05b28d7 100644 --- a/src/carver/htm/io/image_builder.py +++ b/src/carver/htm/io/image_builder.py @@ -5,6 +5,11 @@ ''' from PIL import Image +from carver.htm import HTM +from carver.htm.synapse import SYNAPSES_PER_SEGMENT +from carver.htm.segment import SEGMENT_ACTIVATION_THRESHOLD + +percentSynapsesForActivation = float(SEGMENT_ACTIVATION_THRESHOLD)/SYNAPSES_PER_SEGMENT class ImageBuilder(object): ''' @@ -35,19 +40,22 @@ def setData(self, data): def show(self): return self.img.show() -class ColumnDisplay(object): - def __init__(self, htm): - width = len(htm._column_grid) - length = len(htm._column_grid[0]) - self.imageBuilder = ImageBuilder((width, length), self.colStateColor) - self.imageBuilder.setData(htm.columns) +class HTMDisplayBase(object): def show(self): return self.imageBuilder.show() - + @classmethod def showNow(cls, htm): cls(htm).show() + + +class ColumnDisplay(HTMDisplayBase): + def __init__(self, htm): + width = len(htm._column_grid) + length = len(htm._column_grid[0]) + self.imageBuilder = ImageBuilder((width, length), self.colStateColor) + self.imageBuilder.setData(htm.columns) @classmethod def colStateColor(cls, column): @@ -60,16 +68,45 @@ def colStateColor(cls, column): else: return (0,0,0) +class InputReflectionOverlayDisplay(HTMDisplayBase): + 'show the input cells, and the column activation pushed back onto the input space' + def __init__(self, htm): + self.imageBuilder = ImageBuilder((htm.width, htm.length), self.inputOverlay) + + HTM.stimulateFromColumns(htm.columns, lambda col: col.active) + HTM.normalize_input_stimulation(htm._inputCells) + + data = [(cell, cell.stimulation) for row in htm._inputCells for cell in row] + + for row in htm._inputCells: + for cell in row: + cell.resetStimulation() + + self.imageBuilder.setData(data) + + @classmethod + def inputOverlay(cls, cellInfo): + (cell, percentStimulated) = cellInfo + + triggered = percentStimulated >= percentSynapsesForActivation + + if cell.wasActive and triggered: #correct + return (0,int(percentStimulated*255),0) + elif cell.wasActive: #false negative + return (int(percentStimulated*255),0,0) + elif triggered: #false positive + return (int(percentStimulated*180),0,int(percentStimulated*180)) #purple + else: + gray = int(percentStimulated*255) + return (gray,gray,gray) + -class InputCellsDisplay(object): +class InputCellsDisplay(HTMDisplayBase): def __init__(self, htm): self.imageBuilder = ImageBuilder((htm.width, htm.length), self.cellActiveBW) data = [cell for row in htm._inputCells for cell in row] self.imageBuilder.setData(data) - def show(self): - return self.imageBuilder.show() - @classmethod def cellActiveBW(cls, cell): 'A black and white representation of whether a cell is active' @@ -77,7 +114,3 @@ def cellActiveBW(cls, cell): return (255,255,255) else: return (0,0,0) - - @classmethod - def showNow(cls, htm): - cls(htm).show() From bfc2811d15d65380881e62939bd73a4d6970c085 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 09:09:17 -0400 Subject: [PATCH 19/39] name/comment clarify --- src/carver/tests/recognition_temporal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 4e57f1b..b4ce768 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -86,7 +86,7 @@ def setUp(self): def tearDown(self): pass - def testTemporalTest(self): + def testTemporalImagination(self): h = HTM(cellsPerColumn=3) h.initialize_input(self.left_block) @@ -107,7 +107,7 @@ def testTemporalTest(self): goup = TranslateInput(self.bottom_block, shift=(-1,0)) h.execute(goup.dataGenerator(), ticks=steps-1) - #TODO: test imagination automaticall + #TODO: test imagination automatically #do three steps of block starting left and moving right h.execute(dataGenerator=goright.dataGenerator(), ticks=3, From df8612de3855551b29baf5255b5e8b2d8f6e3c00 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 09:25:36 -0400 Subject: [PATCH 20/39] last imagination run would have been more effective if the cutoff were higher --- src/carver/tests/recognition_temporal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index b4ce768..c9168d0 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -130,7 +130,7 @@ def testTemporalImagination(self): white = (255,255,255) black = (0,0,0) - percentSynapsesForActivation = float(SEGMENT_ACTIVATION_THRESHOLD)/SYNAPSES_PER_SEGMENT + percentSynapsesForActivation = 2*float(SEGMENT_ACTIVATION_THRESHOLD)/SYNAPSES_PER_SEGMENT def stimToRGB(stim): percentStimulated = stim/maxStim triggered = percentStimulated >= percentSynapsesForActivation From 630fe92cef24ff60a9ac1f5eba06475b8929bbbf Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 09:29:16 -0400 Subject: [PATCH 21/39] try higher compression, fails test --- src/carver/tests/recognition_temporal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index c9168d0..8ce5f01 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -88,7 +88,7 @@ def tearDown(self): def testTemporalImagination(self): h = HTM(cellsPerColumn=3) - h.initialize_input(self.left_block) + h.initialize_input(self.left_block, compressionFactor=2.8) #show a whole left->right pass, 5 times steps = 14*5 From 46ed5ebf6f5372ced7df2f1f9a4bfd7a0ef194a2 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 09:35:31 -0400 Subject: [PATCH 22/39] bugfix: input display would crash when htm was compressed --- src/carver/htm/io/image_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/carver/htm/io/image_builder.py b/src/carver/htm/io/image_builder.py index 05b28d7..2839081 100644 --- a/src/carver/htm/io/image_builder.py +++ b/src/carver/htm/io/image_builder.py @@ -71,7 +71,7 @@ def colStateColor(cls, column): class InputReflectionOverlayDisplay(HTMDisplayBase): 'show the input cells, and the column activation pushed back onto the input space' def __init__(self, htm): - self.imageBuilder = ImageBuilder((htm.width, htm.length), self.inputOverlay) + self.imageBuilder = ImageBuilder((htm.inputWidth, htm.inputLength), self.inputOverlay) HTM.stimulateFromColumns(htm.columns, lambda col: col.active) HTM.normalize_input_stimulation(htm._inputCells) From 932c6ab0f2e4c8309b7d839d64f8c098b9f333b7 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 09:38:05 -0400 Subject: [PATCH 23/39] show red when input is not expected in display, or almost black if it was mostly expected --- src/carver/htm/io/image_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/carver/htm/io/image_builder.py b/src/carver/htm/io/image_builder.py index 2839081..662097e 100644 --- a/src/carver/htm/io/image_builder.py +++ b/src/carver/htm/io/image_builder.py @@ -93,7 +93,7 @@ def inputOverlay(cls, cellInfo): if cell.wasActive and triggered: #correct return (0,int(percentStimulated*255),0) elif cell.wasActive: #false negative - return (int(percentStimulated*255),0,0) + return (255-int(percentStimulated*255),0,0) elif triggered: #false positive return (int(percentStimulated*180),0,int(percentStimulated*180)) #purple else: From f5d4924813044dd28fa3e2018c8fe93e895529e7 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 09:50:04 -0400 Subject: [PATCH 24/39] another input vs htm size bugfix --- src/carver/htm/io/image_builder.py | 2 +- src/carver/tests/recognition_temporal.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/carver/htm/io/image_builder.py b/src/carver/htm/io/image_builder.py index 662097e..14ffe8c 100644 --- a/src/carver/htm/io/image_builder.py +++ b/src/carver/htm/io/image_builder.py @@ -103,7 +103,7 @@ def inputOverlay(cls, cellInfo): class InputCellsDisplay(HTMDisplayBase): def __init__(self, htm): - self.imageBuilder = ImageBuilder((htm.width, htm.length), self.cellActiveBW) + self.imageBuilder = ImageBuilder((htm.inputWidth, htm.inputLength), self.cellActiveBW) data = [cell for row in htm._inputCells for cell in row] self.imageBuilder.setData(data) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 8ce5f01..93fb1b4 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -139,7 +139,7 @@ def stimToRGB(stim): blue = 255 if triggered else 0 return (red, green, blue) - img = ImageBuilder([h.width, h.length], stimToRGB) + img = ImageBuilder([h.inputWidth, h.inputLength], stimToRGB) img.setData(allStimulation) img.show() From 15deb9e536b575edd8c9eec61a69e3c6c0bfd53d Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 11:32:21 -0400 Subject: [PATCH 25/39] test smaller network to debug temporal pooler --- src/carver/tests/recognition_temporal.py | 38 +++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 93fb1b4..7b5ef37 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -85,8 +85,44 @@ def setUp(self): def tearDown(self): pass + + def testToyTemporalSetup(self): + data = [ + [1,0], + [0,0], + ] + h = HTM(cellsPerColumn=3) + h.initialize_input(data) + + rowflip = TranslateInput(data, shift=(1,0)) + colflip = TranslateInput(data, shift=(0,1)) + + h.execute(rowflip.dataGenerator(), ticks=10) + h.execute(rowflip.dataGenerator(), ticks=10) + h.execute(colflip.dataGenerator(), ticks=20) + + def printCellActive(htm): + print "cell activity:" + for i, col in enumerate(htm.columns): + print ( + "column %s:" % i, + ' '.join(map(lambda c: '1' if c.active else '0', col.cells)) + ) + + h.execute(rowflip.dataGenerator(), ticks=4, learning=False, + postTick=printCellActive) + + #InputCellsDisplay.showNow(h) + + #imagine next step + h._imagineStimulate(h.columns) + print "stimulation:" + for row in h._inputCells: + print ' '.join(map(lambda cell: '%.2f' % cell.stimulation, row)) + + - def testTemporalImagination(self): + def _testTemporalImagination(self): h = HTM(cellsPerColumn=3) h.initialize_input(self.left_block, compressionFactor=2.8) From 5d61f03ddd6ed8688a2b7d0e3796045a4ef5bca2 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 12:46:04 -0400 Subject: [PATCH 26/39] continue learning while showing output, for step-through debugging --- src/carver/tests/recognition_temporal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 7b5ef37..4c52c03 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -109,7 +109,7 @@ def printCellActive(htm): ' '.join(map(lambda c: '1' if c.active else '0', col.cells)) ) - h.execute(rowflip.dataGenerator(), ticks=4, learning=False, + h.execute(rowflip.dataGenerator(), ticks=4, learning=True, postTick=printCellActive) #InputCellsDisplay.showNow(h) From e68897b288f027b8735f3a55322aefffa2097dce Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 15:25:08 -0400 Subject: [PATCH 27/39] fix many of the segment threshold updates in imagination branch --- src/carver/htm/input.py | 6 ++---- src/carver/htm/io/image_builder.py | 6 ++---- src/carver/tests/recognition_temporal.py | 4 ++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/carver/htm/input.py b/src/carver/htm/input.py index 9bcc053..fcd0bb5 100644 --- a/src/carver/htm/input.py +++ b/src/carver/htm/input.py @@ -4,7 +4,7 @@ @author: Jason Carver ''' from carver.htm.synapse import SYNAPSES_PER_SEGMENT -from carver.htm.segment import SEGMENT_ACTIVATION_THRESHOLD +from carver.htm.segment import FRACTION_SEGMENT_ACTIVATION_THRESHOLD class InputCell(object): ''' @@ -48,9 +48,7 @@ def stimulate(self, amount): def override(self): self.overrideInput = True - percentSynapsesForActivation = float(SEGMENT_ACTIVATION_THRESHOLD)/SYNAPSES_PER_SEGMENT - - if self.stimulation >= percentSynapsesForActivation: + if self.stimulation >= FRACTION_SEGMENT_ACTIVATION_THRESHOLD: self.stimulationPast = 1 else: self.stimulationPast = 0 diff --git a/src/carver/htm/io/image_builder.py b/src/carver/htm/io/image_builder.py index 14ffe8c..48d466e 100644 --- a/src/carver/htm/io/image_builder.py +++ b/src/carver/htm/io/image_builder.py @@ -7,9 +7,7 @@ from PIL import Image from carver.htm import HTM from carver.htm.synapse import SYNAPSES_PER_SEGMENT -from carver.htm.segment import SEGMENT_ACTIVATION_THRESHOLD - -percentSynapsesForActivation = float(SEGMENT_ACTIVATION_THRESHOLD)/SYNAPSES_PER_SEGMENT +from carver.htm.segment import FRACTION_SEGMENT_ACTIVATION_THRESHOLD class ImageBuilder(object): ''' @@ -88,7 +86,7 @@ def __init__(self, htm): def inputOverlay(cls, cellInfo): (cell, percentStimulated) = cellInfo - triggered = percentStimulated >= percentSynapsesForActivation + triggered = percentStimulated >= FRACTION_SEGMENT_ACTIVATION_THRESHOLD if cell.wasActive and triggered: #correct return (0,int(percentStimulated*255),0) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 4c52c03..62c3a65 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -11,8 +11,8 @@ from PIL import Image from carver.htm.io.image_builder import ImageBuilder, InputCellsDisplay,\ ColumnDisplay, InputReflectionOverlayDisplay -from carver.htm.segment import SEGMENT_ACTIVATION_THRESHOLD from carver.htm.synapse import SYNAPSES_PER_SEGMENT +from carver.htm.segment import FRACTION_SEGMENT_ACTIVATION_THRESHOLD class TestRecognitionTemporal(unittest.TestCase): @@ -166,7 +166,7 @@ def _testTemporalImagination(self): white = (255,255,255) black = (0,0,0) - percentSynapsesForActivation = 2*float(SEGMENT_ACTIVATION_THRESHOLD)/SYNAPSES_PER_SEGMENT + percentSynapsesForActivation = FRACTION_SEGMENT_ACTIVATION_THRESHOLD def stimToRGB(stim): percentStimulated = stim/maxStim triggered = percentStimulated >= percentSynapsesForActivation From 36641e609aef68d25ee0df3c0c6a6b6bf8a6e6d0 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 15:30:13 -0400 Subject: [PATCH 28/39] patch up final segment threshold holdover --- src/carver/htm/segment.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/carver/htm/segment.py b/src/carver/htm/segment.py index 0e043f5..aba6620 100644 --- a/src/carver/htm/segment.py +++ b/src/carver/htm/segment.py @@ -47,12 +47,16 @@ def synapses_firing(self, requireConnection=True): return filter(lambda synapse: synapse.is_firing(requireConnection=requireConnection), self.synapses) + @classmethod + def _will_fire_next(cls, requireConnection=True): + return lambda synapse: synapse.will_fire(requireConnection=requireConnection) + def synapses_will_fire(self, requireConnection=True): ''' @param requireConnection: only include synapse if the synapse is connected @return an iterable of firing synapses ''' - return filter(lambda synapse: synapse.will_fire(requireConnection=requireConnection), + return filter(self._will_fire_next(requireConnection), self.synapses) def increase_permanences(self, byAmount): @@ -88,7 +92,8 @@ def activeNext(self): ''' Will the segment fire? Based on current cell active status ''' - return len(self.synapses_will_fire()) >= SEGMENT_ACTIVATION_THRESHOLD + filterFunc = self._will_fire_next(requireConnection=True) + return self._areSynapsesAboveThreshold(filterFunc) @property def activeFromLearningCells(self): From d6271d64be8b9be067db6c9a359b2ae7f1fa9a1d Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 19:47:30 -0400 Subject: [PATCH 29/39] refactor out imagebuilder from htm_main --- src/carver/htm/io/image_builder.py | 29 +++++++++++++++++++++++++ src/htm_main.py | 34 ++++++------------------------ 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/src/carver/htm/io/image_builder.py b/src/carver/htm/io/image_builder.py index 48d466e..4002380 100644 --- a/src/carver/htm/io/image_builder.py +++ b/src/carver/htm/io/image_builder.py @@ -8,6 +8,7 @@ from carver.htm import HTM from carver.htm.synapse import SYNAPSES_PER_SEGMENT from carver.htm.segment import FRACTION_SEGMENT_ACTIVATION_THRESHOLD +from carver.htm.ui.excite_history import ExciteHistory class ImageBuilder(object): ''' @@ -47,6 +48,34 @@ def show(self): def showNow(cls, htm): cls(htm).show() +class ActivityOverTimeDisplay(HTMDisplayBase): + def __init__(self, columnStates): + img = ImageBuilder([len(columnStates[0]), len(columnStates)], self.stateToRGB) + img.setData2D(columnStates) + img.rotate90() + self.imageBuilder = img + + def show(self): + print """*************** Graph History ************** +Y-Axis: All cells in the network, with the 4 cells per column grouped together +X-Axis: Time +Colors: +\tblack: no activity +\tgray: predicting +\twhite: active +""" + HTMDisplayBase.show(self) + + @classmethod + def stateToRGB(cls, state): + if state == ExciteHistory.ACTIVE: + return (255, 255, 255) + elif state == ExciteHistory.PREDICTING: + return (127, 127, 127) + elif state == ExciteHistory.INACTIVE: + return (0, 0, 0) + else: + return (255, 0, 0) #unknown cell/column state class ColumnDisplay(HTMDisplayBase): def __init__(self, htm): diff --git a/src/htm_main.py b/src/htm_main.py index 7c9fe0e..98ada7c 100644 --- a/src/htm_main.py +++ b/src/htm_main.py @@ -7,7 +7,7 @@ from carver.htm import HTM from carver.htm.ui.excite_history import ExciteHistory from copy import deepcopy -from carver.htm.io.image_builder import ImageBuilder +from carver.htm.io.image_builder import ImageBuilder, ActivityOverTimeDisplay def flipDataGenerator(htm): @@ -42,34 +42,12 @@ def flipDataGenerator(htm): history = ExciteHistory() htm.execute(flipDataGenerator(htm), ticks=180, postTick=history.update) - - print """*************** Graph History ************** -Y-Axis: All cells in the network, with the 4 cells per column grouped together -X-Axis: Time -Colors: -\tblack: no activity -\tgray: predicting -\twhite: active + ## Show image with history grouped by cell + ActivityOverTimeDisplay.showNow(history.data) + + print """ Notice that the network settles down very quickly at the left, but not completely. You will typically see artifacts around 100 steps in (about halfway across the image). -At each time step, the input data is flipping bits. So you will see some cells alternating at every time step, some cells that are active either way, and some cells that are never active. +At each time step, the input data is flipping bits. So you will see some cells alternating at every time step, some cells that are active either way, and some cells that are never active. """ - - ## Show image with history grouped by cell - columnStates = history.data - - def stateToRGB(state): - if state == ExciteHistory.ACTIVE: - return (255, 255, 255) - elif state == ExciteHistory.PREDICTING: - return (127, 127, 127) - elif state == ExciteHistory.INACTIVE: - return (0, 0, 0) - else: - return (255, 0, 0) #unknown cell/column state - - img = ImageBuilder([len(columnStates[0]), len(columnStates)], stateToRGB) - img.setData2D(columnStates) - img.rotate90() - img.show() From 32d1f3781058526f7c48dea33f8103990ee04bb3 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 22:43:59 -0400 Subject: [PATCH 30/39] protect against empty set when rounding out synapses --- src/carver/htm/segment.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/carver/htm/segment.py b/src/carver/htm/segment.py index 1460682..5a599bb 100644 --- a/src/carver/htm/segment.py +++ b/src/carver/htm/segment.py @@ -133,6 +133,7 @@ def round_out_synapses(self, htm): missingSynapses = MAX_NEW_SYNAPSES - len(synapses) if missingSynapses > 0: lastLearningCells = filter(lambda cell: cell.wasLearning, htm.cells) - for _ in xrange(missingSynapses): - cell = random.choice(lastLearningCells) - self.create_synapse(cell) + if len(lastLearningCells): + for _ in xrange(missingSynapses): + cell = random.choice(lastLearningCells) + self.create_synapse(cell) From 30f5c1e88eada38570131b01a1e38197b5b984ad Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 22:46:02 -0400 Subject: [PATCH 31/39] show more info in temporal recognition, plus a /0 bugfix --- src/carver/tests/recognition_temporal.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 62c3a65..f991278 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -10,7 +10,7 @@ from carver.htm.io.translate_input import TranslateInput from PIL import Image from carver.htm.io.image_builder import ImageBuilder, InputCellsDisplay,\ - ColumnDisplay, InputReflectionOverlayDisplay + ColumnDisplay, InputReflectionOverlayDisplay, ActivityOverTimeDisplay from carver.htm.synapse import SYNAPSES_PER_SEGMENT from carver.htm.segment import FRACTION_SEGMENT_ACTIVATION_THRESHOLD @@ -97,9 +97,11 @@ def testToyTemporalSetup(self): rowflip = TranslateInput(data, shift=(1,0)) colflip = TranslateInput(data, shift=(0,1)) - h.execute(rowflip.dataGenerator(), ticks=10) - h.execute(rowflip.dataGenerator(), ticks=10) - h.execute(colflip.dataGenerator(), ticks=20) + history = ExciteHistory() + h.execute(rowflip.dataGenerator(), ticks=20, postTick=history.update) + h.execute(colflip.dataGenerator(), ticks=20, postTick=history.update) + h.execute(rowflip.dataGenerator(), ticks=20, postTick=history.update) + h.execute(colflip.dataGenerator(), ticks=20, postTick=history.update) def printCellActive(htm): print "cell activity:" @@ -120,7 +122,7 @@ def printCellActive(htm): for row in h._inputCells: print ' '.join(map(lambda cell: '%.2f' % cell.stimulation, row)) - + ActivityOverTimeDisplay.showNow(history.data) def _testTemporalImagination(self): h = HTM(cellsPerColumn=3) @@ -168,7 +170,7 @@ def _testTemporalImagination(self): black = (0,0,0) percentSynapsesForActivation = FRACTION_SEGMENT_ACTIVATION_THRESHOLD def stimToRGB(stim): - percentStimulated = stim/maxStim + percentStimulated = stim/maxStim if maxStim else 0 triggered = percentStimulated >= percentSynapsesForActivation red = 255 if triggered else 0 green = int(percentStimulated*255) From 5496ad73b68054d2cea1f6a6c333e9b2b54c8f3a Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 22:47:35 -0400 Subject: [PATCH 32/39] don't filter by near synapses when choosing the learning cell --- src/carver/htm/cell.py | 7 ++++++- src/numenta/htm.py | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/carver/htm/cell.py b/src/carver/htm/cell.py index 55b7d17..5c7792b 100644 --- a/src/carver/htm/cell.py +++ b/src/carver/htm/cell.py @@ -167,7 +167,12 @@ def bestMatchingSegment(self, nextStep): ''' bestSegment = None bestSegmentSynapseCount = MIN_THRESHOLD-1 - for seg in filter(lambda seg: seg.nextStep == nextStep, self.segments): + + segments = self.segments + if nextStep: + segments = self.segmentsNear + + for seg in segments: synapseCount = len(seg.old_firing_synapses(requireConnection=False)) if synapseCount > bestSegmentSynapseCount: bestSegmentSynapseCount = synapseCount diff --git a/src/numenta/htm.py b/src/numenta/htm.py index b9f6281..62c3a99 100644 --- a/src/numenta/htm.py +++ b/src/numenta/htm.py @@ -106,7 +106,7 @@ def _temporal_phase1(htm, learning, updateSegments): learningCellChosen = False for cell in col.cells: if cell.predicted: - seg = cell.findSegmentWasActive(nextStep=True) + seg = cell.findSegmentWasActive(nextStep=False) #distal dendrite segments = sequence memory if seg and seg.distal: @@ -124,7 +124,7 @@ def _temporal_phase1(htm, learning, updateSegments): #Learning Phase 1, p41 if learning and not learningCellChosen: - cell, seg = col.bestCell(nextStep=True) + cell, seg = col.bestCell(nextStep=False) cell.learning = True if seg is None: From af38bd8931198b1c3cd4e8ca749a069c3a278fa5 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Thu, 31 Mar 2011 22:48:46 -0400 Subject: [PATCH 33/39] shorter htm_main until it runs more efficiently --- src/htm_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/htm_main.py b/src/htm_main.py index 98ada7c..7fb1795 100644 --- a/src/htm_main.py +++ b/src/htm_main.py @@ -41,7 +41,7 @@ def flipDataGenerator(htm): #track htm's data history with history = ExciteHistory() - htm.execute(flipDataGenerator(htm), ticks=180, postTick=history.update) + htm.execute(flipDataGenerator(htm), ticks=50, postTick=history.update) ## Show image with history grouped by cell ActivityOverTimeDisplay.showNow(history.data) From 6ad13fd7701244db9b0d8296736773c3aa14ac89 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Fri, 1 Apr 2011 00:17:46 -0400 Subject: [PATCH 34/39] automate looking for how many cells are lit up (finding a pattern?) --- src/carver/tests/recognition_temporal.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index f991278..0479041 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -123,6 +123,9 @@ def printCellActive(htm): print ' '.join(map(lambda cell: '%.2f' % cell.stimulation, row)) ActivityOverTimeDisplay.showNow(history.data) + + self.assertGreater(len(filter(lambda c: c.active, h.cells)), 0) + self.assertLess(len(filter(lambda c: c.active, h.cells)), 3) def _testTemporalImagination(self): h = HTM(cellsPerColumn=3) From cbb7f4805e32cfe8456b37669d4ea16e717ea9d7 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Fri, 1 Apr 2011 00:19:40 -0400 Subject: [PATCH 35/39] fix sparsity to work normally on larger ones and degrade gracefully on small one --- src/carver/htm/__init__.py | 11 ++++++++++- src/carver/htm/column.py | 6 +++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/carver/htm/__init__.py b/src/carver/htm/__init__.py index 42c448d..cad6828 100644 --- a/src/carver/htm/__init__.py +++ b/src/carver/htm/__init__.py @@ -23,8 +23,15 @@ EXTENSION_NEXT_STEP_PENALTY = config.getboolean('extensions', 'next_step_penalty') class HTM(object): + + dimensions = 2 #hard-coded for now + def __init__(self, cellsPerColumn=None): self.inhibitionRadius = config.getint('init', 'inhibitionRadius') + + impliedSparsity = float(config.getint('constants','desiredLocalActivity'))/(self.inhibitionRadius**self.dimensions) + self.impliedSparsity = min(impliedSparsity, 1.0) + if cellsPerColumn: self.cellsPerColumn = cellsPerColumn else: @@ -247,7 +254,9 @@ def average_receptive_field_size(self): radii = [] for c in self.columns: for syn in c.synapsesConnected: - radii.append(((c.x-syn.input.x)**2 + (c.y-syn.input.y)**2)**0.5) + radius = ((c.x-syn.input.x)**2 + (c.y-syn.input.y)**2)**0.5 + if radius!=0: + radii.append(radius) return sum(radii)/len(radii) @classmethod diff --git a/src/carver/htm/column.py b/src/carver/htm/column.py index dd7e1bb..0c0f3e4 100644 --- a/src/carver/htm/column.py +++ b/src/carver/htm/column.py @@ -127,13 +127,17 @@ def neighbor_duty_cycle_max(self): ''' return max((c.dutyCycleActive for c in self.neighbors)) + def __adjustKthNeighborForSparsity(self, numNeighbors): + return max(int(self.htm.impliedSparsity*numNeighbors), 1) + def kth_neighbor(self, k): ''' Numenta docs: Given the list of columns, return the kth highest overlap value ''' allNeighbors = sorted(self.neighbors, reverse=True, key=lambda col: col.overlap) - index = min(k-1,len(allNeighbors)-1) + sparserK = self.__adjustKthNeighborForSparsity(len(allNeighbors)) + index = min(k-1, sparserK-1) return allNeighbors[index] @property From ced8906fb1dbb3fc7af75b0bc3c0a710ecc3bad2 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Fri, 1 Apr 2011 00:36:50 -0400 Subject: [PATCH 36/39] successfully test temporal pooler & imagination on tiny 2x2 example --- src/carver/tests/recognition_temporal.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 0479041..1c96cb9 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -111,8 +111,18 @@ def printCellActive(htm): ' '.join(map(lambda c: '1' if c.active else '0', col.cells)) ) - h.execute(rowflip.dataGenerator(), ticks=4, learning=True, - postTick=printCellActive) + h.execute(rowflip.dataGenerator(), ticks=6, learning=True, + #postTick=printCellActive + ) + + for _ in xrange(4): + h.imagineNext() + #InputReflectionOverlayDisplay.showNow(h) + + #check that the right cell is active + active = filter(lambda i:i.wasActive, [i for row in h._inputCells for i in row]) + self.assertEqual(1, len(active)) + self.assertEqual(0, active[0].x+active[0].y) #InputCellsDisplay.showNow(h) From c4181e69e5336699fb6ce62e6c0ccc855c735b50 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Fri, 1 Apr 2011 01:29:20 -0400 Subject: [PATCH 37/39] prefer segments that were learning when returning to temporal phase 1 --- src/carver/htm/cell.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/carver/htm/cell.py b/src/carver/htm/cell.py index 5c7792b..6110cd4 100644 --- a/src/carver/htm/cell.py +++ b/src/carver/htm/cell.py @@ -144,15 +144,25 @@ def __ne__(self, other): return not (self == other) def findSegmentWasActive(self, nextStep=True): - 'prefer distal, return hits from segments connected to other cells that were active' + ''' + prefer distal (comes for free, all cells have only distal segments) + prefer segments where learning cell triggered + return hits from segments connected to other cells that were active + ''' if nextStep: segments = self.segmentsNear else: segments = self.segments + activeSeg = None + for seg in segments: if seg.wasActive: - return seg + activeSeg = seg + if seg.wasActiveFromLearningCells: + return seg + + return activeSeg def bestMatchingSegment(self, nextStep): ''' From e70a5e105adfb2d07e41f27f23f8e28819deac68 Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Fri, 1 Apr 2011 02:15:11 -0400 Subject: [PATCH 38/39] stimulate input according to permanence, when imagining --- src/carver/htm/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/carver/htm/__init__.py b/src/carver/htm/__init__.py index cad6828..1697945 100644 --- a/src/carver/htm/__init__.py +++ b/src/carver/htm/__init__.py @@ -113,11 +113,11 @@ def imagineNext(self): def stimulateFromColumns(cls, columns, columnFilter): for col in columns: if columnFilter(col): - down_scale = len(col.synapsesConnected) - activityPerSynapse = float(1) / down_scale + permanences = map(lambda syn: syn.permanence, col.synapsesConnected) + down_scale = float(sum(permanences)) for synapse in col.synapsesConnected: - synapse.input.stimulate(activityPerSynapse) + synapse.input.stimulate(synapse.permanence / down_scale) @classmethod def _imagineStimulate(cls, columns): From f93c4c686fa10d1fc1b28efef796f03196a5e7ab Mon Sep 17 00:00:00 2001 From: Jason Carver Date: Fri, 1 Apr 2011 02:19:11 -0400 Subject: [PATCH 39/39] htm lost pattern on one major cycle, so cycle twice to ingrain it, move tests after display data so you see info even if test fails --- src/carver/tests/recognition_temporal.py | 62 +++++++++++++++--------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/src/carver/tests/recognition_temporal.py b/src/carver/tests/recognition_temporal.py index 1c96cb9..0339e19 100644 --- a/src/carver/tests/recognition_temporal.py +++ b/src/carver/tests/recognition_temporal.py @@ -117,12 +117,12 @@ def printCellActive(htm): for _ in xrange(4): h.imagineNext() - #InputReflectionOverlayDisplay.showNow(h) +# InputReflectionOverlayDisplay.showNow(h) #check that the right cell is active active = filter(lambda i:i.wasActive, [i for row in h._inputCells for i in row]) - self.assertEqual(1, len(active)) - self.assertEqual(0, active[0].x+active[0].y) + + ActivityOverTimeDisplay.showNow(history.data) #InputCellsDisplay.showNow(h) @@ -132,36 +132,46 @@ def printCellActive(htm): for row in h._inputCells: print ' '.join(map(lambda cell: '%.2f' % cell.stimulation, row)) - ActivityOverTimeDisplay.showNow(history.data) + self.assertEqual(1, len(active)) + self.assertEqual(0, active[0].x+active[0].y) self.assertGreater(len(filter(lambda c: c.active, h.cells)), 0) self.assertLess(len(filter(lambda c: c.active, h.cells)), 3) - def _testTemporalImagination(self): + def testTemporalImagination(self): h = HTM(cellsPerColumn=3) - h.initialize_input(self.left_block, compressionFactor=2.8) - - #show a whole left->right pass, 5 times - steps = 14*5 - goright = TranslateInput(self.left_block, shift=(0,1)) - h.execute(goright.dataGenerator(), ticks=steps-1) + h.initialize_input(self.left_block, +# compressionFactor=2 + ) - #show a whole right->left pass, 5 times - goleft = TranslateInput(self.right_block, shift=(0,-1)) - h.execute(goleft.dataGenerator(), ticks=steps-1) + history = ExciteHistory() - #show a whole top->bottom pass, 5 times - godown = TranslateInput(self.top_block, shift=(1,0)) - h.execute(godown.dataGenerator(), ticks=steps-1) + #show a whole left->right pass, 5 times + steps = 14*10 - #show a whole bottom->top pass, 5 times - goup = TranslateInput(self.bottom_block, shift=(-1,0)) - h.execute(goup.dataGenerator(), ticks=steps-1) + for _ in xrange(2): + goright = TranslateInput(self.left_block, shift=(0,1)) + h.execute(goright.dataGenerator(), ticks=steps-1, postTick=history.update) + + #show a whole right->left pass, 5 times + goleft = TranslateInput(self.right_block, shift=(0,-1)) + h.execute(goleft.dataGenerator(), ticks=steps-1, postTick=history.update) + + #show a whole top->bottom pass, 5 times + godown = TranslateInput(self.top_block, shift=(1,0)) + h.execute(godown.dataGenerator(), ticks=steps-1, postTick=history.update) + + #show a whole bottom->top pass, 5 times + goup = TranslateInput(self.bottom_block, shift=(-1,0)) + h.execute(goup.dataGenerator(), ticks=steps-1, postTick=history.update) #TODO: test imagination automatically + #go one whole loop to give it a chance to figure out what's going on + h.execute(goright.dataGenerator(), ticks=14*10-1, postTick=history.update) + #do three steps of block starting left and moving right - h.execute(dataGenerator=goright.dataGenerator(), ticks=3, + h.execute(dataGenerator=goright.dataGenerator(), ticks=4, learning=False, postTick=InputReflectionOverlayDisplay.showNow) #the displays here should be mostly green and black, but a bit of purple and red is ok @@ -170,8 +180,12 @@ def _testTemporalImagination(self): #imagine 9 more steps # for _ in xrange(9): # h.imagineNext() -# -# InputCellsDisplay.showNow(h) +# InputReflectionOverlayDisplay.showNow(h) +# history.update(h) + + InputCellsDisplay.showNow(h) + + ActivityOverTimeDisplay.showNow(history.data) #downstream the last step to project back into the input, #see if you have a block that is on the right side @@ -185,7 +199,7 @@ def _testTemporalImagination(self): def stimToRGB(stim): percentStimulated = stim/maxStim if maxStim else 0 triggered = percentStimulated >= percentSynapsesForActivation - red = 255 if triggered else 0 + red = 0 green = int(percentStimulated*255) blue = 255 if triggered else 0 return (red, green, blue)