Chainerでニューラルネットワーク、RNN、CNNを実装してみた

RNNの実装の勉強もしました。

今回は整理と備忘録も込めて、Chainerでニューラルネットワーク、リカレントニューラルネットワーク、畳み込みニューラルネットワークの実装について記します。

ニューラルネットワーク(Neural network; NN)

順伝播型のニューラルネットワークです。

簡単な練習問題として、アイリスのデータを分類するモデルを書きました。

ニューラルネットワークを使うまでもない問題ですが、実装の仕方の勉強のため、基本的な問題にしました。

各コードでやっていることを理解すると、別の問題も書くことができますし、他のニューラルネットワークへの参入もグッと楽になりました。

ChainerによるNNの実装1

ニューラルネットワークの実装です。

最後の活性化関数にはソフトマックスを使っているパターンですが、当然シグモイド関数を使った実装もありです。

GitHub: https://github.com/Gin04gh/samples_py/blob/master/NeuralNetwork_Chainer_ver1.ipynb

ChainerによるNNの実装2(classifier、training使用)

追記(2017-08-15)

今はclassifierクラス、trainingクラスを使用も推奨されていますので、同じ問題で実装したコードも記します。

GitHub: https://github.com/Gin04gh/samples_py/blob/master/NeuralNetwork_Chainer_ver2.ipynb

再帰的ニューラルネットワーク(Reccurent neural network; RNN)

系列データを扱うことに優れた構造のニューラルネットワークです。

RNNは前の時刻の隠れ層ベクトルと現時刻の入力ベクトルを使って、現在の隠れ層ベクトルを更新することで、任意の長さの入力履歴を考慮した出力を得ることができます。

詳しい説明は省略しますが、これは構造的に深い層のニューラルネットワークを学習することと同じことになり、層が深いネットワークほど、勾配爆発や勾配消失といった問題により誤差が伝播しづらくなっていくため、普通に構築しただけでは、せいぜい時系列3つ4つ前程度しか記憶しません。

これを改善するために、遠い隠れ層を直接参照できるような仕組み(ゲート)を加えたRNNが提案されています。

その隠れ層の保持の仕方なども調整するパラメータを用意して、同時に学習させることで、過去の記憶力をより向上させたRNNとしてLSTM(Long-short term memory)やGRU(Gated reccurent unit)というものがあります。

現在では、RNNといえば通常LSTMやGRUなどのゲート付きのRNNを指すことが一般的なようです。

下記は、LSTMで正弦波を予測するモデルの実装になります。

ChainerによるRNN-LSTMの実装1(F.lstm)

GitHub: https://github.com/Gin04gh/samples_py/blob/master/LSTM_Chainer_ver1.ipynb

ChainerによるRNN-LSTMの実装2(L.LSTM)

上記の実装はLSTMのゲートがどういう構成をされているのかを理解していなければ、少し直感的にわかりづらいところもありますが、Chainerではより簡単なLSTM関数が用意されていますので、場合によればこっちの方が簡潔で良いと思います。

RNNで計算した隠れ層を別のNNやCNNに用いるなどの複雑なネットワーク構成にする場合は、上記のコードで理解した方が自由度が高くて扱いやすいかもしれません。

同じ問題で、LSTM関数を使った実装が下記になります。

GitHub: https://github.com/Gin04gh/samples_py/blob/master/LSTM_Chainer_ver2.ipynb

RNN-LSTMの実装における、classifierクラス、trainingクラスの使用について

追記(2017-08-15)

RNNではバッチの形や、読み込ませ方が他のモデルと若干異なるため、IteratorクラスとUpdaterクラスを自分で改修しなければならないようです。

以下が参考です。

https://github.com/chainer/chainer/blob/master/examples/ptb/train_ptb.py

正直、RNNを扱う機会自体そんなに多くありませんので、ここまでやる気は起きませんでしたので、実装は省略します。

またやらなければならなくなった際に勉強して、コードを追記することにします。

追記(2017-09-23)

余談ではありますが、RNNで覚えさせたベクトルを最終的に分類タスクに用いたいなどであれば、ネットワークの作り方次第で、バッチの形を他のネットワークと同じように作れますので、そのままTrainerクラスを使うことができます。

下記のLSTMの実装が参考です。

CNN、RNNで文章分類を実装してみた
深層学習において文脈情報を学習させる方法としては、再帰的ニューラルネットワーク(RNN)を用いる方法と畳み込みニューラルネットワーク(CNN)を用いる方法があります。今回はそれぞれの方法で、文章を学習させてラベル分類を行うモデルを、Chainerを使って実装し...

畳み込みニューラルネットワーク(convolution neural network; CNN)

順伝播型ニューラルネットワークのような全結合層だけでなく、畳み込み層とプーリング層から構成されるニューラルネットワークです。

特に画像処理の分野において成功を収めている手法です。

これも詳しくは省略しますが、画像に対して小さな窓(フィルタ)をスライドしていきながら値を取得し、集約(最大プーリングや平均プーリング)することで、画像の特徴的な部分を抽出して、それらの情報を使ってネットワークを計算します。

ChainerによるCNNの実装1

GitHub: https://github.com/Gin04gh/samples_py/blob/master/ConvolutionalNeuralNetwork_Chainer_ver1.ipynb

ChainerによるCNNの実装2(classifier、training使用)

追記(2017-08-15)

こちらもclassifierクラス、trainingクラスを使用した例を記します。

GitHub: https://github.com/Gin04gh/samples_py/blob/master/ConvolutionalNeuralNetwork_Chainer_ver2.ipynb

追記(2017-08-15)

以前に記載していた実装コードでは、optimizerの部分が、

としておりました。

これに対し、先日コメントで、エポックごとにoptimizerの初期化するのはなぜか、とのご質問をいただきました。

これは、私が参考にしたコードがこのようになっていたため、深く考えていませんでしたが、誤りです。

SGDなどの場合は、これでも問題ない(と思う)のですが、上記のようにAdamの場合は、その時のエポックでの学習率が、前のエポックでの誤差に依存するため、上記のようにオプティマイザーをエポックごとに初期化してしまうと、学習率が初期値から変化しなくなるため、不適切だと思います。

ネット上でも、コードが混合していますので、注意が必要です。

コメントしていただいた方、ありがとうございました。

追記(2017-08-31)

PyTorchの実装もまとめてみました。

追記(2017-10-24)

TensorFlowも実装してみました。

TensorFlowでニューラルネットワーク、CNNを実装してみた
今回は、TensorFlowでニューラルネットワーク、畳み込みニューラルネットワークの実装について記します。以前にChainerやPyTorchでも各種ニューラルネットワークを実装していますので、今回も同様のタスクを実装してみます。TensorFlowもはや紹介する必要もないかも...
 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です