Hello!. I am trying to create a simple example of network with HTM
(Hierarchical Temporal Memory - NumentaPIC) to classify values of the iris
dataset. However, I've followed the examples of the NuPIC, nevertheless,
the network only provides zeros instead the class (0 for Iris-setosa, 1 for
Iris-versicolor, and 2 for Iris-virginica).
Here is my code to create, train, and test the network:
import jsonimport csvimport sysimport os
from nupic.bindings.math import GetNTARealfrom nupic.engine import
Networkfrom nupic.research import fdrutilities
from nupic.engine import pyRegionsfrom nupic.encoders import
MultiEncoderfrom nupic.data.file_record_stream import FileRecordStream
class HTMNetwork:
_VERBOSITY = 0
_SEED = 2047
SP_PARAMS = {
"spVerbosity": _VERBOSITY,
"spatialImp": "cpp",
"globalInhibition": 1,
"columnCount": 2048,
"inputWidth": 0,
"numActiveColumnsPerInhArea": 40,
"seed": 1956,
"potentialPct": 0.8,
"synPermConnected": 0.1,
"synPermActiveInc": 0.0001,
"synPermInactiveDec": 0.0005,
"maxBoost": 1.0,
}
TM_PARAMS = {
"verbosity": _VERBOSITY,
"columnCount": 2048,
"cellsPerColumn": 32,
"inputWidth": 2048,
"seed": 1960,
"temporalImp": "tm_py",
"newSynapseCount": 20,
"maxSynapsesPerSegment": 32,
"maxSegmentsPerCell": 128,
"initialPerm": 0.21,
"permanenceInc": 0.1,
"permanenceDec": 0.1,
"globalDecay": 0.0,
"maxAge": 0,
"minThreshold": 9,
"activationThreshold": 12,
"outputType": "normal",
"pamLength": 3,
}
SEQUENCE_CLASSIFIER_PARAMS = {"steps": "0",
"implementation": "py"}
PY_REGIONS = [r[1] for r in pyRegions]
''' 1. Metodo que permite crear las regiones que contendra
la red HTM '''
def createRegions(self,args):
( dataSource,
sensorType,
classifierType,
encoders ) = args
sensor = self.createSensorRegion(sensorType,encoders,dataSource)
sp = self.createSpatialPoolerRegion(sensor.encoder.getWidth())
tm = self.createTemporalMemoryRegion(sp.getSelf().columnCount)
self.createClassifierRegion(classifierType,tm.getSelf().outputWidth)
''' 2. Metodo que permite crear los sensores que se
colocaran en cada region, dependiendo de las entradas que tenga
la red '''
def createSensorRegion(self,sensorType,encoders,dataSource):
try:
regionParams = json.dumps({"verbosity":self._VERBOSITY})
self.network.addRegion("sensor",sensorType,regionParams)
except RuntimeError:
print("No se puede anadir region propia. Revisar.")
return
sensorRegion = self.network.regions["sensor"].getSelf()
if isinstance(encoders,dict):
print "Adding multiple encoders..."
sensorRegion.encoder=self.createEncoder(encoders)
else:
print "Adding one encoder..."
sensorRegion.encoder=encoders
sensorRegion.dataSource=dataSource
return sensorRegion
''' 3. Metodo que se invoca para crear los encoders en caso
de que se utilice mas de uno para cada entrada '''
def createEncoder(self,encoders):
encoder=MultiEncoder()
encoder.addMultipleEncoders(encoders)
return encoder
''' 4. Metodo que permite creare el SpatialPooler '''
def createSpatialPoolerRegion(self,prevRegionWidth):
self.SP_PARAMS["inputWidth"]=prevRegionWidth
spatialPoolerRegion=self.network.addRegion("SP","py.SPRegion",json.dumps(self.SP_PARAMS))
return spatialPoolerRegion
''' 5. Metodo que permite crear el Temporal Memory '''
def createTemporalMemoryRegion(self,prevRegionWidth):
if self.TM_PARAMS["columnCount"] != prevRegionWidth:
raise ValueError("Region widths do not fit!")
self.TM_PARAMS["inputWidth"]=self.TM_PARAMS["columnCount"]
temporalMemoryRegion =
self.network.addRegion("TM","py.TPRegion",json.dumps(self.TM_PARAMS))
temporalMemoryRegion.setParameter("learningMode",False)
temporalMemoryRegion.setParameter("inferenceMode",True)
return temporalMemoryRegion
''' 6. Metodo que permite crear la region encargada de
realizar el proceso de clasificacion de las representaciones
binarias SDR '''
''' Metodo que permite establecer el enlace entre las
diferentes regiones de la red HTM '''
def linkRegions(self):
self.network.link("sensor","SP","UniformLink","")
self.network.link("sensor","SP","UniformLink","",
srcOutput="resetOut",destInput="resetIn")
self.network.link("SP","TM","UniformLink","",
srcOutput="bottomUpOut",destInput="bottomUpIn")
self.network.link("TM","SP","UniformLink","",
srcOutput="topDownOut",destInput="topDownIn")
self.network.link("TM","sensor","UniformLink","",
srcOutput="topDownOut",destInput="temporalTopDownIn")
self.network.link("sensor","TM","UniformLink","",
srcOutput="resetOut",destInput="resetIn")
self.network.link("TM","classifier","UniformLink","",
srcOutput="bottomUpOut",destInput="bottomUpIn")
self.network.link("sensor","classifier","UniformLink","",
srcOutput="categoryOut",destInput="categoryIn")
def createClassifierRegion(self,classifierType,prevRegionWidth):
''' if classifierType.split(".")[1] not in PY_REGIONS:
self.network.registerRegion(SequenceClassifierRegion)
PY_REGIONS.append(classifierType.split(".")[1]) '''
classifierRegion =
self.network.addRegion("classifier",classifierType,json.dumps(self.SEQUENCE_CLASSIFIER_PARAMS))
classifierRegion.setParameter("learningMode",False)
classifierRegion.setParameter("inferenceMode",True)
return classifierRegion
''' Metodo invocado para crear la red. Es el encargado de
llamar a los demas metodos y efectuar las siguientes
operaciones: 1. Creacion de regiones 2. Enlace
de regiones entre si '''
def create_network(self,args):
self.network=Network()
self.createRegions(args)
self.linkRegions()
''' Metodo para realizar pruebas '''
def testNetwork(self):
self.network.initialize()
print "Red inicializada..."
sensorRegion = self.network.regions["sensor"]
spatialPoolerRegion = self.network.regions["SP"]
temporalMemoryRegion = self.network.regions["TM"]
classifierRegion = self.network.regions["classifier"]
for i in xrange(105):
print "Ejecucion [[%i]]"%i
self.network.run(1)
if i==105*1/3:
print "Inicia entrenamiento de Temporal Memory Region"
temporalMemoryRegion.setParameter("learningMode",True)
elif i==105*2/3:
print "Inicia entrenamiento de Classifier Region"
classifierRegion.setParameter("learningMode",True)
self._run_classifier(sensorRegion,temporalMemoryRegion,classifierRegion,i)
spatialPoolerRegion.setParameter("learningMode",False)
temporalMemoryRegion.setParameter("learningMode",False)
classifierRegion.setParameter("learningMode",False)
self.classify()
''' Metodo para realizar el proceso de aprendizaje '''
def
_run_classifier(self,sensorRegion,temporalMemoryRegion,classifierRegion,recordNUM):
actualValue = sensorRegion.getOutputData("categoryOut")[0]
print "[[[[[",sensorRegion.getOutputData("categoryOut"),"]]]]"
bucketIdx = actualValue
classificationIn={ "bucketIdx": int(bucketIdx),
"actValue": int(actualValue)
}
activeCells = temporalMemoryRegion.getOutputData("bottomUpOut")
_patternNZ = activeCells.nonzero()[0]
clResults =
classifierRegion.getSelf().customCompute(recordNum=recordNUM,
patternNZ = _patternNZ,
classification =
classificationIn)
print "clResults: ",clResults
return clResults
''' Metodo que permite analizar la clasificacion de los
patrones se realizo de forma correcta '''
def classify(self):
print "Clasificacion: "
sensorRegion = self.network.regions["sensor"]
temporalMemoryRegion = self.network.regions["TM"]
classifierRegion = self.network.regions["classifier"]
for i in xrange(70):
clResults =
self._run_classifier(sensorRegion,temporalMemoryRegion,classifierRegion,i)
print clResults
inferredValue =
clResults["actualValues"][clResults[int(classifierRegion.getParameter("steps"))].argmax()]
print "Prediccion: %s " % inferredValue
if __name__=="__main__":
args=None
if len(sys.argv)!=4:
print "Pasando parametros por defecto..."
encoders={"largo_sepalo":
dict(fieldname="largo_sepalo",type="ScalarEncoder",
name="largo_sepalo",minval=4.3,maxval=7.9,w=33,n=47),
"ancho_sepalo":
dict(fieldname="ancho_sepalo",type="ScalarEncoder",
name="ancho_sepalo",minval=2.0,maxval=4.4,w=33,n=47),
"largo_petalo":
dict(fieldname="largo_petalo",type="ScalarEncoder",
name="largo_petalo",minval=1.0,maxval=6.9,w=33,n=47),
"ancho_petalo":
dict(fieldname="ancho_petalo",type="ScalarEncoder",
name="ancho_petalo",minval=0.1,maxval=2.5,w=33,n=47),
#"clase":
dict(fieldname="clase",name="clase",w=33,n=47,type="AdaptiveScalarEncoder",
#minval=0,maxval=2)
"clase":
dict(fieldname="clase",name="clase",w=33,n=47,type="AdaptiveScalarEncoder",)
}
args=[FileRecordStream("train.csv"),"py.RecordSensor","py.CLAClassifierRegion",encoders]
else:
print "Pasando parametros por consola..."
args = sys.argv
print "args: ",args
htmNet=HTMNetwork()
htmNet.create_network(args)
htmNet.testNetwork()
When I run the code, the network apparently is created and trained
well, but when I try to "classify" the existing values (from training
file) all values are zero. A fragment of my training file is the
following (train.csv):
largo_sepalo,ancho_sepalo,largo_petalo,ancho_petalo,clase
float,float,float,float,int
,,,,
5.6,2.7,4.2,1.3,1
4.5,2.3,1.3,0.3,0
6.7,3.1,5.6,2.4,2
4.7,3.2,1.6,0.2,0
5.4,3.9,1.7,0.4,0
7.9,3.8,6.4,2.0,2
5.0,3.4,1.5,0.2,0
7.3,2.9,6.3,1.8,2
The results that I get from the network are the following (no errors):
Clasificacion:
[[[[[ [ 0.] ]]]]
clResults: {'actualValues': [0], 0: array([ 1.])}
{'actualValues': [0], 0: array([ 1.])}
Prediction-Class: 0
[[[[[ [ 0.] ]]]]
clResults: {'actualValues': [0], 0: array([ 1.])}
{'actualValues': [0], 0: array([ 1.])}
Prediction-Class: 0
[[[[[ [ 0.] ]]]]
clResults: {'actualValues': [0], 0: array([ 1.])}
{'actualValues': [0], 0: array([ 1.])}
Prediction-Class: 0
[[[[[ [ 0.] ]]]]
clResults: {'actualValues': [0], 0: array([ 1.])}
{'actualValues': [0], 0: array([ 1.])}
Prediction-Class: 0
[[[[[ [ 0.] ]]]]
Please, could someone provide me some advice or idea of what I am doing wrong?
Thank you!