import datetime
import time
import math
import nupic
import random
import numpy as np
import csv
import itertools
from collections import Counter
from urllib import urlretrieve
from nupic.frameworks.opf.modelfactory import ModelFactory
from nupic.bindings.math import GetNTAReal
class ColumnStatesPatcher(object):
def __init__(self, experimentName):
filename = '%s.column_states.%s.csv' % (experimentName, time.strftime('%Y%m%d-%H.%M.%S'))
print "Writing to %s" % filename
self.outfile = open(filename, 'w')
def patch(self, model):
csvOutput = csv.writer(self.outfile)
headerRow = [
'n-unpredicted-active-columns',
'n-predicted-inactive-columns',
'n-predicted-active-columns',
]
csvOutput.writerow(headerRow)
runMethod = model.run
def myRun(v):
tp = model._getTPRegion().getSelf()._tfdr
npPredictedCells = tp.getPredictedState().reshape(-1).nonzero()[0]
predictedColumns = set(np.unique(npPredictedCells / tp.cellsPerColumn).tolist())
runResult = runMethod(v)
spOutput = model._getSPRegion().getSelf()._spatialPoolerOutput
activeColumns = set(spOutput.nonzero()[0].tolist())
row = (
len(activeColumns - predictedColumns),
len(predictedColumns - activeColumns),
len(activeColumns & predictedColumns),
)
csvOutput.writerow(row)
return runResult
model.run = myRun
def onFinished(self):
self.outfile.close()
class TotalSegmentsPatcher(object):
def __init__(self, experimentName):
filename = '%s.segments.%s.csv' % (experimentName, time.strftime('%Y%m%d-%H.%M.%S'))
print "Writing to %s" % filename
self.outfile = open(filename, 'w')
def patch(self, model):
csvOutput = csv.writer(self.outfile)
tp = model._getTPRegion().getSelf()._tfdr
htmData = (tp.activationThreshold,)
csvOutput.writerow(htmData)
runMethod = model.run
def myRun(v):
runResult = runMethod(v)
nSegmentsByConnectedCount = []
if hasattr(tp, "connections"): # temporal_memory.py
for segment, _ in tp.connections._segments.items():
nConnected = 0
for syn in tp.connections.synapsesForSegment(segment):
synapseData = tp.connections.dataForSynapse(syn)
if synapseData.permanence >= tp.connectedPermanence:
nConnected += 1
while len(nSegmentsByConnectedCount) <= nConnected:
nSegmentsByConnectedCount.append(0)
nSegmentsByConnectedCount[nConnected] += 1
else: # tp.py
for col in xrange(tp.numberOfCols):
for cell in xrange(tp.cellsPerColumn):
for segIdx in xrange(tp.getNumSegmentsInCell(col, cell)):
nConnected = 0
v = tp.getSegmentOnCell(col, cell, segIdx)
segData = v[0]
for _, _, perm in v[1:]:
if perm >= tp.connectedPerm:
nConnected += 1
while len(nSegmentsByConnectedCount) <= nConnected:
nSegmentsByConnectedCount.append(0)
nSegmentsByConnectedCount[nConnected] += 1
csvOutput.writerow(nSegmentsByConnectedCount)
return runResult
model.run = myRun
def onFinished(self):
self.outfile.close()
# Does not work with tp.py.
class SegmentLearningPatcher(object):
def __init__(self, experimentName):
filename = '%s.segment_learning.%s.csv' % (experimentName, time.strftime('%Y%m%d-%H.%M.%S'))
print "Writing to %s" % filename
self.outfile = open(filename, 'w')
self.clear()
def clear(self):
self.addedSegments = 0
self.destroyedSegments = 0
self.addedSynapses = 0
self.destroyedSynapses = 0
self.strengthenedSynapses = 0
self.weakenedSynapses = 0
self.newlyConnectedSynapses = 0
self.newlyDisconnectedSynapses = 0
def patch(self, model):
csvOutput = csv.writer(self.outfile)
headerRow = (
'n-added-segments',
'n-destroyed-segments',
'n-added-synapses',
'n-destroyed-synapses',
'n-strengthened-synapses',
'n-weakened-synapses',
'n-newly-connected-synapses',
'n-newly-disconnected-synapses',
)
csvOutput.writerow(headerRow)
tp = model._getTPRegion().getSelf()._tfdr
connections = tp.connections
createSegmentMethod = connections.createSegment
def myCreateSegment(*args, **kwargs):
self.addedSegments += 1
return createSegmentMethod(*args, **kwargs)
connections.createSegment = myCreateSegment
destroySegmentMethod = connections.destroySegment
def myDestroySegment(*args, **kwargs):
self.destroyedSegments += 1
return destroySegmentMethod(*args, **kwargs)
connections.destroySegment = myDestroySegment
createSynapseMethod = connections.createSynapse
def myCreateSynapse(*args, **kwargs):
self.addedSynapses += 1
return createSynapseMethod(*args, **kwargs)
connections.createSynapse = myCreateSynapse
destroySynapseMethod = connections.destroySynapse
def myDestroySynapse(*args, **kwargs):
self.destroyedSynapses += 1
return destroySynapseMethod(*args, **kwargs)
connections.destroySynapse = myDestroySynapse
updateSynapsePermanenceMethod = connections.updateSynapsePermanence
def myUpdateSynapsesPermanence(synapse, permanence):
previous = connections.dataForSynapse(synapse).permanence
if previous < permanence:
self.strengthenedSynapses += 1
if previous < tp.connectedPermanence and permanence >= tp.connectedPermanence:
self.newlyConnectedSynapses += 1
elif previous > permanence:
self.weakenedSynapses += 1
if previous >= tp.connectedPermanence and permanence < tp.connectedPermanence:
self.newlyDisconnectedSynapses += 1
return updateSynapsePermanenceMethod(synapse, permanence)
connections.updateSynapsePermanence = myUpdateSynapsesPermanence
runMethod = model.run
def myRun(v):
self.clear()
runResult = runMethod(v)
row = (
self.addedSegments,
self.destroyedSegments,
self.addedSynapses,
self.destroyedSynapses,
self.strengthenedSynapses,
self.weakenedSynapses,
self.newlyConnectedSynapses,
self.newlyDisconnectedSynapses,
)
csvOutput.writerow(row)
return runResult
model.run = myRun
def onFinished(self):
self.outfile.close()
class SaveInputsPatcher(object):
def __init__(self, experimentName, inputKey):
filename = '%s.inputs.%s.csv' % (experimentName, time.strftime('%Y%m%d-%H.%M.%S'))
print "Writing to %s" % filename
self.inputKey = inputKey
self.outfile = open(filename, 'w')
def patch(self, model):
csvOutput = csv.writer(self.outfile)
header = ('input',)
csvOutput.writerow(header)
runMethod = model.run
def myRun(v):
row = (v[self.inputKey],)
csvOutput.writerow(row)
return runMethod(v)
model.run = myRun
def onFinished(self):
self.outfile.close()
class ColumnOverlapsPatcher(object):
def __init__(self, experimentName):
filename = '%s.column_overlaps.%s.csv' % (experimentName,
time.strftime('%Y%m%d-%H.%M.%S'))
print "Writing to %s" % filename
self.outfile = open(filename, 'w')
def patch(self, model):
csvOutput = csv.writer(self.outfile)
spRegion = model._getSPRegion().getSelf()
sp = spRegion._sfdr
runMethod = model.run
def myRun(v):
runResult = runMethod(v)
overlaps = sp.getOverlaps()
activeColumns = spRegion._spatialPoolerOutput.nonzero()[0].tolist()
outputRow = sorted((overlaps[bit] for bit in activeColumns), reverse=True)
csvOutput.writerow(outputRow)
return runResult
model.run = myRun
def onFinished(self):
self.outfile.close()
class ColumnBoostedOverlapsPatcher(object):
def __init__(self, experimentName):
filename = '%s.column_boosted_overlaps.%s.csv' % (experimentName,
time.strftime('%Y%m%d-%H.%M.%S'))
print "Writing to %s" % filename
self.outfile = open(filename, 'w')
def patch(self, model):
csvOutput = csv.writer(self.outfile)
spRegion = model._getSPRegion().getSelf()
sp = spRegion._sfdr
runMethod = model.run
def myRun(v):
runResult = runMethod(v)
overlaps = sp.getBoostedOverlaps()
activeColumns = spRegion._spatialPoolerOutput.nonzero()[0].tolist()
outputRow = sorted((overlaps[bit] for bit in activeColumns), reverse=True)
csvOutput.writerow(outputRow)
return runResult
model.run = myRun
def onFinished(self):
self.outfile.close()
class ColumnBoostFactorsPatcher(object):
def __init__(self, experimentName):
filename = '%s.column_boost_factors.%s.csv' % (experimentName,
time.strftime('%Y%m%d-%H.%M.%S'))
print "Writing to %s" % filename
self.outfile = open(filename, 'w')
def patch(self, model):
csvOutput = csv.writer(self.outfile)
spRegion = model._getSPRegion().getSelf()
sp = spRegion._sfdr
runMethod = model.run
def myRun(v):
boostFactors = np.zeros(sp.getNumColumns()).astype(GetNTAReal())
sp.getBoostFactors(boostFactors)
runResult = runMethod(v)
activeColumns = spRegion._spatialPoolerOutput.nonzero()[0].tolist()
#outputRow = sorted((boostFactors[bit] for bit in activeColumns))
csvOutput.writerow(boostFactors)
return runResult
model.run = myRun
def onFinished(self):
self.outfile.close()
class BoostedColumnsPatcher(object):
def __init__(self, experimentName):
filename = '%s.boosted_columns.%s.csv' % (experimentName, time.strftime('%Y%m%d-%H.%M.%S'))
print "Writing to %s" % filename
self.outfile = open(filename, 'w')
def patch(self, model):
csvOutput = csv.writer(self.outfile)
spRegion = model._getSPRegion().getSelf()
sp = spRegion._sfdr
runMethod = model.run
def myRun(v):
boostFactors = np.zeros(sp.getNumColumns()).astype(GetNTAReal())
sp.getBoostFactors(boostFactors)
freqs = Counter(boostFactors)
# Format: [boostFactor1, count1, boostFactor2, count2, ...]
row = list(itertools.chain.from_iterable(freqs.items()))
csvOutput.writerow(row)
runResult = runMethod(v)
return runResult
model.run = myRun
def onFinished(self):
self.outfile.close()
class ActiveToDueBoostingPatcher(object):
def __init__(self, experimentName):
filename = '%s.active_due_to_boosting.%s.csv' % (experimentName, time.strftime('%Y%m%d-%H.%M.%S'))
print "Writing to %s" % filename
self.outfile = open(filename, 'w')
def patch(self, model):
csvOutput = csv.writer(self.outfile)
headerRow = [
'n-active-due-to-boosting',
]
csvOutput.writerow(headerRow)
spRegion = model._getSPRegion().getSelf()
sp = spRegion._sfdr
runMethod = model.run
def myRun(v):
runResult = runMethod(v)
activeColumns = set(spRegion._spatialPoolerOutput.nonzero()[0].tolist())
overlaps = sp.getOverlaps()
overlapsReal = nupic.bindings.math.FloatVector(sp.getNumColumns())
overlapsReal[:] = overlaps
hypotheticalColumns = nupic.bindings.math.VectorOfUInt32()
sp.inhibitColumns_(overlapsReal, hypotheticalColumns)
hypotheticalActive = set(hypotheticalColumns)
row = (
len(activeColumns - hypotheticalActive),
)
csvOutput.writerow(row)
return runResult
model.run = myRun
def onFinished(self):
self.outfile.close()
class TimeSinceColumnActivePatcher(object):
def __init__(self, experimentName):
filename = '%s.time_since_column_active.%s.csv' % (experimentName, time.strftime('%Y%m%d-%H.%M.%S'))
print "Writing to %s" % filename
self.outfile = open(filename, 'w')
def patch(self, model):
csvOutput = csv.writer(self.outfile)
headerRow = [
'min',
'q1',
'median',
'q3',
'max'
]
csvOutput.writerow(headerRow)
spRegion = model._getSPRegion().getSelf()
sp = spRegion._sfdr
timeSinceActive = np.zeros(sp.getNumColumns())
runMethod = model.run
def myRun(v):
timeSinceActive[:] += 1
runResult = runMethod(v)
activeColumns = spRegion._spatialPoolerOutput.nonzero()[0].tolist()
timeSinceActive[activeColumns] = 0
row = np.percentile(timeSinceActive, [0, 25, 50, 75, 100]).tolist()
csvOutput.writerow(row)
return runResult
model.run = myRun
def onFinished(self):
self.outfile.close()
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': 100.0,
'minval': 0.0,
'n': 143,
'name': '_classifierInput',
'type': 'ScalarEncoder',
'w': 21
},
u'kw_energy_consumption': {
'clipInput': True,
'fieldname': 'kw_energy_consumption',
'maxval': 100.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': 'tm_py',
'verbosity': 0
},
'trainSPNetOnlyIfRequested': False
},
'predictAheadTime': None,
'version': 1
}
MODEL_PARAMS2 = {
'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': 'input',
'maxval': 100.0,
'minval': 0.0,
'n': 143,
'name': '_classifierInput',
'type': 'ScalarEncoder',
'w': 21
},
u'input': {
'clipInput': True,
'fieldname': 'input',
'maxval': 100.0,
'minval': 0.0,
'n': 97,
'name': 'input',
'type': 'ScalarEncoder',
'w': 21
},
},
'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': 'tm_py',
'verbosity': 0
},
'trainSPNetOnlyIfRequested': False
},
'predictAheadTime': None,
'version': 1
}
def experiment1(nsteps):
model = ModelFactory.create(MODEL_PARAMS2)
model.enableInference({"predictedField": "input"})
experimentName = 'fixed_seq'
patchers = (ColumnStatesPatcher(experimentName),
TotalSegmentsPatcher(experimentName),
SegmentLearningPatcher(experimentName),
SaveInputsPatcher(experimentName, 'input'),
ColumnOverlapsPatcher(experimentName),
ColumnBoostedOverlapsPatcher(experimentName),
BoostedColumnsPatcher(experimentName),
ActiveToDueBoostingPatcher(experimentName),
TimeSinceColumnActivePatcher(experimentName),)
for p in patchers:
p.patch(model)
for i in range(nsteps):
if i % 100 == 0:
print "timestep %d" % i
input = (i%24) * 4
result = model.run({
"input": input,
})
for p in patchers:
p.onFinished()
return model
def experiment2(nsteps):
model = ModelFactory.create(MODEL_PARAMS2)
model.enableInference({"predictedField": "input"})
experimentName = 'sine'
patchers = (ColumnStatesPatcher(experimentName),
TotalSegmentsPatcher(experimentName),
SegmentLearningPatcher(experimentName),
SaveInputsPatcher(experimentName, 'input'),
ColumnOverlapsPatcher(experimentName),
ColumnBoostedOverlapsPatcher(experimentName),
BoostedColumnsPatcher(experimentName),
ActiveToDueBoostingPatcher(experimentName),
TimeSinceColumnActivePatcher(experimentName),)
for p in patchers:
p.patch(model)
for i in range(nsteps):
if i % 100 == 0:
print "timestep %d" % i
# Use:
# - a period that's close to 24
# - but not exactly 24. Keep it irrational so that it's
# not perfectly predictable by sequence memory
# - an output range of [0,100]
input = (math.sin(i/4.0) + 1) * 50
result = model.run({
"input": input,
})
for p in patchers:
p.onFinished()
return model
def experiment3():
inputFile = open(urlretrieve("http://mrcslws.com/stuff/rec-center-hourly.csv")[0], 'r')
csvReader = csv.reader(inputFile)
csvReader.next()
csvReader.next()
csvReader.next()
model = ModelFactory.create(MODEL_PARAMS)
model.enableInference({"predictedField": "kw_energy_consumption"})
experimentName = 'hotgym'
patchers = (ColumnStatesPatcher(experimentName),
TotalSegmentsPatcher(experimentName),
SegmentLearningPatcher(experimentName),
SaveInputsPatcher(experimentName, 'kw_energy_consumption'),
ColumnOverlapsPatcher(experimentName),
ColumnBoostedOverlapsPatcher(experimentName),
BoostedColumnsPatcher(experimentName),
ActiveToDueBoostingPatcher(experimentName),
TimeSinceColumnActivePatcher(experimentName),)
for p in patchers:
p.patch(model)
i = 0
for row in csvReader:
i += 1
if i % 100 == 0:
print "timestep %d" % i
timestampStr, consumptionStr = row
timestamp = datetime.datetime.strptime(timestampStr, "%m/%d/%y %H:%M")
consumption = float(consumptionStr)
result = model.run({
"timestamp": timestamp,
"kw_energy_consumption": consumption,
})
for p in patchers:
p.onFinished()
return model
def experiment4(nsteps):
model = ModelFactory.create(MODEL_PARAMS2)
model.enableInference({"predictedField": "input"})
experimentName = 'random'
patchers = (ColumnStatesPatcher(experimentName),
TotalSegmentsPatcher(experimentName),
SegmentLearningPatcher(experimentName),
SaveInputsPatcher(experimentName, 'input'),
ColumnOverlapsPatcher(experimentName),
ColumnBoostedOverlapsPatcher(experimentName),
BoostedColumnsPatcher(experimentName),
ActiveToDueBoostingPatcher(experimentName),
TimeSinceColumnActivePatcher(experimentName),)
for p in patchers:
p.patch(model)
for i in range(nsteps):
if i % 100 == 0:
print "timestep %d" % i
input = random.randint(0,100)
result = model.run({
"input": input,
})
for p in patchers:
p.onFinished()
return model
experiment1(4300)
experiment2(4300)
experiment3()
experiment4(4300)