機械学習のモデルを評価する時によく使われる、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 件のコメント:
コメントを投稿