(HTM)使用HTM进行异常检测

如果你对HTM感兴趣,我建立了一个群,我们共同学习交流。515743445。

阅读本文前需要对HTM有基本的了解,建议阅读HTM白皮书。

本文研究使用HTM进行单变量的异常检测,并尝试复现了numenta的出租车异常检测结果。Numenta的异常检测项目在这里https://github.com/numenta/NAB。我们复现https://github.com/numenta/NAB/tree/master/results/numentaTM/realKnownCause下的numentaTM_nyc_taxi.csv的结果。

建议先阅读readme对NAB有个基本了解。

 

首先,在numentaTM_nyc_taxi.csv中我们看到,该出租车检测结果的异常分数一列,构成的图形,清晰的显示出了四个异常点,这与numenta的论文中的图形是一致的。

(HTM)使用HTM进行异常检测_第1张图片

我们不使用NAB提供的框架重复结果,采用直接调用algorithm的方式来复现。

代码如下

from nupic.algorithms.spatial_pooler import SpatialPooler as SP
from nupic.algorithms.backtracking_tm_shim import TMCPPShim as TM
from nupic.encoders.random_distributed_scalar import RandomDistributedScalarEncoder
from nupic.encoders.date import DateEncoder
from nupic.algorithms import anomaly
from datetime import datetime
import numpy as np
from tqdm import tqdm
from matplotlib import pyplot as plt

DATA_URL = "https://github.com/numenta/NAB/tree/master/data/realKnownCause"
PATH = "C:/Users/mi/PycharmProjects/nupic-master/nab/"
DATA = "nyc_taxi.csv"

value = np.loadtxt(PATH+DATA,usecols=(1),delimiter=',',skiprows=1,dtype=np.int32)
time = np.loadtxt(PATH+DATA,usecols=(0),delimiter=',',skiprows=1,dtype=np.str)

sp = SP(inputDimensions=(454, 1),
            columnDimensions=(2048, 1),
            potentialRadius=2048,
            potentialPct=0.8,
            globalInhibition=True,
            localAreaDensity=-1,
            numActiveColumnsPerInhArea=40,
            synPermInactiveDec=0.0005,
            synPermActiveInc=0.003,
            synPermConnected=0.2,
            dutyCyclePeriod=1000,
            boostStrength=0.0,
            seed=1956)

tm = TM(       numberOfCols=2048,
               cellsPerColumn=32,
               initialPerm=0.24,
               connectedPerm=0.50,
               minThreshold=13,
               permanenceInc=0.04,
               permanenceDec=0.008,
               predictedSegmentDecrement=0.001,
               newSynapseCount=31,
               globalDecay=0.0,
               activationThreshold=20,
               seed=1960,
               verbosity=0,
               pamLength=3,
               maxAge=0,
               maxSegmentsPerCell=128,
               maxSynapsesPerSegment=128,
               outputType='normal',
              )

dateEncoder = DateEncoder(timeOfDay=(21, 9.49))
randomEncoder = RandomDistributedScalarEncoder(resolution=422.03538461538466,seed=42)
def encode(date,value):
    t = datetime.strptime(date[2:-3], "%y-%m-%d %H:%M")
    dateSdr = dateEncoder.encode(t)
    valueSdr = randomEncoder.encode(value)
    sdr = np.concatenate((dateSdr,valueSdr))
    return sdr

prdictiveColumns = np.zeros(2048)
x = np.arange(0,10320)
y = []
for t, v in zip(time, value):#[:200]:
    sdr = encode(t, v)
    column = np.zeros(2048,dtype=np.int32)
    sp.compute(sdr, True, column)
    #print 'activateColumns:',activateColumns
    prdictiveColumnsSdr = tm.topDownCompute().copy()
    prdictiveColumns = prdictiveColumnsSdr.nonzero()[0]
    #print 'prdictivaColumns:', prdictiveColumns
    tm.compute(column, True,True)
    activateColumns = np.nonzero(column)[0]
    activateColumns = activateColumns.astype(np.int32)
    score = anomaly.computeRawAnomalyScore(activateColumns, prdictiveColumns)
    #print score
    y.append(score)
y = np.array(y)
plt.plot(x,y)
plt.show()

这里有几个注意点:

第一:我们使用nupic.algorithms.backtracking_tm_shim,该tm与标准tm实现不同,专门为异常检测做了优化,但是该方法官方已不再维护。

第二:encoder,sp和tm使用的参数,来自getScalarMetricWithTimeOfDayAnomalyParams方法,实际读取自nupic项目下的/src/nupic/frameworks/opf/common_models/anomaly_params_random_encoder/best_single_metric_anomaly_params_tm_cpp.json

第三:这些参数是numenta反复试验获得的最优结果。

 

然后我们获得了相同的结果:

 

(HTM)使用HTM进行异常检测_第2张图片

很抱歉之前两篇解读sp和tm的文章写的很杂乱,但是我不想改了。。。读代码嘛,一行行读就是了,写的还是很清晰的。里面几个核心类使用c++加速,但是并不影响阅读。基本上到这里再想深入学习HTM,就要看numenta的最新论文了,没有成熟和结构良好的代码和文档了。他们最新的几篇论文关于位置理论,其最新思想似乎是将位置信号作为tm的偏置输入,这样相比于本文中将两个编码器的结构直接相连的效果要好。

 

 

 

你可能感兴趣的