【Python/Keras】手書き文字認識(mnist)のサンプルを動かす

Pythonの機械学習モジュール「Keras」のmnistの手書き文字認識のサンプルを動かす方法をソースコード付きで解説します。

mnistの手書き文字認識

mnistのデータセットは、「6万枚の手書き数字の学習用画像」と「1万枚のテスト画像」が格納されています。
これらの画像は全て28×28[px]のグレースケール画像となっています。
mnistのデータセットは、機械学習の性能評価によく用いられます。
詳細→https://keras.io/ja/datasets/#mnist

Kerasでは、mnistのデータセットを使って簡単に動作テストができます。

サンプルコード

サンプルプログラムのソースコードです。

# -*- coding: utf-8 -*
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop

def main():
    batch_size = 128 # バッチサイズ(データサイズ)
    num_classes = 10 # 分類クラス数(今回は0~9の手書き文字なので10)
    epochs = 20 # エポック数(学習の繰り返し回数)

    # mnistデータセット(訓練用データと検証用データ)をネットから取得
    (x_train, y_train), (x_test, y_test) = mnist.load_data()

    # 2次元配列から1次元配列へ変換(784次元のベクトル)
    x_train = x_train.reshape(60000, 784)
    x_test = x_test.reshape(10000, 784)

    # データ型をfloat32に変換
    x_train = x_train.astype('float32')
    x_test = x_test.astype('float32')

    # 値の正規化(0-255から0.0-1.0に変換)
    x_train /= 255
    x_test /= 255

    # データセットの個数を表示
    print(x_train.shape[0], 'train samples')
    print(x_test.shape[0], 'test samples')

    # 階調データ(0~255)を2値化(0, 1)
    y_train = keras.utils.to_categorical(y_train, num_classes)
    y_test = keras.utils.to_categorical(y_test, num_classes)

    # モデルの構築
    model = Sequential()

    # Dense:全結合のニューラルネットワークレイヤー
    # 入力層784次元(=28x28)、出力層512次元
    model.add(Dense(512, activation='relu', input_shape=(784,)))
    model.add(Dropout(0.2)) # 過学習防止用:入力の20%を0にする(破棄)
    model.add(Dense(512, activation='relu')) # 活性化関数:relu
    model.add(Dropout(0.2)) # 過学習防止用:入力の20%を0にする(破棄)
    model.add(Dense(num_classes, activation='softmax')) # 活性化関数:softmax
    model.summary()

    # コンパイル(多クラス分類問題)
    model.compile(loss='categorical_crossentropy', optimizer=RMSprop(), metrics=['accuracy'])

    # 構築したモデルで学習
    history = model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_test, y_test))

    # モデルの検証・性能評価
    score = model.evaluate(x_test, y_test, verbose=0)
    print('Test loss:', score[0])
    print('Test accuracy:', score[1])


if __name__ == '__main__':
    main()

実行結果

サンプルプログラムの実行結果です。

