こんにちは。ぶたキムチです。
前回はkerasでMNISTに挑戦しましたが、
今回はChainerを使ってMNISTに挑戦したいと思います。
Chainerは、国内の企業が開発したpythonの深層学習ライブラリです。
Chainer は、ニューラルネットワークの計算および学習を行うためのオープンソースソフトウェアライブラリである。バックプロパゲーションに必要なデータ構造をプログラムの実行時に動的に生成する特徴があり、複雑なニューラルネットワークの構築を必要とする深層学習で主に用いられる。
(ウィキペディアより)
MNIST・Chainerについては、くわしい解説は前回の記事で説明しているのこちらもあわせてご覧ください。
1.処理の流れ
・ライブラリのインポート
・MNISTデータセットのロード
・学習のモデルの作成
・optimizerの設定
・SerialIteratorの設定
・Updaterの設定
・trainerの設定
・Extentionの設定
・学習の実行
・評価
2.ソースコード
#ライブラリをインポートする import numpy as np import matplotlib.pyplot as plt import chainer #Load the MNIST datasets train, test = chainer.datasets.get_mnist() #モデルの作成 import chainer.links as L import chainer.functions as F class Model(chainer.Chain): def __init__(self, n_in, n_hidden, n_out): super(Model, self).__init__() with self.init_scope(): self.l1 = L.Linear(n_in, n_hidden) self.l2 = L.Linear(n_hidden, n_hidden) self.l3 = L.Linear(n_hidden, n_out) def __call__(self, x): h = F.relu(self.l1(x)) h = F.relu(self.l2(h)) h = self.l3(h) return h model = L.Classifier(Model(784, 100, 10)) #optimizerのセット optimizer = chainer.optimizers.Adam() optimizer.setup(model) #SerialIteratorのセット from chainer.iterators import SerialIterator train_iter = SerialIterator(train, batch_size=4) test_iter = SerialIterator(test, batch_size=4,repeat=False, shuffle=False) #Updaterの設定 updater = chainer.training.StandardUpdater(train_iter, optimizer, device=-1) #trainerの設定 epoch = 10 trainer = chainer.training.Trainer(updater, (epoch, "epoch"), out="result/mnist") #Extentionの設定 from chainer.training import extensions trainer.extend(extensions.Evaluator(test_iter, model, device=-1)) trainer.extend(extensions.LogReport()) trainer.extend(extensions.ProgressBar()) trainer.extend(extensions.PrintReport(['epoch', 'main/loss', 'validation/main/loss', 'main/accuracy', 'validation/main/accuracy'])) trainer.extend(extensions.dump_graph('main/loss', out_name="model.dot")) trainer.extend(extensions.PlotReport(['main/loss', 'validation/main/loss'], x_key='epoch', file_name='loss.png')) trainer.extend(extensions.PlotReport(['main/accuracy', 'validation/main/accuracy'], x_key='epoch', file_name='accuracy.png')) #学習の実行 trainer.run() #評価 idx = np.random.choice(len(test), 100) for i in idx: x = test[i][0]#入力画像データ predicts = np.argmax(model.predictor(x=x.reshape(1,len(x))).data) y = test[i][1]#labeldata if y != predicts: plt.imshow(x.reshape(28,28),cmap='gray') #file名 filename = "label" + str(y) + "_predict" + str(predicts) + ".png" plt.savefig(filename)
3.ソースコード詳細
それではソースコードの詳細を見ていきましょう。
3.1ライブラリのインポート
#ライブラリをインポートする import numpy as np import matplotlib.pyplot as plt import chainer
まず必要なライブラリのインポートをしましょう。
import文の使い方
・import モジュール名
・from モジュール名 import クラス名/関数名など
・import モジュール名 as 別名
3.2MNISTのデータセットのロード
#Load the MNIST datasets train, test = chainer.datasets.get_mnist()
MNISTのデータセットは、Chainerで用意されている関数を使用します。
chainer.datasets.get_mnist()関数の使い方
train, test = chainer.datasets.get_mnist(withlabel, ndim, scale, dtype, label_dtype, rgb_format)
・引数
withlabel:Trueならラベル付きのデータ / Falseならラベルなしのデータ
ndim:画像の形状の指定。ndim==1:(784,) / ndim==2 : (28,28) / ndim==3 : (1,28,28)
scale : pixelのスケール
dtypr:画像配列のデータ型
label_dtype:ラベルのデータ型
rgb_format : bool型でRGBにフォーマと変換するかどうか
・戻り値
train : 訓練データ(TupleDataset)
test : 評価データ(TupleDataset)
データの中身はこんな感じ
print(train[0]) (array([0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , ・・・(省略)・・・ 0. , 0.53333336, 0.9921569 , 0.9921569 , 0.9921569 , 0.8313726 , 0.5294118 , 0.5176471 , 0.0627451 , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], dtype=float32), 5)
3.3 学習モデルの作成
次に学習モデルである分類モデルを作成していきます。
import chainer.links as L import chainer.functions as F class Model(chainer.Chain): def __init__(self, n_in, n_hidden, n_out): super(Model, self).__init__() with self.init_scope(): self.l1 = L.Linear(n_in, n_hidden) self.l2 = L.Linear(n_hidden, n_hidden) self.l3 = L.Linear(n_hidden, n_out) def __call__(self, x): h = F.relu(self.l1(x)) h = F.relu(self.l2(h)) h = self.l3(h) return h model = L.Classifier(Model(784, 100, 10))
今回作成するモデルは、入力層・中間層・出力層の3層のニューラルモデルを作成していきます。
順番に解説していきます。
chainer.functionsとchainer.linksについてchainer.functions:シグモイド関数やReLU関数といった関数を実装することができます
chainer.links:入力層・中間層・出力層・全結合層などの実装に使われる
学習モデルModelに使用されている引数について説明します。
学習モデルModelについて
Model:レイヤー構成を定義するクラス
chainer.Chain:パラメータを持つ層をまとめるためのクラス
__init__:モデルを構成するレイヤーをて定義するメソッド。インスタンス。
__call__:クラスのインスタンスを関数として呼び出すメソッド。
L.linear:全結合層を実現するクラス
F.relu:活性化関数としてrelu関数を実装
n_in:入力層,n_hidden:隠れ層,n_out:出力層
(n_in)×(n_hidden)の大きさの行列を指定してパラメータ保持
model : Classifierインスタンスの定義をし、modelにデータ渡すことで順伝播が開始する
モデルの概要図は以下のような感じです。
3.4 optimizerの設定
#optimizerのセット optimizer = chainer.optimizers.Adam() optimizer.setup(model)
次にoptimizerの設定をしましょう。
今回使用する最適化関数は、Adamを使用します。
optimizerは、逆伝播させ重みのパラメータを更新し最適化する部分になります。
最適化関数を設定することで予測した値と実際の値の誤差を計算することができます。
採用した最適化関数はAdamを使用します。
Adamについて
2015年に提唱された手法で、ニューラルネットワークの学習において、よく使用される最適化手法の一つです。
複雑な手法であり、MomentumとAdaGradが融合したような手法になります。
効率的にパラメータ空間を探索できることが期待されており、ハイパラメータの「バイアス補正」が行われていることもAdamの特徴です。
3.5 SerialIteratorの設定
#SerialIteratorのセット from chainer.iterators import SerialIterator train_iter = SerialIterator(train, batch_size=4) test_iter = SerialIterator(test, batch_size=4,repeat=False, shuffle=False)
次に、Iteratorの設定をしていきます。
IteratorはChainerno便利機能で、訓練データや検証データを毎エポックおで順序をシャッフルしてくれる関数です。
Chainerではネットーワークの訓練データの順番をシャッフルすることでデータセットへの操作を抽象化してくれます。
SerialIteratorの使い方
iter = chainer.iterators.SerialIterator(data, batch_size, repeat=True, shuffle=True)
data : 訓練データ(もしくは検証データ)
batch_size : バッチサイズ
repeat : 1epochを繰り返すかどうかをTrue/Falseのbool型で決定
shuffle:Trueの場合はランダムでデータを返す。Falseの場合はデータセットと同じ順序で返す。
3.6 Updaterの設定
#Updaterの設定 updater = chainer.training.StandardUpdater(train_iter, optimizer, device=-1)
Upadaterはoptimizerを更新する関数になります。
Upadaterの使い方
updater = chainer.training.StandardUpdater(train_iter, optimizer, device=-1)
train_iter : Iteratorでシャッフルされた訓練データ
optimizer : データに適用する最適化手法
device=-1 : 実装時GPU(=0)かCPU(=-1)どちらかを指定
3.7 Trainerの設定
#trainerの設定 epoch = 10 trainer = chainer.training.Trainer(updater, (epoch, "epoch"), out="result/mnist")
エポックは学習時間を短くしようと思ったので、適当にエポックを10にしました。
Trainerの使い方
trainer = chainer.training.Trainer(updater, (epoch, “epoch”), out=”result/mnist”)
updater : trainerを使う場合はupdaterを渡す必要があるためupdaterを指定
(epoch, “epoch”): エポック数
out : ログを出力し保存する先のディレクトリ作成または指定
3.8 Extensionsの設定
#Extentionの設定 from chainer.training import extensions #テストデータを使ってモデル評価を行う機能 trainer.extend(extensions.Evaluator(test_iter, model, device=-1)) #ログの保存 trainer.extend(extensions.LogReport()) #学習の進捗の表示 trainer.extend(extensions.ProgressBar()) trainer.extend(extensions.PrintReport(['epoch', 'main/loss', 'validation/main/loss', 'main/accuracy', 'validation/main/accuracy'])) #dotグラフの作成と表示保存 trainer.extend(extensions.dump_graph('main/loss', out_name="model.dot")) #正答率をグラフを作成と保存 trainer.extend(extensions.PlotReport(['main/loss', 'validation/main/loss'], x_key='epoch', file_name='loss.png')) trainer.extend(extensions.PlotReport(['main/accuracy', 'validation/main/accuracy'], x_key='epoch', file_name='accuracy.png'))
ExtensionはTrainerに様々な機能を追加するためのものです。
主な追加できる機能は以下のようなものが挙げられます。
・モデルの保存
・評価
・学習中のプログラスバーの表示やログの保存
・学習の記録
・学習グラフの作成と保存
3.9 学習の実行
#学習の実行 trainer.run()
trainer.run()の使い方
trainer.run()
Chainerでの学習の実行は設定したtrainerに.run()関数を加えるだけです。
実行している段階はこんな感じspyderのコンソールに出ます。
Extensionで設定したaccuracyとlossのグラフになります。
3.10 評価
#評価 idx = np.random.choice(len(test), 100) for i in idx: x = test[i][0]#入力画像データ predicts = np.argmax(model.predictor(x=x.reshape(1,len(x))).data) y = test[i][1]#labeldata if y != predicts: plt.imshow(x.reshape(28,28),cmap='gray') #file名 filename = "label" + str(y) + "_predict" + str(predicts) + ".png" plt.savefig(filename)
評価はランダムに何枚か抜き出して、正解ラベルと評価した結果が一致しなかったものだけ抜き出してみましょう。
正解ラベルと一致しなかった結果はこんな感じです。
中には結果のように正解ラベルと一致していないものあります。
今回はエポック数は10とかなり少ないエポックで学習したのもあって、いい学習モデル、評価も何とも言えないです。
まとめ
今回は初心者向けにChainerの練習としてMNISTに挑戦した結果をまとめました。
前回の記事ではkerasでMNISTに挑戦し、今回のChainerでMNISTに挑戦した結果と比較すると
kerasは圧倒的にコード数が少なく実装できたのが特徴で簡単にディープラーニングを実装できました。
Chainerはディープラーニングぞ実装する過程を逐一コード化していくため、kerasよりコードは多いですが、Chainerの方が直感的に深層学習を実装できる感じでした。
ただ、最適化関数などやはり初心者には難しい部分がかなり多いです。
そちらは参考書をベースに学習することをおすすめします。
・ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装
・深層学習
コメント