LoginSignup
4
9

More than 5 years have passed since last update.

KerasでMNIST

Posted at

とりあえず書いてみた

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()はモデルの層を表示するだけなので書かなくてもいいが今回は見てみたかったので書いておいた。
実際に実行すると下のような出力になった。

output
_________________________________________________________________
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を利用して過学習をしているようなら中断するようにした。この時、patience2にすることで学習不足も防止できるようにしてみた。(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_size128にあげるともう少し早く終了した。
精度は0.98以上が出ていた。

結果

予想していたよりも簡単にとても高い精度が出るものが作れた。
このあと角度を45度、60度で試してみたがどちらもとても高い精度が出て驚いた。
Kerasを利用して他の画像認識なども試してみようと思った。

4
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
9