Using TensorFlow backend.
Downloading data from https://s3.amazonaws.com/img-datasets/mnist.npz
11493376/11490434 [==============================] - 18s 2us/step
60000 train samples
10000 test samples
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
dense_1 (Dense)              (None, 512)               401920
_________________________________________________________________
dropout_1 (Dropout)          (None, 512)               0
_________________________________________________________________
dense_2 (Dense)              (None, 512)               262656
_________________________________________________________________
dropout_2 (Dropout)          (None, 512)               0
_________________________________________________________________
dense_3 (Dense)              (None, 10)                5130
=================================================================
Total params: 669,706
Trainable params: 669,706
Non-trainable params: 0
_________________________________________________________________
Train on 60000 samples, validate on 10000 samples
Epoch 1/20
2018-04-23 20:14:51.119606: I C:\tf_jenkins\workspace\rel-win\M\windows\PY\36\tensorflow\core\platform\cpu_feature_guard.cc:137] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX AVX2
60000/60000 [==============================] - 16s 273us/step - loss: 0.2437 - acc: 0.9241 - val_loss: 0.1192 - val_acc: 0.9631
Epoch 2/20
60000/60000 [==============================] - 18s 300us/step - loss: 0.1029 - acc: 0.9687 - val_loss: 0.0905 - val_acc: 0.9712
Epoch 3/20
60000/60000 [==============================] - 17s 279us/step - loss: 0.0756 - acc: 0.9773 - val_loss: 0.0804 - val_acc: 0.9760
Epoch 4/20
60000/60000 [==============================] - 18s 300us/step - loss: 0.0608 - acc: 0.9822 - val_loss: 0.0726 - val_acc: 0.9808
Epoch 5/20
60000/60000 [==============================] - 18s 308us/step - loss: 0.0495 - acc: 0.9855 - val_loss: 0.0751 - val_acc: 0.9791
Epoch 6/20
60000/60000 [==============================] - 18s 308us/step - loss: 0.0447 - acc: 0.9867 - val_loss: 0.0723 - val_acc: 0.9808
Epoch 7/20
60000/60000 [==============================] - 18s 305us/step - loss: 0.0386 - acc: 0.9887 - val_loss: 0.0866 - val_acc: 0.9792
Epoch 8/20
60000/60000 [==============================] - 18s 306us/step - loss: 0.0342 - acc: 0.9895 - val_loss: 0.0969 - val_acc: 0.9768
Epoch 9/20
60000/60000 [==============================] - 18s 299us/step - loss: 0.0301 - acc: 0.9910 - val_loss: 0.0846 - val_acc: 0.9814
Epoch 10/20
60000/60000 [==============================] - 18s 304us/step - loss: 0.0306 - acc: 0.9918 - val_loss: 0.0891 - val_acc: 0.9824
Epoch 11/20
60000/60000 [==============================] - 18s 297us/step - loss: 0.0270 - acc: 0.9923 - val_loss: 0.0901 - val_acc: 0.9841
Epoch 12/20
60000/60000 [==============================] - 18s 303us/step - loss: 0.0247 - acc: 0.9929 - val_loss: 0.0997 - val_acc: 0.9813
Epoch 13/20
60000/60000 [==============================] - 19s 311us/step - loss: 0.0248 - acc: 0.9935 - val_loss: 0.0980 - val_acc: 0.9820
Epoch 14/20
60000/60000 [==============================] - 18s 301us/step - loss: 0.0246 - acc: 0.9932 - val_loss: 0.0977 - val_acc: 0.9819
Epoch 15/20
60000/60000 [==============================] - 17s 285us/step - loss: 0.0214 - acc: 0.9940 - val_loss: 0.1000 - val_acc: 0.9822
Epoch 16/20
60000/60000 [==============================] - 18s 299us/step - loss: 0.0231 - acc: 0.9938 - val_loss: 0.1159 - val_acc: 0.9807
Epoch 17/20
60000/60000 [==============================] - 18s 301us/step - loss: 0.0209 - acc: 0.9945 - val_loss: 0.1062 - val_acc: 0.9844
Epoch 18/20
60000/60000 [==============================] - 18s 304us/step - loss: 0.0216 - acc: 0.9948 - val_loss: 0.1099 - val_acc: 0.9830
Epoch 19/20
60000/60000 [==============================] - 18s 307us/step - loss: 0.0191 - acc: 0.9950 - val_loss: 0.1214 - val_acc: 0.9815
Epoch 20/20
60000/60000 [==============================] - 18s 301us/step - loss: 0.0187 - acc: 0.9948 - val_loss: 0.1091 - val_acc: 0.9839
Test loss: 0.109066825757
Test accuracy: 0.9839

エポック数(繰り返し回数)が増加すると、スコア(精度)も上がっています。

関連記事
1 Python入門 基本文法
2 【Python/Keras】機械学習入門・使い方
関連記事