【Chainer実践編5】Trainerってなに?超便利なChainer学習のデフォルトスタンダード!

【Chainer実践編5】Trainerってなに?超便利なChainer学習のデフォルトスタンダード!

新しいチャレンジを始めるには、古い習慣を捨てなければならないというのは本当でしたね。私も深層学習を勉強し始めたことで、ゲームやアニメを見る時間が極端に減ってしまいました。

睡眠時間は増えました。

アイーンです。

 

今日は、Chainer学習のデフォルトスタンダード、Trainer(トレーナー)について学習したいと思います。

実は、これまでこのブログで書いてきたChainer基礎編・実践編のコードには、問題点がありました。

まずはそこから解説してみましょう。

 

問題点とは?

問題点は以下の3つです。

1.これまでのコードでは、バッチ学習しか行えていない。

  (ミニバッチ学習、オンライン学習が実行できない)

2.学習の進行中は、どこまで進んだかが確認できない。

  (確認するためには、コードを追加して書かなければならない。)

3.学習させるループ部分はほぼ定型文なのに、毎回書かなければならない。

 

Trainerはこの問題を一気に解決してくれる、便利なあんちくしょうです。

 

Trainerの使い方

Trainerの記述するためには、他に覚えておくべきモジュールが3つあります。

Iterator(イテレータ)

Updater(アップデータ)

extensions(エクステンションズ)

です。

Iteratorは、Trainerで使用する”学習データ”を保持し、ミニバッチ処理やオンライン処理用に、データを分割して使用できる形に変更してくれるものです。

Updaterは、学習用ループの代わりです。IteratorとOptimizerを使ってコードを簡略化してくれています。

extensionsは、学習の途中経過を様々な形で表示してくれるものです。

これで、今後は学習中の待ち時間に「あれ?PC止まった?」とならずに済みます。

 

それでは、アヤメの品種分類のコードを書き換える形で、Trainerを導入してみましょう。

ここに、アヤメの品種分類の全コードを載せておきますので、Trainer導入前と導入後で比較してみてください。

 

導入前

import chainer
import chainer.links as L
import chainer.functions as F
from chainer import Variable,Chain,optimizers

#追加

import numpy as np
from sklearn import datasets

IrisData = datasets.load_iris()
x = IrisData.data.astype(np.float32)
t = IrisData.target
n = t.size

t_matrix = np.zeros(3 * n).reshape(n, 3).astype(np.float32)

for i in range(n):
    t_matrix[i, t[i]] = 1.0

index = np.arange(n)
index_train = index[index % 2 != 0]
index_test = index[index % 2 == 0]

x_train = x[index_train, : ] #入力データ(訓練用)
t_train = t_matrix[index_train, : ] #正解データ(訓練用)
x_test = x[index_test, : ] #入力データ(テスト用)
t_test = t[index_test] #正解データ(テスト用)

x_train_v = Variable(x_train)
t_train_v = Variable(t_train)
x_test_v = Variable(x_test)


class IrisLearn(Chain):
    def __init__(self):
        super(IrisLearn, self).__init__(
            l1=L.Linear(4, 6),
            l2=L.Linear(6, 6),
            l3=L.Linear(6, 3),
        )
    def predict(self, x):
        h1 = F.sigmoid(self.l1(x))
        h2 = F.sigmoid(self.l2(h1))
        h3 = self.l3(h2)
        return h3



model = IrisLearn()
opt = optimizers.Adam()
opt.setup(model)

for i in range(10000):
    model.cleargrads()
    y_train_v = model.predict(x_train_v)
    loss = F.mean_squared_error(y_train_v,t_train_v)
    loss.backward()
    opt.update()
    

model.cleargrads()
y_test_v = model.predict(x_test_v)
y_test = y_test_v.data

correct = 0
count = y_test.shape[0]

for i in range(count):
    maxIndex = np.argmax(y_test[i, :])
    print(y_test[i, :], maxIndex)
    if maxIndex == t_test[i]:
        correct += 1

print("正解数 ", correct, ",問題数 ",count , ", ", correct/ count * 100,"%")

 

 

導入後

import chainer
import chainer.links as L
import chainer.functions as F
from chainer import Variable,Chain,optimizers

from chainer.datasets import tuple_dataset
from chainer import training, iterators
from chainer.training import extensions

import numpy as np

from sklearn import datasets

IrisData = datasets.load_iris()
x = IrisData.data.astype(np.float32)
t = IrisData.target
n = t.size

t_matrix = np.zeros(3 * n).reshape(n, 3).astype(np.float32)

for i in range(n):
    t_matrix[i, t[i]] = 1.0

index = np.arange(n)
index_train = index[index % 2 != 0]
index_test = index[index % 2 == 0]

x_train = x[index_train, : ] #入力データ(訓練用)
t_train = t_matrix[index_train, : ] #正解データ(訓練用)
x_test = x[index_test, : ] #入力データ(テスト用)
t_test = t[index_test] #正解データ(テスト用)

train = tuple_dataset.TupleDataset(x_train, t_train)

x_test_v = Variable(x_test)


class IrisLearn(Chain):
    def __init__(self):
        super(IrisLearn, self).__init__(
            l1=L.Linear(4, 6),
            l2=L.Linear(6, 6),
            l3=L.Linear(6, 3),
        )

    def __call__(self, x, t):
        return F.mean_squared_error(self.predict(x), t)

    def predict(self, x):
        h1 = F.sigmoid(self.l1(x))
        h2 = F.sigmoid(self.l2(h1))
        h3 = self.l3(h2)
        return h3



model = IrisLearn()
opt = optimizers.Adam()
opt.setup(model)

train_iter = iterators.SerialIterator(train, 30)
updater = training.StandardUpdater(train_iter, opt)
trainer = training.Trainer(updater, (5000, 'epoch'))
trainer.extend(extensions.ProgressBar())
trainer.run()

model.cleargrads()
y_test_v = model.predict(x_test_v)
y_test = y_test_v.data

correct = 0
count = y_test.shape[0]

for i in range(count):
    maxIndex = np.argmax(y_test[i, :])
    print(y_test[i, :], maxIndex)
    if maxIndex == t_test[i]:
        correct += 1

print("正解数 ", correct, ",問題数 ",count , ", ", correct/ count * 100,"%")

 

これがTrainerで書き換えたコードです。変更箇所は赤く表示してます。

学習過程や使うデータなどは前回のコードと全く同じなのに、スッキリ書けているのがお分かりいただけますか。

次回は、コードを実際に実行し、各箇所がどのように動くか詳細を説明したいと思います。

それでは。