Skip to content
mattya edited this page Apr 2, 2015 · 7 revisions

#RNNこれくしょんRNNこれ

RNN-colleはRNN (Recurrent Neural Networks)を用いた機械学習ライブラリです。GPUによる高速化も可能。Reservoir ComputingやDeep LSTMといった最先端のRNNモデルで学習を行ったり、オリジナルのRNNを定義するのも簡単にできます。

特徴

  • 最新のRNNモデルを実装 - Reservoir computing, LSTM, ...
  • mshadowベースの実装 - CPU/GPUの切り替えが容易に可能
  • json formatのパラメタファイルで簡単に学習を管理
  • オリジナルのRNNアーキテクチャを定義することも可能

要件

  • CBLAS or MKL
  • C++ compiler (g++, icc, etc.)
  • python
  • numpy
  • wget
  • (optional) nvidia GPU & CUDA 6.5

Build

まず、fetch.shを実行する。これで必要なデータがfetchされる。次に、

  • GPUを用いるとき make gpu=1
  • 行列計算にMKLを用いるとき make mkl=1
  • 両方 make gpu=1 mkl=1

Tutorial

#####Multi layer perceptron 多層パーセプトロンでMNISTを学習する。 MNISTのデータは**./data/mnist/の中に、学習に用いるパラメタは./param_files/mnist.json**に記載されている。 numpyが使えるpythonのパスがpythonで無い場合は、mnist.jsonのpythonの項目を書き換える必要がある。

では、学習を開始しよう。

./bin/train < ./param_files/mnist.json > log.txt

log.txtには、

epoch: 1, train error: 0.056024, test error: 0.063052 epoch: 2, train error: 0.037949, test error: 0.044077 epoch: 3, train error: 0.024398, test error: 0.035643

のように、学習の進行が記録される。今回の設定では、errorの数値は誤答率で表される。10 epochごとに、学習したモデルの情報がtmp/mnist_model_10.txtといったファイルに記録される。30 epochもすれば、train errorは1%を切り、過学習状態となるであろう。

次に、この学習したモデルを用いて、テストデータ全てについて、各手書き画像がどの数字を表しているかを推定させてみよう。

./bin/train < ./param_files/mnist_predict.json

このコマンドを実行すると、./tmp/mnist_predict.txtに結果が出力される。結果の各行はそれぞれ、各テストデータに対するNNの最終層の出力を表す。これにsoftmax関数を通したものが、NNの予測した各数字に対する確率分布ということになる。

最後に、mnist.jsonのパラメタについて解説する。

"env": {
      "python": "python",  # pythonのパス
      "debug": false,      # debug mode 
      "prefix": "mnist"    # 生成されるファイルのprefix
      "mode": "train"      # train or predict
 }

modeを"predict"にすると、テストデータの入力に対する推定出力をファイルに書き出すモードになる。

"network": {
	"type": "MLP",    # ネットワークの種類
	"param": {
	     "layers": 4,                     # 層の数
	     "neurons": [784, 500, 200, 10],  # 各層のニューロン数
	     "hidden_nl": "tanh",             # 中間層の非線形関数
	     "out_nl": "none",                # 最終層の非線形関数
	     "loss": "category",              # 誤差の計算法
	     "shuffle": "full_shuffle",       # trainの際のshuffle
	     "dropout": false                 # dropout
	}
}

networkはネットワークの構造を指定する。上記のパラメタでは、以下の様な4層パーセプトロンが作られる。

in=>operation: Input(784)
h1=>operation: 500
h2=>operation: 200
out=>operation: Output(10)

in(right)->h1(right)->h2(right)->out
"data": {
      "type": "MNIST",         # データの格納形式
      "train_data": "./data/mnist/train-images.idx3-ubyte",
      "train_label": "./data/mnist/train-labels.idx1-ubyte",
      "test_data": "./data/mnist/t10k-images.idx3-ubyte",
      "test_label": "./data/mnist/t10k-labels.idx1-ubyte",
      "predict": "./tmp/mnist_predict.txt", 
                               # 予測結果の出力先(modeがpredictのとき)
      "n_train": 60000,        # trainデータの数
      "n_test": 10000,         # testデータの数
      "n_x_data": 784,         # dataの次元数
      "n_x_label": 10          # labelの次元数
      "load_model": false,     # 学習済みのモデルから再開するか
 },

dataではtrain, testデータの入出力ファイル、ファイル形式、次元数を指定する。

"learning": {
     "n_time": 1,             # BPTTの逆伝播ステップ数
     "n_batch": 60,           # batchサイズ
     "load_model": true,      # 学習済みのモデルから再開するか
     "init_epoch": 10,        # 何番目のepochから再開するか  
     "iter_per_epoch": 1000,  # 1回のepochで何batch処理するか
     "snapshot_interval": 10, # modelファイルを出力する頻度 
     "max_epoch": 100,        # 何epoch回すか
     "sgd": "rmsprop",        # 学習則 momentum or rmsprop
     "momentum": 0.9,         # momentum
     "decay": 0.001,          # weight decay
     "base_lr": 0.0001,       # learning rateの初期値
     "lr_mult_interval": 10,  # learning rateを変化させる頻度
     "lr_mult": 0.75,         # learning rateの変化倍率
}

