Tensorflow+KerasでCNNを使ってMNISTを動かしてみる

はじめに

前回のチュートリアルをCNN(畳み込みニューラルネットワーク)に書き直して動かしてみます。
KerasのGitHubに CNNのサンプルがありますので、これを参考します。
このサンプルはKeras単体の場合で、今回はTensorflowに組み込まれたKerasを使用しているため、若干修正が必要になります。

ソースコード

チュートリアルのソースをコピーして動かしてみました。

import tensorflow
from tensorflow import keras

batch_size = 128
num_classes = 10
epochs = 5

img_rows, img_cols = 28, 28

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()

# CNN用にデータの形状を変更
if keras.backend.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train, x_test = x_train / 255.0, x_test / 255.0

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

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

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))

model.evaluate(x_test, y_test)

処理の概要

Kerasのイメージデータの形式を取得し、それに合わせてデータの形状を変更しています。
1の部分が画像のチャネル数(1:白黒、3:RGB)となります。

if keras.backend.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
else:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

Conv2D:2次元の畳み込み
32,kernel_size=(3, 3):32の3×3の畳み込み
input_shape:入力データの形状です。MNISTの画像は28×28でチャネル数が1となります。

keras.layers.Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape),

2×2のMax Poolingをします。

keras.layers.MaxPooling2D(pool_size=(2, 2))

実行

テスト用データでどれくらいの精度で分類できるかを実行します。

model.evaluate(x_test, y_test)

テスト用データでどれくらいの精度で分類できるかを実行した結果は以下になりました。
前回とあまり変化はありませんでした。

[0.037433680679209644, 0.9874]