(HTM)层次时序记忆-空间沉积池实现解读
如果你对HTM感兴趣,我建立了一个群,我们共同学习交流。515743445。
阅读本文前建议先阅读HTM白皮书(需要了解sp和tm的工作步骤),以及论文The HTM Spatial Pooler-A Neocortical Algorithm for Online Sparse Distributed Coding
本文研究src/nupic/algorithms/spatial_pooler.py的代码实现
我们以Complete-algo-example.py为实例对其进行研究。该范例的数据来自gymdata.csv。这是一个关于不同时间consumption数据的文件。其日期部分使用DateEncoder转换为SDR,其consumption部分使用RandomDistributedScalarEncoder转换为SDR。合并后输入sp。该范例的参数存放在model.yaml中。需要注意,该文件中SDRClassifierFactory.create()可能由于配置问题存在错误,我们直接使用python实现的SDRClassifier。另外其使用的tm与opf中使用的是不同的版本,导致结果不同。
SpatialPooler主要包括两个方法。init方法接收入参,构造sp。compute方法接收一个sdr,并计算激活的列。(这里的列指圆柱区域)
Sp的一些重要入参包括:
InputDimensions=(946,),一维,输入sdr的大小。默认(32,32)是二维的。
ColumnDimensions=(2048,),一维,输出sdr的大小,默认(64,64)是二维的。
PotentialRadius=16.指每一个列,可以建立前馈输入的范围(半径)。其实际效果是,每一个圆柱的潜在输入,在其与输入sdr的对应输入位的一定范围内。
PotentialPct=0.85 潜在突触范围内,85%是潜在输入。
GlobalInhibition=1使用全局抑制
lacalAreaDensity=-1.0 抑制范围内活跃列的密度,不启用
numActiveColumnsPerInhArea=40,使用该方式控制活跃列数量为40
stimulusThreshold=0, 列激活的,有输入的最小连通突触数
synPermInactiveDec=0.005, 活跃列中,连接到非有效输入的突触的连通值减小量
synPermActiveInc=0.04, 活跃列中,连接到有效输入的突触的连通值增加量
synPermConnected=0.10, 连通阈值
minPctOverlapDutyCycle=0.001,
dutyCyclePeriod=1000, 计算抑制半径的周期
boostStrength=3.0,默认0
seed=1956,
spVerbosity=0,
wrapAround=True
Sp的内部变量包括:
self._numInputs=946 输入向量大小
self._numColumns=2048 列的数量
self._columnDimensions = 列的尺寸(各维度)。本例等价2048
self._inputDimensions = 输入的尺寸(各维度)。本例等价946
self._potentialRadius = 946 潜在半径
self._potentialPct = 0.85 列在输入(潜在突触范围内)上的连通百分比限制
self._globalInhibition = 1 启用全局抑制
self._numActiveColumnsPerInhArea = 40 每个抑制区域的活跃列数量限制
self._localAreaDensity = localAreaDensity 活跃列密度限制
self._stimulusThreshold = 0 列的连通位数下限
self._synPermInactiveDec = synPermInactiveDec 活跃列的非输入的减益
self._synPermActiveInc = synPermActiveInc 活跃列的输入的增益
self._synPermBelowStimulusInc = synPermConnected / 10.0 不活跃列的连通值增加量
self._synPermConnected = 0.1 突触连通阈值,同时也是基准值
self._minPctOverlapDutyCycles = 0.001 激活程度的最低占空比。低于它的列被认为是不活跃的。
self._dutyCyclePeriod = 1000 周期。每次计算一次占空比并进行学习。
self._boostStrength = 3.0 boosting的参数
self._spVerbosity = spVerbosity
self._wrapAround = wrapAround
self._synPermMin = 0.0
self._synPermMax = 1.0
self._synPermTrimThreshold = synPermActiveInc / 2.0
self._overlaps = numpy.zeros(self._numColumns, dtype=realDType)
self._boostedOverlaps = numpy.zeros(self._numColumns, dtype=realDType)
Init():
Sp.Compute():
1. calculateOverlap()计算每个柱状区域,其连通的前馈输入,输入是1的位的个数。具体计算方式为调用_connectedSynapses.rightVecSumAtNZ_fast,入参inputvector.使用overlap数组记录2048个数,connectedSynapses拿到inputvector后,计算每一个column激活的前馈输入的数量,写入overlap,overlap我们称之为激活程度。
2. overlap*boostfactors记录到boostedOverlaps。将连通的,且有前馈输入的突触数量overlap乘以促进因子boostfactor,该因子初始化是1,后续一直没有激活的柱状区域的因子会被提高。
3. 抑制过程。boostedOverlaps作为参数,由_inhibitColumns计算。在所有2048个列中选择激活程度最高的40个列。得到activeColumns。抑制过程中,关键参数_inhibitionRadius抑制半径,会依据激活的柱状区域的数量而增大或缩小。首先计算抑制区域,为(直径+1)为底,ColumnDimensions的维度,即柱状区域和输入输出sdr的维度为指数乘方。即由半径算面积。然后计算密度density,为入参numActiveColumnsPerInhArea要求的40激活列,除以抑制区域,即所有区域的2048.本例采用全局抑制,调用_inhibitColumnsGlobal,由密度还原得到激活列数numActive=40.对overlaps进行排列,得到激活程度最高的前40个列的下标。并且激活程度要大于stimulusThreshold(默认值为0).
4. 以上已经得到了sp的输出activeColumns。将sp的输出activeArray根据下标activeColumns置一即可。可以由activeColumnIndices = np.nonzero(activeColumns)[0]得到激活列在原始column列表中下标。如图所示的”sp output activeColumnIndices“。下面是学习过程。
5. _adaptSynapses。这一步是修改连通值。入参inputVector,activeColumns(这里是之前inhibitColumnsGlobal方法返回的下标)。更新_permanences,对于活跃的列(不活跃的列不变,如果这个列被激活,我们认为它识别了一种模式,那么我们让它更加专注于这种模式),获得其潜在连通池,对其所有的连通值_permanences,如果该位有输入则增大synPermActiveInc,如果没有则减小synPermInactiveDec。_connectedSynapses和_connectedCounts同步更新。在这个过程中,注意每一个列最小连通数要符合要求。这样做的后果,是使得每一个列,在其潜在输入范围内,倾向于模拟其输入。从全局看,这样做的后果是,每一个列,在其潜在输入范围内,为其输入寻找共有模式。
6. _updateDutyCycles更新占空比。即对于所有的列,计算到目前位置它的激活程度的和。和其激活的总次数。再除以周期数。
7. _bumpUpWeakColumns。增加不活跃的列的连通值。如果一个列的激活程度过低,即小于minOverlapDutyCycles最低占空比,它的连通值会被增加连通阈值的1/10。即所谓对输入的覆盖情况不是很好。
8. _updateBoostFactors 由激活次数的占空比,依据一个公式,修改列的促进因子。目的是为了达到D图的效果。
9. _updateInhibitionRadius 更新抑制半径。全局抑制不变。
10. _updateMinDutyCycles() 更新最小连通程度占空比。设置为当前最大的连通程度的1/1000
11. 综上,首先计算覆盖情况,乘以促进因子,然后在全局范围内进行抑制,取前40.最后进行学习,修改连通值。然后有两种独立的促进机制帮助一个列学习如何连接。一是overlap占空比过低,即对于输入的覆盖情况不是很好。这种情况提升其所有突触的连通值。二是激活次数过低,提升其促进因子。Sp_tutorial.py对sp进行了一些测试。
12. over