粗大メモ置き場

個人用,たまーに来訪者を意識する雑記メモ

Kerasを用いた手書き画像認識Ⅲ:畳み込みネットワークを用いたテストコード

前回までのあらすじ

最初はTensorflowを用いて隠れ層を導入したパーセプトロンにて学習を行いました。
ossyaritoori.hatenablog.com


次に,Kerasを導入して3層のニューラルネットワークで学習を行い,改善を得ました。
ossyaritoori.hatenablog.com

今回は畳み込みニューラルネットワークを試してみましょう。



畳み込みネットワーク(CNN)について

画像の認識などにおいて強力な性能を発揮する手法で、
画像の二次元畳み込み(2D Convolution)計算を層間の伝搬に用いる手法です。
以下のサイトが図が見やすくてわかりやすいでしょう。
postd.cc

最近聞いてきた公演によるとプーリング層や全結合層はなくて,GAP層を用いるのが標準になりつつあるそうですね。

環境の下準備

前回の記事でのKerasパッケージの導入のところをきちんとこなしておいてください。
Tensorflow,Kerasを用いた手書き画像認識:MNISTを使ったテストコード - 粗大メモ置き場

KerasにおけるCNNの実装手法

以下にKerasを用いた際のモデルの生成部を示します。
Denseの代わりにConv2Dという関数で畳み込みの層を決めており,
Kernelのサイズや数などを同時に決定しています。

これだけです。まじかよ超簡単じゃん。

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

流れは,

  • 32カーネル 畳み込み層(ReLu)
  • 64カーネル 畳み込み層(ReLu)
  • プーリング層
  • 128要素の全結合相?
  • 10クラスへの出力層

と言ったところでしょう。


例のごとく他所様からコードをお借りしていますが疑問として,
どうして最初の層が32個のカーネルなのに次の層が64個なんでしょう?
(勉強不足が露呈している)

なんとなく逆の方が良さそうなもんですが何か意味があるんでしょうか。

Kerasを用いたコード

ライブラリとしてKerasをダウンロードしたPC上で動作を確認しています。
実行環境はSpyder3上のIPythonコンソール上で行っています。

詳しい環境については過去記事を漁ってください。


結果:元のコード

数回のEpochを繰り返して精度をブラッシュアップしますが今回は12回目で99%を達成しました。これだけでも十分すごいですが実用上では99.999%より上の性能が求められるようでなんというか大変だなぁ…

Epoch 12/12
60000/60000 [==============================] - 82s - loss: 0.0365 - acc: 0.9887 - val_loss: 0.0289 - val_acc: 0.9901
Test loss: 0.0288566211587
Test accuracy: 0.9901

結果:ちょっと弄ったコード

さっきの畳み込み層の順番を32→64から64→32へと変更してみました。
ほとんど差がありませんね。ただ,かかった時間はこちらのほうが長かったように思います。
確かより「深い層」の方が計算が面倒になるのでそういった事情を考慮して32→64という構造なのかもしれません。

Epoch 12/12
60000/60000 [==============================] - 102s - loss: 0.0450 - acc: 0.9869 - val_loss: 0.0287 - val_acc: 0.9904
Test loss: 0.0286987099324
Test accuracy: 0.9904

後処理

モデルの保存

せっかく作ったモデルですのでもったいないしきちんと保存しましょう。
[TF]KerasでModelとParameterをLoad/Saveする方法 - Qiita

jsonという形式を通してファイルで保存したいとすると,以下のような流れになります。
詳細は今度記事に書きます。pickleというクラスを使います。

import pickle
json_string = model.to_json()
with open('mnistmodel.pickle', 'wb') as f:
    pickle.dump(json_string,f)

学習したパラメータの保存

学習したパラメータは.hdf5という形式で保存されます。

model.save_weights('mnistparam.hdf5')

読み出し方は上のURLを参照してください。個別に記事を書くかもしれません。

可視化

可視化についてはgraphvizやらpydot_ngやらをインストールする必要があるのでまた今度書きます。
以下のサイトが役に立つことでしょう。
www.mathgram.xyz

感想

とりあえず一連の記事をもってMNISTのテストはここらへんで終了ということにしようと思います。感想として複雑な学習をするにはGPUが必須という所感を受けました。

今回のMNISTの学習では大体18分くらいかかっていましたが,コードを書いた人によるとGPUを積んだPCだと大体その1/5弱の3~4分で終えることができるそうです。

これから機械学習を始める人は是非GPUをきちんと積んだPCを使うのが良いでしょう。