(python)深層学習ライブラリChainer基礎の基礎

こんにちは！かっきーです！！

ディープラーニング入門者向けの記事です。

今回はpython用の深層学習ライブラリChainerの基礎的な部分について解説します。
全結合ニューラルネットの組み方や活性化関数、最適化関数等について書きます。

python環境はpython3.6.7-64bitを用いています。また、ライブラリはchainerのみを使用します。

また、この記事で示すコードは、あくまでこんな風にディープラーニングのコードを組みますよという感じなので、参考にしながら自分で最初から組んでみることをオススメします。

##ニューラルネット(NN)のモデルを作る
以下がchainerを用いてNNを構築するコードです。

```python
import chainer
import chainer.functions as F
import chainer.links as L
from chainer import training

class MyChain(chainer.Chain):
    def __init__(self, n_input, n_node, n_output):
        #重みをガウス分布で初期化、scaleで標準偏差のスケールを決定する
        w = chainer.initializers.HeNormal(scale=1.0)
        super(MyChain, self).__init__()
        #4層NNを構築
        with self.init_scope():
            self.l1 = L.Linear(n_input, n_node, initialW=w)
            self.l2 = L.Linear(n_node, n_node, initialW=w)
            self.l3 = L.Linear(n_node, n_node, initialW=w)
            self.l4 = L.Linear(n_node, n_output, initialW=w)
            
    def __call__(self, x):
        #活性化関数にrelu関数を使用
        h = F.relu(self.l1(x))
        h = F.relu(self.l2(h))
        h = F.relu(self.l3(h))
        return self.l4(h)


def create_model():
    #入力10次元、ノード数200個、出力10次元のNNを構築
    model = L.Classifier(MyChain(10, 200, 10), lossfun=F.softmax_cross_entropy)

    #最適化関数としてAdamを使用、alpha(学習率)を0.025、εを1e-3に設定。
    optimizer = chainer.optimizers.Adam(alpha=0.025, eps=1e-3)
    optimizer.setup(model)

    return model, optimizer

```

以上はNNのモデルを作成するまでのコードです。

##活性化関数
活性化関数とは、NNモデルの表現力を上げるためにあります。つまり、より複雑な認識問題にも対応できるようになります。

活性化関数はreluの他にtanh、sigmoid、swish等があります。
以下のchainer公式リファレンスのリンクより他の活性化関数も見ることができます（Activation functionsという欄を見てください）。
https://docs.chainer.org/en/stable/reference/functions.html

##損失関数
損失関数は誤差を計算するためにあります。通常、損失が減る方向にNNを最適化します。損失関数は目的関数とも呼ばれます。

損失関数(loss_fun)はsoftmax_cross_entropyを用いましたが、上記のリンクのLoss functionsという欄に他の損失関数も書いてあります。

##最適化関数
最適化関数はNNをどのように更新していくかを決定する関数です。

最適化関数(optimizer)はAdamの他にSGD、RMSprop、AdaGrad等があります。
以下のchainer公式リファレンスのリンクより他の活性化関数も見れます。
https://docs.chainer.org/en/stable/reference/optimizers.html
（最適化関数のパラメータは学習の精度に大きく関係するので、色々な組み合わせを試して最適な値を見つけと良いです）


##NNに学習させる

以下は学習を始めるためのコード(の雛形)です。先程のNNモデル構築コードと同じ.pyファイルにコピペしてください。

```python
# trainデータ、testデータを引数に取る
def learn(train, test):
    # プロパティ
    epoch = 8
    batchsize = 256
    
    # NNモデル作成
    model, optimizer = create_model()

    # イテレータの定義
    train_iter = chainer.iterators.SerialIterator(train, batchsize) # 学習用
    test_iter = chainer.iterators.SerialIterator(test, batchsize, repeat=False) # 評価用

    # アップデータの登録
    updater = training.StandardUpdater(train_iter, optimizer)

    # トレーナーの登録
    trainer = training.Trainer(updater, (epoch, 'epoch'))
            
    # 学習状況の表示や保存
    trainer.extend(extensions.LogReport()) # ログ
    trainer.extend(extensions.Evaluator(test_iter, model)) # エポック数の表示
    trainer.extend(extensions.PrintReport(['epoch', 'main/loss', 'validation/main/loss',
                                            'main/accuracy', 'validation/main/accuracy', 'elapsed_time'] )) # 計算状態の表示
            
    # 学習開始
    trainer.run()

    # 保存
    #chainer.serializers.save_npz("result/Agent" + str(episode) + ".model", model)
```


ここで定義したlearn関数は教師データ、テストデータを引数に受け取ります。（教師データ及びテストデータは学習させたいものに合わせて作成してください）また、エピソード数に合わせてこの関数をループさせてください。

最後にエポック数とバッチサイズについて解説します。

##エポック数
エポック数(epoch)とは、同じ教師データを何回学習させるかを決める値です。通常、1回で学習できることは少ないので何回か学習させます。ただ、あまり大きな値にすると過学習を起こしてしまうので、そこは色々な値を試しながら調整しましょう。


##バッチサイズ
バッチサイズ(batchsize)とは、教師データから何個ずつ取り出して学習させるかを決定する値です。通常、データ数が多い程、大きな値を設定します。また、イテレーション数という値がありますが、バッチサイズとイテレーション数の片方の値が決まれば、もう片方の値も自動的に決まります。


##まとめ
以上が今回の内容となります。全体的にサラっと説明しただけなので、もっと詳しく知りたい方は他のサイトや論文を参考にして頂ければと思います。

この記事が、これからchainerを使ってディープラーニングの勉強をしようとしている人のちょうどいい入口になれれば良いなと思っています。