Chainer 1.6 で dropout を使う練習のメモ。
使い方が正しいかはよくわからないが、
結果からいうとこれにより過学習は避けられて、
評価用のデータセットに対してもそこそこよい推定ができるようになったので、
正しい使い方だったのではないかと思う。

python シェルで Chainer を始める準備。
各種パッケージをインポートする。

import numpy as np
import chainer
from chainer import cuda, Function, gradient_check, Variable, optimizers, serializers, utils
from chainer import Link, Chain, ChainList
import chainer.functions as F
import chainer.links as L
import matplotlib.pyplot as plt

多層パーセプトロンを作成するため、以下のクラスを定義をする。

class MyNN(Chain):
    def __init__(self, in_size, mid1_size, mid2_size, out_size):
        super(MyNN,self).__init__(
            layer1=L.Linear(in_size, mid1_size), 
            layer2=L.Linear(mid1_size, mid2_size),
            layer3=L.Linear(mid2_size, out_size),
            )
        self.train = True
        self.dr = 0.5
    def set_train_state(self, _train):
        self.train = _train
    def set_dropout_r(self, _dr):
        self.dr = _dr
    def __call__(self, x):
        h1 = F.dropout(F.relu(self.layer1(x)), train=self.train, ratio=self.dr)
        h2 = F.dropout(F.relu(self.layer2(h1)), train=self.train, ratio=self.dr)
        h3 = self.layer3(h2)
        return h3

赤字で示したところに dropout 関数が使われている。
今回は中間層の2層にのみ dropout を適用した。
このクラスを使って、layer1, layer2 のセル数を適宜設定して、

mnn = MyNN( len(data), layer1, layer2, len(result) )
model = L.Classifier(mnn, lossfun=F.mean_squared_error)
model.compute_accuracy = False
mopt = optimizers.SGD(0.003)
mopt.setup(model)

というように optimizer を作成する。

mnn.set_train_state(True)

として学習をすると、dropout が効いてデフォルトで 0.5 の割合でセルを dropout して学習を進めることができる。
学習を進める(ウェイトを変更する)には

mopt.update(model, data, result)

を実行する。
dropout を使わずに学習するには

mnn.set_train_state(False) 

としてから、update を実行する。dropout を使わずに学習した場合、学習用データセットに対してきわめて良く mnn の出力と result が合うようになる。
しかし、評価用データセットに対しては mnn の出力がなかなかうまく result を再現しない。

例を以下に示す。まず最初の図が学習データセットに対する結果。成長曲線を示すデータを再現する NN を学習したところ、NN の出力(青色線)が丸赤線(実データ)と、とても良く一致した。



ところが、評価用のデータセットに対しては、青線、つまり NN の出力がデータに合うものもあれば、大きく外れるものもあった。



そこで、

mnn.set_train_state(True)

として dropout を使うようにして学習してみると、学習用データセットに対する一致度は低下したが、



評価用データに対してもそこそこ一致する出力をだすことができた。



これが dropout の効果であると考えて良いのだろう。過学習を回避した結果、汎用的にもっともらしい出力を出せるようになったと解釈した。



やじるし Chainer 関連メモの目次