2017年6月3日土曜日

Jupiter Notebook + Keras(Tensor Flow)でチュートリアルをしてみる3 MINIST

Kerasチュートリアル第3弾。

機械学習のモデルを評価する時によく使われる、MINIST(手書き文字の認識をする)問題のコードを追っていく。
解説している記事をみながら、コードを追ってみる。

使う画像のサイズは28 x 28ピクセル。
60000イメージはモデル構築のために、10000イメージはテストのために使う。

いいモデルはエラー率1%以下になるらしい。

では実際にコードを見ていく。

実際の文字イメージ画像群(データセット)をダウンロードする必要があるが、Kerasでは便利なスクリプトが用意されているらしい。(~/.keras/datasets/mnist.pkl.gz にダウンロードされる)

以下はダウンロードしてプロットするスクリプト。

# Plot ad hoc mnist instances
from keras.datasets import mnist
import matplotlib.pyplot as plt
# load (downloaded if needed) the MNIST dataset
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# plot 4 images as gray scale
plt.subplot(221)
plt.imshow(X_train[0], cmap=plt.get_cmap('gray'))
plt.subplot(222)
plt.imshow(X_train[1], cmap=plt.get_cmap('gray'))
plt.subplot(223)
plt.imshow(X_train[2], cmap=plt.get_cmap('gray'))
plt.subplot(224)
plt.imshow(X_train[3], cmap=plt.get_cmap('gray'))
# show the plot
plt.show()


ふむ、Jupiter Notebook上でも綺麗に表示された。

ではデータはダウンロードされたので、今回使うライブラリたちを読み込む。
Dropoutというのは、過学習を避けるためにランダムに伝播をさせずに、ネットワークをFatにさせないテクニックらしい。
詳しい論文

keras.unilsはその名の通り、kerasの便利クラス。モデルのシリアライズしたりするメソッドがある。https://keras.io/utils/


import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.utils import np_utils



前回と同じように、再現性を持たせるためにseedをセット。

# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)



でMINISTのデータを読み込む

# load data
(X_train, y_train), (X_test, y_test) = mnist.load_data()


読み込んだトレーニングセットは3次元の配列(白黒の場合)だが、モデルに食わせるためには、Vector(1次元の配列)にする必要があるらしい。28 x 28の画像だから784要素の配列する。

# flatten 28*28 images to a 784 vector for each image
# print(type(X_train))
num_pixels = X_train.shape[1] * X_train.shape[2] # 28 * 28
X_train = X_train.reshape(X_train.shape[0], num_pixels).astype('float32') # 60000 , 784
# 784要素のArrayが60000個ある2次元配列になった。
# print(X_train.shape)
X_test = X_test.reshape(X_test.shape[0], num_pixels).astype('float32')


グレースケールは0 to 255で表しているが、これを255で割って0 to 1のスケールにする。

# normalize inputs from 0-255 to 0-1
X_train = X_train / 255
X_test = X_test / 255


教師データのラベルは0,1,2,3と正解の数値で表されているが、これを
0だったら [1,0,0,0,0,0,0,0,0,0]
5だったら [0,0,0,0,1,0,0,0,0,0]
と表すように変換する。

# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]


ついにモデルの定義をする。
1層目は入力784、出力784
2層目は入力784、出力10、活性化関数にsoftmaxを使っている。ざっくり言うと出力を確率に変えてくれるらしい。

損失関数はcategorical_crossentropy = Logarithmic loss


# create model
model = Sequential()
model.add(Dense(num_pixels, input_dim=num_pixels, 
                kernel_initializer='normal', activation='relu'))
model.add(Dense(num_classes, kernel_initializer='normal', activation='softmax'))
# Compile model
model.compile(loss='categorical_crossentropy', 
              optimizer='adam', metrics=['accuracy'])


データを与えて、モデルを最適化する
200イメージごとにモデルのパラメータをアップデートして、20回繰り返す。

最後にテストデータでテストしたスコアをプリント!

# Fit the model
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=20, batch_size=200, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Baseline Error: %.2f%%" % (100-scores[1]*100))




Baseline Error: 1.61%

が最終出力。つまり10000のイメージでテストしてみて、1.61%はこのモデルでの予想とはずれたが、98.4%は正解になったということ

こんなシンプルな2層のネットワークでも98.4%正解になると驚きだった。まあ人間がやれば99.9%ぐらい成功できるだろうけど。

ただこのチュートリアルはシンプル 編なようなので、次週もっと正解率を高めるモデル構築を見ていく。

たぶん使ってないDropoutを使うんだろうな。





0 件のコメント:

コメントを投稿