Help us understand the problem. What is going on with this article?

KerasでMNIST

More than 1 year has passed since last update.

とりあえず書いてみた

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を利用して他の画像認識なども試してみようと思った。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした