Chainerで多層パーセプトロンを実装した
研究室に配属されましたが,相変わらず対してやることもなくてヒマです.*1
なので今週はChainerを使って多層パーセプトロンを実装したりして遊んでいました.
(手を動かしてなにかやって,なにかをやった気になっていないと元気がなくなるので…)
実装した話
Chainerの場合,アップデートによる仕様変更とかが原因でver 1.5以前のコードは使い物にならないと聞きました. なのでとりあえず公式チュートリアルをやるのが良いかと思い.Chainerのチュートリアルをやりました.
で,チュートリアルのコードをベースとして多層パーセプトロンを組んで,xorを学習させれば良いと思って書いたコードが以下
最終層を2層にして,交差エントロピーをコスト関数にして識別を行うコードです. lossの値が0.3くらいに収束してしまうのはどうにかならないのか…と思ったのですが,これはsoftmax関数で識別を行う以上仕方ないらしい.
交差エントロピーの代わりに二乗誤差をコスト関数に使うやつだと,
こうなりました.
型が合わなくて困っている話
実は上のコードは,MyMLPクラスの中にforwardメソッドを定義しているあたりで今風のChainerっぽい書き方ではないんですね.
今風に書くならば,チュートリアルのコードのように,callメソッドを定義して,その上でchainer.links.Classifier
にMyMLPクラスを食わせてやるべきなんでしょう.
ただそれをやると,型のトラブルでうまくいかなかったので,あえてレガシーな書きかたしています.
具体的には. chainer.links.Classifier
の中身を見てみるとわかるのですが,
self.y = None self.loss = None self.accuracy = None self.y = self.predictor(x) self.loss = self.lossfun(self.y, t) if self.compute_accuracy: self.accuracy = accuracy.accuracy(self.y, t) return self.loss
となってます.
ここでlossfun
とaccuracy
の両方に引数t
が与えられていますが,このときlossfun
に指定したものによってはt
の型が一致せず,エラーとなってしまいます.
例えば,二乗誤差をlossfun
として設定すると,引数t
はnp.float32
型でないといけませんが,一方accuracy
の指定する型はnp.int32
となっています.
つまりchainer.links.Classifier
を使って同時にlossとaccuracyを求めることができないわけです.
これを回避するには,チュートリアルのように,独自にClassifierを定義することなどが考えられます.
今回は「そもそもaccuracyとか要らねえな…」と思ったので,Classifierを定義することなく,MyMLPから直接modelインスタンスを生成することにしました.*2
次は
LSTMで遊んでみようかなと思っています.