マイノート

いろいろ勉強したことをまとめていきます

MENU

【keras】kerasでmnistデータの数字分類

今更ながら、単純なmnistの数値分類問題をkerasでやってみようと思います

前提

keras

keras はニューラルネットを非常に簡単に構築可能なライブラリです。

install方法

シンプルに以下のコマンドでインストールできる

pip install keras

mnistデータ・セット

手書き文字の認識用データ・セットです。 

0〜9までの手書きの数字の画像が、学習用、テスト用でそれぞれ60000枚、10000枚用意されています。

特別ダウンロードする必要はありません。

下のサンプルコードを実行すれば、自動的にダウンロードされます。

実験

mnistの手書きの文字をうまく分類できるように、 ニューラルネットに学習させたいと思います。

kerasのexampleに格納されているサンプルコードを用いて、 学習と評価を行ってみます。

ソースコード

kerasのexampleのソースコードに少し変更を加えたコード。

基本的には、参考文献のページを参照してもらえば、以下のコードは理解できると思います。

import numpy as np
import json
np.random.seed(1337)  # for reproducibility

from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import SGD, Adam, RMSprop
from keras.utils import np_utils


batch_size = 128
nb_classes = 10 # クラス数。今回は0〜9の10クラスなので、10
nb_epoch = 20

# mnistデータ・セットの取得
(X_train, y_train), (X_test, y_test) = mnist.load_data()

X_train = X_train.reshape(60000, 784)
X_test = X_test.reshape(10000, 784)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')

# 数値をone-hotの形に変更 例) 5 => array([ 0.,  0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  0.])
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)

model = Sequential()
model.add(Dense(512, input_shape=(784,)))
model.add(Activation('relu'))
model.add(Dropout(0.2))

model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.2))

model.add(Dense(10))
model.add(Activation('softmax'))

model.summary()

model.compile(loss='categorical_crossentropy',
              optimizer=RMSprop(),
              metrics=['accuracy'])

history = model.fit(X_train, Y_train,
                    batch_size=batch_size, nb_epoch=nb_epoch,
                    verbose=1, validation_data=(X_test, Y_test))
score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])

# 学習historyを保存
with open("history.json", "w") as f:↲
    json.dump(history.history, f)↲

結果

epochが進む毎にloss(誤差)が減少し、acc(正解率)が上昇していることがわかります。 学習できているようです。

f:id:ttt242242:20170827142440p:plain

f:id:ttt242242:20170827142815p:plain

おまけ実験

隠れ層を増やしてやってみました。

f:id:ttt242242:20170827142825p:plainf:id:ttt242242:20170827143051p:plain

隠れ層が増加すればするほど、精度が低下するという結果に。

層が増えれば増えるほど、勾配が適切に入力層に近い層まで、逆伝搬されないのが、問題なのかと思います。 まぁ先人達が層を増やす時にぶつかった基本的な問題だと思います。

なので、問題が比較的簡単な今回の問題のような場合などでは、

むやみに層や各層のノード数を増やすと逆に精度が落ちるので注意しましょう。

最後に

kerasはわかりやすく良い

参考文献

以下の参考サイトはとてもわかりやすかったです。ありがとうございました。

aidiary.hatenablog.com

PythonでMNISTを利用する方法まとめ - Qiita

Sequentialモデルのガイド - Keras Documentation