学習の時はDropoutを適用、予想の時はDropoutは外したほうがいいのでしょうか?

3,615 views
Skip to first unread message

yasuo kasajima

unread,
Jan 18, 2016, 2:06:29 AM1/18/16
to Chainer Japanese User Group
はじめまして。@kasajei です。
最近、Chainerを使って、機械学習を勉強し始めています!
まだ初心者なので、場違いな質問をしてしまったらすいませんがよろしくお願いします。

今、多層パーセプトロンでのMNISTの学習をしています。
入力層784→中間層1024→出力層10の3層のネットワークで行っています。

普通に行った場合97%ぐらいの制度が出ます。

次に、ドロップアウトを入れてみて、やると95%ぐらいまで精度が落ちます。
学習自体はうまく行ってるように見えるのですが、
テストデータに対しての正答率が悪いように見えます。

質問なのですが
- これぐらいのネットワークではドロップアプトは効果がないのでしょうか?
- 学習時にドロップアウトを適用し、予想時にはドロップアウトしない方が良いでしょうか?

また予想時にドロップアウトをはずす場合、
Chainerではどのように実装したらいいでしょうか?

あと、Autoencoderでのプレ学習もやってみたのですが、
それほど精度が上がらず。。

コードはちょっと雑なのですが、こちらに公開していますので、
もしよろしければご覧いただけると嬉しいです

認識違いなどがあれば、教えていただけると助かります!
( Chainerとは本質的には関係ない質問申し訳ないです。。
このような質問ができる場所が他にあれば教えていただけると、
そちらも助かります!)

よろしくお願いします!

kitanokumo

unread,
Jan 19, 2016, 3:54:52 AM1/19/16
to Chainer Japanese User Group
リンク先によればもう解決しているかもしれませんが trainにbooleanを入れることでDropoutするしないを切り替える事ができます。
デフォルトではdropout_rate=0.5なので、半分のユニットを切り捨た状態でpredictしたら当然精度は落ちると思います。

>dropout関数にtrainというフラグがあるからこれは予想するときには変えるべきってことよね。ここはChainer側でなんとかしてほしいなぁって思ったりする。

これの意味がよくわからなかったのですが、trainをハードコーディングしないといけないから、という事でしょうか。
MNISTMLPerceptronの__init__ではなく__call__でtrainを設定すればいいのではないでしょうか。
勘違いだったらすみません。

yasuo kasajima

unread,
Jan 19, 2016, 9:38:21 PM1/19/16
to Chainer Japanese User Group
ありがとうございます!やっぱりそうなんですね!

__call__でtrain設定できるのが良いと思ってます!
ただ、NNをL.Clasiffierのpredictorとして設定したいのですが、
L.Classifierは__call__の中で、predictor(x)としか呼んでくれないのです。
ここで、predictor(x, train=False)と呼んでくれれば嬉しいのですが。

なので、MNISTMLPerceptronの__call__で設定しても、L.Classifierを使う限りは、
trainを設定できず、MNISTMLPerceptronにtrainをもたせるか、L.Classifierを書き換えるか、
しか方法がないのかなぁと思ったのですが、どうでしょうか?
まだ始めたばっかりなので、見当違いのことを言っていたら申し訳ありません!


2016年1月19日火曜日 17時54分52秒 UTC+9 kitanokumo:

kitanokumo

unread,
Jan 20, 2016, 8:01:48 AM1/20/16
to Chainer Japanese User Group
なるほど確かにそうですね。これでどうでしょうか。

def __call__(self, x):
    h1 = F.dropout(F.relu(self.l1(x)), train=not x.volatile)
    h2 = F.dropout(F.relu(self.l2(h1)), train=not x.volatile)
return self.l3(h2)


__call__に入力されたx(Varible)は学習時はvolatileがOFF(False)、学習しない時はON(True)になっているのでそれを利用します。
それをnotで反転させて学習時はdropoutのtrainにTrueを、学習しないときはFalseを与えています。

volatileでon/offを設定するときはVariableを作る時に設定します。
volatileの内部は1.5からflagというものに変更になったらしいので、1.5以降は以下の3つは全部同じと解釈されるようです(多分)。
'on' 'ON' True
'off' 'OFF' False

学習時 どの書き方も同じ
x = Variable(xp.asarray(dataset), volatile='off')
x = Variable(xp.asarray(dataset), volatile=False)
x = Variable(xp.asarray(dataset)) #デフォルトがoffなのでこれでも

テスト時
x = Variable(xp.asarray(dataset), volatile='on')
x = Variable(xp.asarray(dataset), volatile=True)

(1.4以前の場合はTrue/Falseのみしか駄目だと思います)

ただこれだと学習時とテスト時で分岐コードになってしまうので
trainにTrue/Falseを入れておいて、これで学習/テスト時共通のコードになります。
x = chainer.Variable(xp.asarray(dataset), volatile=not train) #notで反転させて入力
普通はこう書くと思います。

もしかしたら1.5以降はもっとスマートなやり方があるのかもしれませんが参考になれば幸いです。

yasuo kasajima

unread,
Feb 12, 2016, 4:02:20 AM2/12/16
to Chainer Japanese User Group
(遅くなりすいません!)
なるほどです!ありがとうございます!

volatileってもともと何に使うものなのでしょうか。
特に副作用なければこれで良さそうですね!


2016年1月20日水曜日 22時01分48秒 UTC+9 kitanokumo:
Reply all
Reply to author
Forward
0 new messages