TensorFlowでFashion-MNISTを試してみた

ファッション画像?でMNIST

こんにちは。

AI coordinatorの清水秀樹です。

Fashion-MNISTというデータセットが公開されたので早速試してみました。

MNISTとの違いは数字データがファッション画像になっているところです。

どんなデータが入っているかというと、

ラベル データ
0  T-shirt/top
1  Trouser
2  Pullover
3  Dress
4  Coat
5  Sandal
6  Shirt
7  Sneaker
8  Bag
9  Ankle boot

 

なんで、そんなデータセットができたのかというと、公式サイトには以下のように書かれていました。

・MNISTは簡単すぎるし、既にみんな使っているから

だそうです。

 

う〜ん、なるほど。

 

いまいちピンとこないので、実際に動かしてみました。

 

参考サイト

以下、サイト(日本語版)を参考にしました。

TensorFlow: TensorFlow で Fashion-MNIST

 

開発環境

iMac (27-inch, Late 2012)

プロセッサ 2.9 GHz intel Core i5

macOS Sierra バージョン 10.12.4

Anaconda3-4.2.0-MacOSX-x86_64

python 3.5.2

tensorflow 1.0.0

keras 1.2.2

 

どんな画像が入っているのか除いてみました。

とりあえず1枚のトレーニング画像とテストデータを抜き出してみました。

以下のソースコードで簡単に抜き出せます。

# -*- coding: utf-8 -*-
import mnist_reader
import sys
import numpy as np
from keras.utils import np_utils
from PIL import Image

X_train, y_train = mnist_reader.load_mnist('data/fashion', kind='train')
X_test, y_test = mnist_reader.load_mnist('data/fashion', kind='t10k')

#訓練画像
train_no = 0
outImg = Image.fromarray(X_train[train_no].reshape((28,28))*255).convert("RGB")
outImg.save("train.png")

#テスト画像
test_no = 0
outImg = Image.fromarray(X_test[test_no].reshape((28,28))).convert("RGB")
outImg.save("test.png")

抜き出した画像は ‘train.png’と’test.png’という名前で保存されます。

ちっさ!!

そりゃそうですね。28×28サイズですから。

 

MNISTと比較してみた。

従来の数字のみのMNISTと、今回公開されたFashion-MNISTを比較してみます。

まずは従来の数字のみMNISTの結果です。

Epoch = 2で試した結果、

Train on 60000 samples, validate on 10000 samples
Epoch 1/2
60000/60000 [==============================] - 8s - loss: 0.2515 - acc: 0.9239 - val_loss: 0.1021 - val_acc: 0.9690
Epoch 2/2
60000/60000 [==============================] - 7s - loss: 0.1018 - acc: 0.9686 - val_loss: 0.0950 - val_acc: 0.9679
 9888/10000 [============================>.] - ETA: 0sloss= 0.0949767166178
accuracy= 0.9679

accuracy = 0.9679と、たった2回の学習でかなりの精度が出ています。

 

続いて、Fashion-MNISTの結果です。

Train on 60000 samples, validate on 10000 samples
Epoch 1/2
60000/60000 [==============================] - 7s - loss: 0.5189 - acc: 0.8126 - val_loss: 0.3969 - val_acc: 0.8528
Epoch 2/2
60000/60000 [==============================] - 7s - loss: 0.3864 - acc: 0.8600 - val_loss: 0.3377 - val_acc: 0.8764
 9280/10000 [==========================>...] - ETA: 0sloss= 0.337676012874
accuracy= 0.8764

accuracy = 0,8764となりました。

 

確かに、数字のみMNISTよりもFashion-MNISTの方が精度が出にくい感じですね。

難易度が上がったことが実感できました。

 

Fashion-MNISTを試したソースコード

試したい方は、以下のサイトからデータをクローンしましょう。

https://github.com/zalandoresearch/fashion-mnist

 

実行するには、公式サイトにも記載があるように、

utils/mnist_reader を使用する必要があります。

 

筆者は、いきなりこれにハマりました。

import mnist_reader

