Chainerで多層パーセプトロンを実装した

研究室に配属されましたが,相変わらず対してやることもなくてヒマです.*1

なので今週はChainerを使って多層パーセプトロンを実装したりして遊んでいました.

(手を動かしてなにかやって,なにかをやった気になっていないと元気がなくなるので…)

実装した話

Chainerの場合,アップデートによる仕様変更とかが原因でver 1.5以前のコードは使い物にならないと聞きました. なのでとりあえず公式チュートリアルをやるのが良いかと思い.Chainerのチュートリアルをやりました.

で,チュートリアルのコードをベースとして多層パーセプトロンを組んで,xorを学習させれば良いと思って書いたコードが以下

gist.github.com

最終層を2層にして,交差エントロピーをコスト関数にして識別を行うコードです. lossの値が0.3くらいに収束してしまうのはどうにかならないのか…と思ったのですが,これはsoftmax関数で識別を行う以上仕方ないらしい.

交差エントロピーの代わりに二乗誤差をコスト関数に使うやつだと,

gist.github.com

こうなりました.

型が合わなくて困っている話

実は上のコードは,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

となってます.

ここでlossfunaccuracyの両方に引数tが与えられていますが,このときlossfunに指定したものによってはtの型が一致せず,エラーとなってしまいます. 例えば,二乗誤差をlossfunとして設定すると,引数tnp.float32型でないといけませんが,一方accuracyの指定する型はnp.int32となっています.

つまりchainer.links.Classifierを使って同時にlossとaccuracyを求めることができないわけです. これを回避するには,チュートリアルのように,独自にClassifierを定義することなどが考えられます.

今回は「そもそもaccuracyとか要らねえな…」と思ったので,Classifierを定義することなく,MyMLPから直接modelインスタンスを生成することにしました.*2

次は

LSTMで遊んでみようかなと思っています.

*1:かなりヒマです

*2:すごいダサい書き方なのは否めない