とりあえず書いてみた
KerasでMNISTコードを書くのは初めてだったので、このサイトを参考に書いてみた
http://aidiary.hatenablog.com/entry/20161109/1478696865
はじめにMNISTのデータを準備する
from keras.datasets import mnist
from keras.utils import np_utils
(x_train,y_train),(x_test,y_test) = mnist.load_data()
データを使える形に変換する。
x_train = x_train.reshape(len(x_train),784)
x_test = x_test.reshape(len(x_test),784)
x_train = x_train.astype("float32")
x_test = x_test.astype("float32")
x_train = x_train / 255
x_test = x_test / 255
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
nb_classes = 10
y_train = np_utils.to_categorical(y_train,nb_classes)
y_test = np_utils.to_categorical(y_test,nb_classes)
入力データ(x_train
,x_test
)はもともと28x28の二次元配列なのでそれを784の一次元配列に変換する。また0〜255という数字は扱えないので0〜1に変換するために255で割っている。
出力データ(y_train
,y_test
)はもともと数字が入っているがone-hot形式に変換したほうが使いやすいのでnp_utils.to_categorical()
を使う。
実際にモデルを作る
def build_model():
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"))
return model
model = build_model()
model.summary()
model.compile(loss="categorical_crossentropy",
optimizer=Adam(),
metrics=['accuracy'])
ここではmodel.summary()
はモデルの層を表示するだけなので書かなくてもいいが今回は見てみたかったので書いておいた。
実際に実行すると下のような出力になった。
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 512) 401920
_________________________________________________________________
activation_1 (Activation) (None, 512) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 512) 0
_________________________________________________________________
dense_2 (Dense) (None, 512) 262656
_________________________________________________________________
activation_2 (Activation) (None, 512) 0
_________________________________________________________________
dropout_2 (Dropout) (None, 512) 0
_________________________________________________________________
dense_3 (Dense) (None, 10) 5130
_________________________________________________________________
activation_3 (Activation) (None, 10) 0
=================================================================
Total params: 669,706
Trainable params: 669,706
Non-trainable params: 0
_________________________________________________________________
学習させてみる
参考にしたサイトに過学習を防止するためのコードが書かれていたので少し変えて使用させていただいた。
early_stopping = EarlyStopping(patience=2)
model.fit(x_train,y_train,
batch_size=32,
epochs=100,
verbose=1,
validation_split=0.1,
shuffle=True,
callbacks=[early_stopping])
ここではEarlyStopping
を利用して過学習をしているようなら中断するようにした。この時、patience
を2
にすることで学習不足も防止できるようにしてみた。(MNISTでそこまで影響があるかわからない)
これだけで実際、精度は0.98以上出ているのでしっかり学習できていると思う。
テストデータで確認
テストデータで最後に精度を確認した
print(model.evaluate(x_test,y_test))
ロスと精度が出てくるので確認してみると0.97以上出てくるので精度はかなり高い。
元のデータを加工して学習させる
元のデータを少し回転させてもっと読み取り精度を高めてみた
回転させるためにはPILを使った。
下をインポートする。
from PIL import Image
import numpy as np
まずは入力データに回転を加えた。
#deg = 回転させる角度
#n = 生成する枚数
def rotate_array(x_array,deg,n):
def rotate(x):
img = Image.fromarray(x)
arr = []
for _ in range(n):
arr.append(np.asarray(img.rotate(np.random.rand()*deg*2-deg)))
return arr
x_out = []
for x in x_array:
arr = rotate(x)
for a in arr:
x_out.append(a)
return np.array(x_out)
x_train = rotate_array(x_train,30,10)
x_test = rotate_array(x_test,30,10)
これだけでは出力側と合わなくなるので下のコードを書いた。
def add_y(y_array,n):
y_out = []
for y in y_array:
for _ in range(n):
y_out.append(y)
return np.array(y_out)
y_train = add_y(y_train,10)
y_test = add_y(y_test,10)
回転したデータで学習
これでデータに回転がかかり学習できる状態になったので学習させた
10倍のデータがあるので自分の環境では時間がかった。model.fit()
の中のbatch_size
を128
にあげるともう少し早く終了した。
精度は0.98以上が出ていた。
結果
予想していたよりも簡単にとても高い精度が出るものが作れた。
このあと角度を45度、60度で試してみたがどちらもとても高い精度が出て驚いた。
Kerasを利用して他の画像認識なども試してみようと思った。