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 json
import csv
import sys
import os
from nupic.bindings.mathimport GetNTAReal
from nupic.engineimport Network
from nupic.researchimport fdrutilities
from nupic.engineimport pyRegions
from nupic.encodersimport MultiEncoder
from nupic.data.file_record_streamimport 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 rin 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 iin 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 iin 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!