HTMのサンプルを眺めてみた


HTM（Hierarchical Temporal Memory)
というのはJeff Hawkinsの「<a href="http://www.amazon.co.jp/dp/4270000600">On Intelligence(邦訳：「考える脳 考えるコンピューター」）</a>」で原理が紹介されたニューラルネットワークの一種で、大脳の新皮質の仕組みにヒントを得ている。

人間の知性を特徴づけているのは、哺乳動物に特有で、しかも人間では他の哺乳動物に比して巨大な新皮質だろう、というのは納得しやすい仮説だ。 
そして、視聴覚野や言語野といった重要な機能が分布していることもよく知られている。
ところが、新皮質自体はその担う機能の多様さにくらべて構造は極めて均一でシンプルである。おおよそ６つの層をなす、テーブルナプキンのようなもの、でしかない。ただし、皮質上の各点をつなぐ結線は非常に複雑になっている。

HTMは大脳新皮質の構造と機能をかなり忠実にコンピュータ上に再現したものと言える。そのアイデアの核心については上述の著書を読んでもらえば良いと思うし、詳細なアイデアや実装のヒントについては日本語訳の文書が公開されている。https://numenta.com/assets/pdf/whitepapers/hierarchical-temporal-memory-cortical-learning-algorithm-0.2.1-jp.pdf

そのJeff Hawkinsが立ち上げた人工知能研究組織のNumentaがHTMの実装をgithub上で公開している　https://github.com/numenta/nupic　ので、以下はサンプル https://github.com/numenta/nupic/tree/master/examples をざっと触ってみたメモ。

※公開されたAPIではないので、サンプルの内容は予告なく随時更新される可能性があります。

なお、順序は自分が基礎的と思えたものから並べてある。numentaのガイドに沿っているわけではない。

大抵のサンプルはPythonのスクリプトで、`phthon スクリプト名` だけで実行できる。

## binding : nupicのPython ライブラリの使い方

公式のAPIではないが、HTMに関係する基本的なデータ構造やアルゴリズムの応用方法などを知ることができる。

- sparse_matrix_how_to.py : HTMで使われるニューロンのデータは行列の形をしていることが多い。そして、大抵の場合、ほとんどのニューロンは活性化していないので、それに対応する行列の要素もほとんど０で、０以外の値はまばらにしか存在しない。それをsparse（疎）な状態と呼ぶ。行列が疎であることを仮定すると、効率良い計算アルゴリズムがnumpyなどのライブラリに揃っているので、nupicではそれを利用して組み立てられている。（nupic.coreのC++実装ならばこのあたりはGPGPUで実装されるだろう）ここではSparseMatrixというクラスをnupic.bindings.mathから呼び出した演算の例を示す。
    1.  SparseMatrixの型の指定
    1.  ゼロを判定するための誤差（ε：global epsilon）の指定。32bitの浮動小数点の場合は10のマイナス６乗
    1. 疎な行列の生成 `s = SparseMatrix([[1,2],[3,4]], dtype='FLoat32')`　略記法として`SM32`が使える
    1. 行列に関する各種getter：行の数、列の数、零行列か？etc.
    1. 行列の個々の要素やスライスへのアクセス方法
        - ：s[0,0]、s.getOuter、s.getElements, s.getSlice 
        - 全要素への一括操作：s.setRowToZero, s.setColToZero
        - ゼロでない行、列の取り出し：s.colNonZeros, s.rowNonZeros
    1. 行列の行、列の数を変更する：
        - s.reshape(新しい行数、新しい列数)、s.resize
        - s.addRow, s.deleteRows
        - 閾値によってゼロに設定する：s.normalize, s.threshold, s.thresholdRow, s.thresholdCol
    1. 各要素の操作
        - elementNZInverse 非零要素の符号反転、elementNZlog 非零要素の対数をとる、など
    1. 行列とベクトル、行列と行列同士の演算
       - 行列の積、線形結合
       - 疎な行列への定数を掛ける
    1. 数値演算
    1. 数え上げ、検索
        - countWhereEqual(比較対象)
        - whereEqual(比較対象）
- svm_how_to.py Support Vector Machine(SVM)をnupicのライブラリを使って構成する例（参考：http://home.hiroshima-u.ac.jp/tkurita/lecture/svm.pdf 、http://qiita.com/nonbiri15/items/3b0440a95e61f134413d ）手持ちのデータの性質をあらかじめ把握するのには有効な手法なので、サンプルに用意されているのだと思われる。
    - ライブラリ：nupic.bindings.algorithms
    - SVMのclassifier(分類器)オブジェクトの構成と利用できるメソッド
        - nupic.bindings.algorithms.svm_dense
            - 学習データ入力：add_sample()
            - pickling(永続化)：load(dump())
            - 学習：train()
            - predict()
        - nupic.bindings.algorithms.svm_01

## sp 空間プーリング

HTMのクラスは内部にこれまで見てきたregionやlinkを含んでいる。あらかじめプリセットされたクラスやパラメータを与えることで、簡単にHTMをセットアップできるようになっている。

- hello_sp.py：HTMの空間プーリングの動作のデモ
    - region内部のセルが数多くあっても、同時に発火するのはその数％
    - 同じ入力があれば、出力も同じになることは保証されている
    - 入力のうち、１０％、２０％ものノイズが混入していても、同じ出力を再現できる安定性がある。パターンにノイズや変形、運動や欠落があっても認識が安定することを保証できる。

## tp 時間プーリング

HTMの基本機能として、時間的なシーケンスを学習して、入力の中にシーケンスの先頭部分を検出できたら、それがまだ完了していないうちからシーケンスの後続部分を予測できる。このディレクトリはそのデモやテストケースを集めたもの。

- hello_tm.py：時間プーリングによる単純な文字シーケンスの予測のデモ-  -- - - - tp_test.py：時間プーリングのテストをまとめて起動

## prediction HTMの応用として、シーケンスの予測の機能のデモ
### category_prediction 文章を読み込んで単語とそのつながりの確率などを計算するデモ

### experiments 

inspect_test.py を実行することでHTMによる各種の予測機能の実験的機能を確認できる。
- confidenceTest：重複する部分をもつ２つのパターンについてその途中まで入力された場合、どれくらいの確信度があるか、など。
- dutyCycle：（TBD）

## audio stream マイクへの入力を学習して、目新しいパターンがあればanomalyとして表示
HTMの時間プーリングによるシーケンスの学習と予測の機能によって、予測と大きく食い違うケースをanomalyとしている。
Mac OSX推奨。
なお、マイクからの入力はそのまま波形をサンプリングするのではなく、周波数領域に変換して、そのうち主要な周波数成分をとりだして、その変遷をシーケンスとして学習している。
なお、HTMのregionに入力するには、入力パターンはsparse(疎。ベクトルの値のほとんどがゼロ)でなくてはいけないのでSDR(sparse distributed representation)に変換されている。

## network ：HTMのregionをつなぐ入出力のネットワーク規定するAPIの紹介

nupicのAPIを使えば、発火した情報の伝達などの機能が自動的に提供されるので、コーディングする必要がなくなる。
regionの間の階層構造を定義することもできる。

### region(HTMのセルの集まった領域) のクラス定義

Pythonでは`nupic.regions.PyRegion.PyRegion` のサブクラスとして定義。

### サンプルPythonスクリプトの説明

ｌｓ- /custom_region/identity_region.py : PyRegionクラスのpublicなメソッドをoverrideすることでカスタマイズして、入力をそのまま出力するRegionを定義した例。
- network_api_demo.py：ネットワークを生成し、実行する
    - addRegion(名前、クラス、パラメータ)
    - encoder メンバー：入力データをregionで処理できる形に変換する
    - link(A, B)：region AとBを結びつける
    - run()：ネットワーク機能を実行
- core_encoders_demo.py：`extra/hotgym/rec-center-hourly.csv`のデータを読み込んで異常を検知するためのanomaly regionを定義してrun
    - sp region: SPRegion センサーとクロックのタイムスタンプ入力がlinkされている。入力のencoderとしてnupic.encoders.DateEncoderが使われている
    - tp region: Temporal Memoryとして、下位のsp regionからのパターンに対して推論を行う
- custom_region_demo.p：自作の特殊なリージョンのライブラリをimportして使用するデモ。importに先立って、sys.path.append()しておく必要がある。
- hierarchy_network_demo.py：大脳新皮質をモデルにしたregionの階層の例。空間的プーリングを行うregionと時間プーリングを行うregionの２つを含む層の上に、パターンを分類する層がlinkされている。パターンに分類不能はanomalyがあるとエスカレーションが上がる
- temporal_anomaly_network_demo.py：HTMではよく使われるhotgymの温度管理のネットワーク構成のサンプル。nupic.engine.common_networkというクラスが使われている以外は`network-api-demo.py`と同じ出力をする。


## swarm：HTMアプリケーション設計
データ(フロー）の集まりをどうつなぎこんでいくか。
ここが人手がかかるのは仕方ない。人間はそんなことしなくてもできるじゃないか、と言うなかれ。それは進化と自然淘汰の仕事だった。神経の接続や脳の他の部位との協調が脳の機能分化を促進したのだろう。
結局のところ、ニューラルネットワークが「役立つ」かどうかの評価は、手法のユーザーがこの段階のコストをどう評価するかにかかっているのかもしれない。

参考：https://www.youtube.com/watch?v=xYPKjKQ4YZ0 - Swarming in NuPIC 

## opf：Online Prediction Framework （HTMをベースにした予測アプリケーションフレームワーク）のサンプル
詳しくは　https://github.com/numenta/nupic/wiki/Online-Prediction-Framework　を参照。