learningでは学習時のパラメタを指定する。MNISTは時系列データではないので、n_timeは1である。


#####Reservoir computing RNNのひとつのアルゴリズムであるReservoir ComputingでNARMA30というタスクを学習しよう(narma.json)。NARMA30は次のような規則で生成される。vは入力であり、各時刻[0,0.5]の一様分布で生成される。この入力vに対するxが予測するべき出力である。今回のデータではk=30となっており、RNNは30ステップを超える長い時間相関を学習する必要がある。

    for i in range(1,tmax):
        for j in range(max(0,i-k), i):
            x[i] += 0.004*x[i-1]*x[j]
        x[i] += 0.2*x[i-1] + 0.01
        if i>=k:
            x[i] += 1.5*v[i]*v[i-k]

データはテキストファイルで、各行に、各時刻での入力データが数字で書かれている。

"network": {
     "type": "Reservoir_MLP",   # Reservoirの後ろにMLPを付けたもの
     "param": {
          "base_neurons": 200,  # Reservoirのニューロン数
          "scale": 0.95,        # Reservoirの時間スケール
          "layers": 4,          # MLPの層数
          "neurons": [200, 100, 100, 1],  # MLPのニューロン数
          "loss": "mse",        # 二乗誤差
          "shuffle": "single_series"  #  入力が一本の長い時系列
     }
}
"learning": {
     "n_time": 100,       # 1つのbatchで100ステップ連続で処理する
     "handover": true,    # batchを切り替えるとき、Reservoirを初期化しない
     "n_batch": 20,
     (以下略)
}

このパラメタで表されるネットワークの構造は、以下のようになる。 RMLP

Reservoir Computingは再帰結合の行列をランダム行列で初期化し、そのまま固定する。この部分は学習せずに固定することにより、RNNをBPTTで学習する際に生じるvanishing gradient problemを回避するのである。本ライブラリでは、固有値がscaleになるような直交行列で初期化される。

学習開始

./bin/train < ./param_files/narma.json > log.txt

学習後の様子。 narma_result


#####Deep LSTM 自然言語処理などに用いられる階層LSTMを用いて、シンプルな記憶タスクを学習しよう(recall.json)。

LSTM

ひとつのLSTMは、HiddenニューロンとCellニューロン、そしてその間の結合からなる。Cellは記憶を担当するニューロンで、情報が書き込まれたら、次に別の情報が来るか、忘却信号が来るまで今の値をずっと保持するようにできている。HiddenニューロンはCellから情報を取り出し、出力を生成する。この際、1ステップ前のHiddenの値によりCellに書き込む・読み込む・忘却させる情報が決定される。

本ライブラリにおけるLSTMの詳しい動作は、以下の通りである(http://arxiv.org/abs/1410.4615より引用)。 Alt text

さらに、このLSTMを階層状に重ねることで、RNNとLSTMを組み合わせたようなモデルを実現する。recall.jsonのパラメタでは、以下の様なネットワークが構築される。LSTMのHidden, Cellニューロンはそれぞれ30ニューロンずつとなる。 Alt text

"network": {
     "type": "Stacked_LSTM_MLP",
     "param": {
          "layers": 2,               # LSTMの層数
          "base_neurons": 30,        # 各LSTMの基準ニューロン数
          "layers2": 3,              # MLPの層数
          "neurons": [50, 20, 1],    # MLPのニューロン数
          "out_nl": "sigmoid"        # MLPの出力にsigmoid関数
          "loss": "nll",             # negative log likelihood
          "shuffle": "multiple_series",
     }
}

データはバイナリファイルで、n_time*n_x個のint型のデータが格納されている。

学習後 Alt text

プログラムの構成

  • Node Nodeはニューロン集団を表す。集団内のニューロンの出力を格納するとともに、入力Nodeでは入力データそのものも保持する。
  • x_batch_cpu - ニューロンの出力。[時間][バッチ][データ]の3次元。
  • x_batch_gpu - ニューロンの出力のGPU側へのコピー
  • dx_batch_cpu - ニューロンの誤差。Back propagation用。
  • dx_batch_gpu - ニューロンの誤差のGPUへのコピー
  • x_all - 入力データ全体

入力Nodeでは、まずx_allからx_batch_cpuに一部のデータがコピーされ、x_batch_gpuにさらにコピーされ、forward, backwardの後にdx_batch_gpuに値が入り、updateでそれが使われる。

  • Layer
  • Network
  • Main
  • Parameter files
  • IO
  • Util

Detailed usage

  1. Preparing data
  2. Choose Node
  3. Choose NN
  4. Parameter file
  5. Learning
  6. Using model file

Make your own RNN

  1. Define Node
  2. Define NN
  3. Original parameter
  4. Build

TBA

  • Network definition by parameter files
  • more sophisticated loss, shuffle type impl
  • partial loading
  • Image Node, Im2Col, Col2Im, Convolution layer
  • NADE Layer
  • Neural Turing Machine
  • Q-Learning

オリジナル版はここで作られました

Clone this wiki locally