Keras で MNIST を分類
「Keras で iris を分類」 に続き、今回は Keras で畳み込みニューラルネットを使った MNIST の分類を試してみました。
- Keras 1.0.8
- Python 3.5.2
ソースは http://github.com/fits/try_samples/tree/master/blog/20160920/
準備
Docker で実行するための Docker イメージを作成します。
Docker イメージ作成
/vagrant/work/keras/Dockerfile
FROM python RUN apt-get update && apt-get upgrade -y RUN pip install --upgrade pip RUN pip install keras RUN pip install h5py RUN apt-get clean
h5py
は Keras の save_model
関数を使うために必要でした。
今回のバージョンでは keras をインストールしても h5py は自動的にインストールされなかったので、別途インストールするようにしています。
上記を docker build して Docker イメージを作成しておきます。
Docker ビルド
$ cd /vagrant/work/keras $ docker build --no-cache -t sample/py-keras:0.2 .
(1) MNIST データセットの取得
keras.datasets の mnist を使うと MNIST データセットを取得できます。(S3 からダウンロードするようになっている)
load_data
関数で取得したデータセットは [[<学習用画像データ>, <学習用ラベルデータ>], [<評価用画像データ>, <評価用ラベルデータ>]]
のような内容となっていましたが(画素の値は 0 ~ 255)、そのままでは今回の用途に使えなかったので numpy
を使って変換しています。
/vagrant/work/mnist_helper.py
import numpy as np from keras.datasets import mnist from keras.utils import np_utils # 学習用のデータセット取得 def train_mnist(): return convert_mnist(mnist.load_data()[0]) # 評価用のデータセット取得 def test_mnist(): return convert_mnist(mnist.load_data()[1]) def convert_mnist(tpl): # 画像データの加工 features = tpl[0].reshape(tpl[0].shape[0], 1, 28, 28).astype(np.float32) features /= 255 # ラベルデータの加工 (10種類の分類) labels = np_utils.to_categorical(tpl[1], 10) return (features, labels)
(2) 畳み込みニューラルネットモデル
畳み込みニューラルネットのモデルを作成してバイナリファイルとして保存する処理です。
畳み込みのレイヤー構成は 「ConvNetJS で MNIST を分類2」 と同じ様にしてみました。 (活性化関数は relu
を使用)
/vagrant/work/create_layer_conv.py
import sys from keras.models import Sequential, save_model from keras.layers.core import Dense, Activation, Flatten from keras.layers import Convolution2D, MaxPooling2D model_dest_file = sys.argv[1] model = Sequential() # 1つ目の畳み込み層(5x5 で 8個出力) model.add(Convolution2D(8, 5, 5, input_shape = (1, 28, 28))) model.add(Activation('relu')) # 1つ目のプーリング層 (最大プーリング) model.add(MaxPooling2D(pool_size = (2, 2), strides = (2, 2))) # 2つ目の畳み込み層(5x5 で 16個出力) model.add(Convolution2D(16, 5, 5)) model.add(Activation('relu')) # 2つ目のプーリング層 (最大プーリング) model.add(MaxPooling2D(pool_size = (3, 3), strides = (3, 3))) model.add(Flatten()) model.add(Dense(10)) model.add(Activation('softmax')) model.compile(loss = 'categorical_crossentropy', optimizer = 'adam', metrics = ['accuracy']) # モデルの保存 save_model(model, model_dest_file)
(3) 学習処理
学習処理は以下の通りです。
学習用の MNIST データセットを使って fit
を実行します。
/vagrant/work/learn_mnist.py
import sys from keras.models import save_model, load_model from mnist_helper import train_mnist epoch = int(sys.argv[1]) mini_batch = int(sys.argv[2]) model_file = sys.argv[3] model_dest_file = sys.argv[4] # モデルの読み込み model = load_model(model_file) # 学習用 MNIST データセット取得 (x_train, y_train) = train_mnist() # 学習 model.fit(x_train, y_train, nb_epoch = epoch, batch_size = mini_batch) # 学習後のモデルを保存 save_model(model, model_dest_file)
(4) 評価処理
評価処理は以下の通りです。
評価用の MNIST データセットを使って evaluate
を実行します。
verbose を 0 にすれば途中経過を出力しなくなるようです。
/vagrant/work/eval_mnist.py
import sys from keras.models import load_model from mnist_helper import test_mnist model_file = sys.argv[1] model = load_model(model_file) # 評価用 MNIST データセット取得 (x_test, y_test) = test_mnist() # 評価 (loss, acc) = model.evaluate(x_test, y_test, verbose = 0) print("loss = %f, accuracy = %f" % (loss, acc))
実行
まずは、作成した Docker イメージ(py-keras)を使って Docker コンテナを起動します。
Docker コンテナ起動
$ docker run --rm -it -v /vagrant/work:/work sample/py-keras:0.2 bash # cd /work
起動した Docker コンテナで、畳み込みニューラルネットのモデルを作成してファイルへ保存します。
1. モデル作成
# python create_layer_conv.py 1.model Using Theano backend.
保存したファイルを使って学習を行います。 今回はミニバッチサイズ 200 で 3 回繰り返してみます。
初回実行時は MNIST データセットのダウンロードが行われます。
2. 学習
# python learn_mnist.py 3 200 1.model 1a.model Using Theano backend. Downloading data from https://s3.amazonaws.com/img-datasets/mnist.pkl.gz ・・・ Epoch 1/3 60000/60000 [==============================] - 116s - loss: 0.7228 - acc: 0.7931 Epoch 2/3 60000/60000 [==============================] - 116s - loss: 0.1855 - acc: 0.9458 Epoch 3/3 60000/60000 [==============================] - 115s - loss: 0.1352 - acc: 0.9591
最後に、学習後のモデルを使って評価用のデータセットを評価します。
3. 評価
# python eval_mnist.py 1a.model Using Theano backend. loss = 0.102997, accuracy = 0.968600