を実行するために、utils/mnist_reader が必要になります。

このモジュールは、上記サイトからクローンしたフォルダ内にあります。

これがないと、データをimportできません。

 

以下、今回使用したソースコードになります。

数字版MNISTの使い回しなので、コメントなど適当なのはご容赦ください。

import mnist_reader
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import Adam 
from keras.utils import np_utils

from keras.utils.visualize_util import plot
import matplotlib.pyplot as plt

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'))

    # 損失関数の定義
    model.compile(
        loss='categorical_crossentropy',
        optimizer=Adam(),
        metrics=['accuracy'])
    
    return model

def plot_history(history):
    # 精度の履歴をプロット
    plt.plot(history.history['acc'],"o-",label="accuracy")
    plt.plot(history.history['val_acc'],"o-",label="val_acc")
    plt.title('model accuracy')
    plt.xlabel('epoch')
    plt.ylabel('accuracy')
    plt.legend(loc="lower right")
    plt.show()
 
    # 損失の履歴をプロット
    plt.plot(history.history['loss'],"o-",label="loss",)
    plt.plot(history.history['val_loss'],"o-",label="val_loss")
    plt.title('model loss')
    plt.xlabel('epoch')
    plt.ylabel('loss')
    plt.legend(loc='lower right')
    plt.show()

if __name__ == "__main__":
    # MNISTのデータの読み込み
    # 訓練データ6万件、テストデータ1万件
    # 28ピクセル × 28ピクセル = 784ピクセルのデータ
    # 色は0〜255
    X_train, y_train = mnist_reader.load_mnist('data/fashion', kind='train')
    X_test, y_test = mnist_reader.load_mnist('data/fashion', kind='t10k')
    X_train = X_train.reshape(60000, 784).astype('float32')
    X_test  = X_test.reshape(10000, 784).astype('float32')
    X_train /= 255
    X_test  /= 255

    # 10次元配列に変換 //数字の5ならこんな感じ[0,0,0,0,1,0,0,0,0,0]
    y_train = np_utils.to_categorical(y_train, 10)
    y_test  = np_utils.to_categorical(y_test, 10)

    # データで訓練 今回は時間省略のため2回で学習する
    model = build_model()
    history = model.fit(X_train, y_train, 
        nb_epoch=50, #学習させる回数 今回は2 回数はお好みで pytyonのnb_epochとはrangeの繰り返しのこと
        batch_size=128, #無作為に128画像取得している。数字はなんでも良い
        validation_data=(X_test, y_test)
    )


    #学習モデルの保存
    json_string = model.to_json()
    #モデルのファイル名 拡張子.json
    open('mnist.json', 'w').write(json_string)
    #重みファイルの保存 拡張子がhdf5
    model.save_weights('mnist.hdf5')

    # モデルの評価を行う
    score = model.evaluate(X_test, y_test, verbose=1)

    print('loss=', score[0])
    print('accuracy=', score[1])
    
    # modelに学習させた時の変化の様子をplot
    plot_history(history)

 

精度を出すために、epoch = 50 で実施してみた結果、

Epoch 49/50
60000/60000 [==============================] - 8s - loss: 0.1336 - acc: 0.9479 - val_loss: 0.3355 - val_acc: 0.9029
Epoch 50/50
60000/60000 [==============================] - 7s - loss: 0.1351 - acc: 0.9477 - val_loss: 0.3284 - val_acc: 0.9009
 9280/10000 [==========================>...] - ETA: 0sloss= 0.328375703002
accuracy= 0.9009

なるほど。

epoch = 10 あたりから、過学習が発生しています。

精度をあげるには学習モデルの工夫が必要そうですね。

確かに従来のMNISTよりFashion-MNISTの方が難易度が上がっていますね。

どんな学習モデルにすれば精度が出るのか考えることで、色々勉強になりそうです。

 

興味がある方は参考にしてみてください。

また、これからDeep Learningの勉強をするなら、こちらで紹介する書籍も参考になりますので一読してみることをオススメします。

 

 

それではまた。

あなたにオススメの記事

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

PAGE TOP