Marcus Lewis | 2015-11-12 | Download this IPython Notebook
While running NuPIC, I've been seeing a few unexpected behaviors. I figured it'd be useful to capture them in a notebook where you can inspect them from a code environment.
from IPython.display import Image
Image(url="https://www.dropbox.com/s/ims48coyn4sr9b4/Screenshot%202015-11-12%2012.13.08.png?dl=1")
See the blue "cell 4"? That cell was predicted, but not activated.
See the red "cell 0"? That cell was not predicted, but was activated.
Let's rerun up to step 545 and verify this by API.
import datetime
from itertools import groupby
import nupic
from nupic.frameworks.opf.modelfactory import ModelFactory
cellsPerColumn = 32
MODEL_PARAMS = {
'aggregationInfo': {
'days': 0,
'fields': [],
'hours': 0,
'microseconds': 0,
'milliseconds': 0,
'minutes': 0,
'months': 0,
'seconds': 0,
'weeks': 0,
'years': 0
},
'model': 'CLA',
'modelParams': {
'anomalyParams': {
u'anomalyCacheRecords': None,
u'autoDetectThreshold': None,
u'autoDetectWaitRecords': None
},
'clParams': {
'alpha': 0.01472949181138251,
'clVerbosity': 0,
'regionName': 'CLAClassifierRegion',
'steps': '1'},
'inferenceType': 'TemporalMultiStep',
'sensorParams': {
'encoders': {
'_classifierInput': {
'classifierOnly': True,
'clipInput': True,
'fieldname': 'kw_energy_consumption',
'maxval': 53.0,
'minval': 0.0,
'n': 143,
'name': '_classifierInput',
'type': 'ScalarEncoder',
'w': 21
},
u'kw_energy_consumption': {
'clipInput': True,
'fieldname': 'kw_energy_consumption',
'maxval': 53.0,
'minval': 0.0,
'n': 97,
'name': 'kw_energy_consumption',
'type': 'ScalarEncoder',
'w': 21
},
u'timestamp_dayOfWeek': None,
u'timestamp_timeOfDay': {
'fieldname': 'timestamp',
'name': 'timestamp',
'timeOfDay': ( 21,
4.92648688354549),
'type': 'DateEncoder'
},
u'timestamp_weekend': None},
'sensorAutoReset': None,
'verbosity': 0},
'spEnable': True,
'spParams': {
'columnCount': 2048,
'globalInhibition': 1,
'inputWidth': 0,
'maxBoost': 2.0,
'numActiveColumnsPerInhArea': 40,
'potentialPct': 0.8,
'seed': 1956,
'spVerbosity': 0,
'spatialImp': 'cpp',
'synPermActiveInc': 0.05,
'synPermConnected': 0.1,
'synPermInactiveDec': 0.07703611403439363
},
'tpEnable': True,
'tpParams': {
'activationThreshold': 13,
'cellsPerColumn': cellsPerColumn,
'columnCount': 2048,
'globalDecay': 0.0,
'initialPerm': 0.21,
'inputWidth': 2048,
'maxAge': 0,
'maxSegmentsPerCell': 128,
'maxSynapsesPerSegment': 32,
'minThreshold': 9,
'newSynapseCount': 20,
'outputType': 'normal',
'pamLength': 2,
'permanenceDec': 0.1,
'permanenceInc': 0.1,
'seed': 1960,
'temporalImp': 'cpp',
'verbosity': 0
},
'trainSPNetOnlyIfRequested': False
},
'predictAheadTime': None,
'version': 1
}
import csv
from urllib import urlopen
inputFile = urlopen("http://mrcslws.com/stuff/rec-center-hourly.csv")
csvReader = csv.reader(inputFile)
csvReader.next()
csvReader.next()
csvReader.next()
model = ModelFactory.create(MODEL_PARAMS)
model.enableInference({"predictedField": "kw_energy_consumption"})
def step():
global model, csvReader
timestampStr, consumptionStr = csvReader.next()
timestamp = datetime.datetime.strptime(timestampStr, "%m/%d/%y %H:%M")
consumption = float(consumptionStr)
result = model.run({
"timestamp": timestamp,
"kw_energy_consumption": consumption,
})
def getPredictedCells(model):
tp = model._getTPRegion().getSelf()._tfdr
return tp.getPredictedState().reshape(-1).nonzero()[0].tolist()
def getActiveCells(model):
tp = model._getTPRegion().getSelf()._tfdr
return tp.getActiveState().nonzero()[0].tolist()
def getActiveColumns(model):
return model._getSPRegion().getSelf()._spatialPoolerOutput.nonzero()[0].tolist()
First, run to step 544. Observe this timestep's predicted cells.
Then run to step 545. Observe this timestep's active cells.
for i in range(544):
step()
previouslyPredictedCells = getPredictedCells(model)
print "Timestep 744 predicted columns / cells:"
print ""
for column, cells in groupby(previouslyPredictedCells,
lambda x: x / cellsPerColumn):
print "Column %d cells: %s" % (column, ", ".join(str(cell) for cell in cells))
step()
activeCells = getActiveCells(model)
print "Timestep 745 active columns / cells:"
print ""
for column, cells in groupby(activeCells,
lambda x: x / cellsPerColumn):
print "Column %d cells: %s" % (column, ", ".join(str(cell) for cell in cells))
You can see that many columns were predicted + active, but that a totally different set of cells was selected.
from IPython.display import Image
Image(url="https://www.dropbox.com/s/46xwmfgy0fl2265/Screenshot%202015-11-12%2012.34.41.png?dl=1")
In the same timestep as Oddity 1, all non-predicted columns have only activated their first cell.
predictedColumns = list(cell / cellsPerColumn for cell in previouslyPredictedCells)
activeColumns = getActiveColumns(model)
burstingColumns = filter(lambda x: x not in predictedColumns,
activeColumns)
for column, cells in groupby(activeCells,
lambda x: x / cellsPerColumn):
if column in burstingColumns:
print "Bursting column %d active cells: %s" % \
(column, ", ".join(str(cell) for cell in cells))
I'd expect to have 32 active cells in each of these columns.
So this might all be one issue: Sometimes an HTM just activates the first cell in each activated column, never bursting and never paying attention to the predicted cells.
Maybe sometimes this is intentional? But it seems wrong for predicted columns.