FUNC-RETURN

システム、インフラ、AI、デザイン

【HTM - Python】Sine関数の予測、新皮質モデルで機械学習

f:id:kijnmb-1110:20171231231233p:plain





HTM記事全体のの目次は以下。

【HTM - Python】新皮質モデルで機械学習(目次) - FUNC-RETURN

Sine関数の時系列データを生成

とりあえず、1000個のSineウェーブのデータをcsvとしてsine.csvに書き出します。

# -*- coding: utf-8 -*-

import csv
import math



def generateData(num, file_name):
  '''
  Generate Sine wave data.

  Args:
    num: number of data.
    file_name: output csv file name.
  '''

  file_handler = open(file_name, 'w')
  writer = csv.writer(file_handler)
  writer.writerow(['angle', 'sine'])
  writer.writerow(['float', 'float'])
  writer.writerow(['', ''])

  for i in range(num):
    angle = i * math.pi / 50.0
    sine_value = math.sin(angle)
    writer.writerow([angle, sine_value])

  file_handler.close()



if __name__ == '__main__':
  generateData(num=1000, file_name="sine.csv")

スウォーミング
モデルパラメータを自動的に取得するためにSwarmingを実行しておきます。

haretoke.hatenablog.jp

OPF-API

モデルパラメータからモデルを生成

opfのAPIで提供されるModelFactoryを使って生成します。

Online Prediction Framework (OPF) — NuPIC 1.0.3 documentation

from nupic.frameworks.opf.modelfactory import ModelFactory
from swarm.model_0.model_params import MODEL_PARAMS
...

model = ModelFactory.create(MODEL_PARAMS)
model.enableInference({
  "predictedField": "sine"
})


opfを一回実行

nupic.frameworks.opf.model.Model.runで一回分実行します。
今回のサインウェーブ予測ではforのループ毎にこれを実行してます。

Models — NuPIC 1.0.3 documentation

result = model.run({
  "angle": angle,
  "sine": sine
})

InferenceShifter

上記nupic.frameworks.opf.model.Model.runは、T(i)のデータをインプットしてT(i + 1)の時の予測値をアウトプットします。

なので、例えば、for文でループして実行する際に、前のループの予測値と今のループの正解インプットデータを比較したくなります。
そういう際に、このShifterを使うと便利です。


Shifterのドキュメント
Model Results — NuPIC 1.0.3 documentation


Shifterのコード
nupic/inference_shifter.py at master · numenta/nupic · GitHub

from nupic.data.inference_shifter import InferenceShifter

...

result = model.run({
  "angle": angle,
  "sine": sine
})

# 一つ前の予測がシフトされたModelResultオブジェクトが返ってくる。
result = shifter.shift(result)

Let's Sine関数予測

グラフの説明
上のグラフは、青のラインがインプットデータ(正しいサインウェーブ)で、緑のラインがNupicが予測したラインです。
下は、異常検知を示すグラフです。
これは、SwarmingでinferenceTypeTemporalAnomalyにしたので、異常検知もしてくれるモデルが作られたからです。
はじめの方は、HTMモデルが、頻出する時間シーケンスをまだ学習できてないので異常値が高くなり、
進んでいくに従って、パターンを学習していくので異常値が下がって行きます。


実行ファイルのコード

# -*- coding: utf-8 -*-


import csv

from nupic.data.inference_shifter import InferenceShifter
from nupic.frameworks.opf.modelfactory import ModelFactory
import nupic_output

from swarm.model_0.model_params import MODEL_PARAMS


def createModel():
  '''
  Create nupic.frameworks.opf.model.Model from ModelFactory.

  Return:
    An opf model.
  '''

  model = ModelFactory.create(MODEL_PARAMS)
  model.enableInference({
    "predictedField": "sine"
  })
  return model



def runModel(model, file_name):
  '''
  Run predictions by a given model.

  Args:
    model: Opf model.
  '''

  input_file = open(file_name, "rb")
  csv_reader = csv.reader(input_file)

  # ヘッダーをスキップ
  csv_reader.next()
  csv_reader.next()
  csv_reader.next()

  shifter = InferenceShifter()

  # これは、結果を描画する用のクラス。
  # 実際に書かれてるのはMatplotlib周りの実装
  # 内容に関してはレポジトリでみてください。
  output = nupic_output.NuPICPlotOutput("Sine", show_anomaly_score=True)

  for row in csv_reader:
    
    angle = float(row[0])
    sine  = float(row[1])

    # Modelを一回実行
    result = model.run({
      "angle": angle,
      "sine": sine
    })

    # 今のインプットと一つ前の予測値が入ったModelResultを生成
    result = shifter.shift(result)

    # NuPICPlotOutputで図が更新される
    output.write(angle, sine, result)

  input_file.close()
  output.close()



if __name__ == "__main__":
  model = createModel()
  runModel(model=model, file_name="sine.csv")

コード全体は以下。
github.com



f:id:kijnmb-1110:20171231231233p:plain