2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

機械学習で「令和」Tシャツと「平成」Tシャツを見分ける。

Last updated at Posted at 2019-04-14

目的

2019.4.1.に新元号「令和」が発表されました。
540px-Yoshihide_Suga_announcing_new_imperial_era_Reiwa_2_(cropped).jpg

「人々が美しく心を寄せ合う中で文化が生まれ育つ」という意味が込められているようで、
災害や景気変動の影響が残る平成時代の課題を踏まえ、良い時代を創っていければと切に願います。

一方で、新しい元号にちなんだ商品もちらほら見かけるようになりました。
スクリーンショット 2019-04-13 17.32.36.png

そういえば、平成Tシャツあったな、と思い出しまして、
heisei1.jpg

今回は、これら商品の文字がどの程度機械学習で分類可能か試したいと思います。

準備

1.「令和」「平成」の文字画像を用意します。

  • 令和 20枚
スクリーンショット 2019-04-14 18.03.28.png
  • 平成 20枚
スクリーンショット 2019-04-14 18.03.55.png
  • 最終評価用 6枚 ※文字の部分は切り出して使います、一部の画像は有名人の方の画像を使わせて頂きます。
スクリーンショット 2019-04-14 18.09.16.png

2.学習(train)/検証(validation)/最終評価(evaluation)フォルダにそれぞれ格納します。

data-org

  • train
      reiwa :用意した「令和」のうち16枚をこちらに格納
      heisei :用意した「平成」のうち16枚をこちらに格納
  • validation
      reiwa ::用意した「令和」のうち4枚をこちらに格納
      heisei :用意した「平成」のうち4枚をこちらに格納
  • evaluation 6枚
      
    3.機械学習用コード準備(後述のlearn.py)
     学習データの数を増やせるのが望ましいですが準備工数削減のため、
     ImageDataGeneratorで、回転/ズーム/などを駆使して枚数増やします。

コード

'learn.py'
from tensorflow.python.keras import layers
from tensorflow.python.keras import models
from tensorflow.python.keras import optimizers
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import glob

# モデルの定義
model = models.Sequential()
model.add(layers.Conv2D(16, (3, 3), activation='relu', input_shape=(256, 256, 3)))
model.add(layers.Conv2D(16, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(32, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))

# モデルのコンパイル
model.compile(optimizer='rmsprop',
              loss='binary_crossentropy',
              metrics=['acc'])

model.summary()

# クラス宣言
train_datagen = ImageDataGenerator(
    rescale=1.0 / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1.0 / 255)


# フォルダ指定
batch_size=20
train_generator = train_datagen.flow_from_directory(
    'data/train',
    target_size=(256, 256),
    batch_size=batch_size,
    class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
    'data/validation',
    target_size=(256, 256),
    batch_size=batch_size,
    class_mode='binary')

print(train_generator.class_indices)


# 学習
history = model.fit_generator(train_generator,
                              steps_per_epoch=10,
                              epochs=10,
                              validation_data=validation_generator,
                              validation_steps=10)

acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']

epochs = range(1, len(acc) + 1)

print(acc);
print(val_acc);
print(loss);
print(val_loss);

plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.savefig("figure-acc.png")
plt.figure()

plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.savefig("figure-loss.png")

# evaluation
paths = glob.glob("./data/evaluation/*.jpg")
for path in paths:
    img = Image.open(path).convert('RGB')
    img = img.resize((256, 256))
    x = np.array(img)
    x = x / 255.
    x = x[None, ...]
    pred_prob = model.predict(x, batch_size=1, verbose=0)

    # 2値分類なので[0,1]の確率を出力する。0.5以上なら1とする。
    pred = np.round(pred_prob, 0)

    print("---{0}---".format(path))
    print(pred_prob)
    print("{0}の予測結果は{1}です.".format(path, pred))

テスト

学習stepのさじ加減は調整必要ですが、とりあえず15epochを指定して学習。
(もっと良いパラメータがあるはず)

2019-04-14 17:34:11.610592: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 254, 254, 16)      448       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 252, 252, 16)      2320      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 126, 126, 16)      0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 124, 124, 32)      4640      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 62, 62, 32)        0         
_________________________________________________________________
flatten (Flatten)            (None, 123008)            0         
_________________________________________________________________
dense (Dense)                (None, 512)               62980608  
_________________________________________________________________
dense_1 (Dense)              (None, 256)               131328    
_________________________________________________________________
dense_2 (Dense)              (None, 1)                 257       
=================================================================
Total params: 63,119,601
Trainable params: 63,119,601
Non-trainable params: 0
_________________________________________________________________
Found 32 images belonging to 2 classes.
Found 8 images belonging to 2 classes.
{'heisei': 0, 'reiwa': 1}
Epoch 1/15
10/10 [==============================] - 18s 2s/step - loss: 8.1931 - acc: 0.4750 - val_loss: 0.8280 - val_acc: 0.5000
Epoch 2/15
10/10 [==============================] - 16s 2s/step - loss: 0.7148 - acc: 0.4875 - val_loss: 0.7022 - val_acc: 0.5000
Epoch 3/15
10/10 [==============================] - 17s 2s/step - loss: 0.7318 - acc: 0.5250 - val_loss: 0.7039 - val_acc: 0.5000
Epoch 4/15
10/10 [==============================] - 18s 2s/step - loss: 0.6831 - acc: 0.5437 - val_loss: 0.7165 - val_acc: 0.5000
Epoch 5/15
10/10 [==============================] - 18s 2s/step - loss: 0.9253 - acc: 0.5375 - val_loss: 0.6806 - val_acc: 0.5375
Epoch 6/15
10/10 [==============================] - 16s 2s/step - loss: 0.6640 - acc: 0.6438 - val_loss: 0.6785 - val_acc: 0.4875
Epoch 7/15
10/10 [==============================] - 17s 2s/step - loss: 0.6093 - acc: 0.6812 - val_loss: 0.7921 - val_acc: 0.4000
Epoch 8/15
10/10 [==============================] - 16s 2s/step - loss: 0.6163 - acc: 0.6875 - val_loss: 0.8923 - val_acc: 0.4500
Epoch 9/15
10/10 [==============================] - 16s 2s/step - loss: 0.5593 - acc: 0.7312 - val_loss: 0.8695 - val_acc: 0.5625
Epoch 10/15
10/10 [==============================] - 17s 2s/step - loss: 0.5669 - acc: 0.7063 - val_loss: 0.8767 - val_acc: 0.3125
Epoch 11/15
10/10 [==============================] - 16s 2s/step - loss: 0.6163 - acc: 0.7188 - val_loss: 0.8409 - val_acc: 0.5000
Epoch 12/15
10/10 [==============================] - 16s 2s/step - loss: 0.5653 - acc: 0.7125 - val_loss: 0.9275 - val_acc: 0.4125
Epoch 13/15
10/10 [==============================] - 17s 2s/step - loss: 0.6229 - acc: 0.7625 - val_loss: 0.8779 - val_acc: 0.3500
Epoch 14/15
10/10 [==============================] - 17s 2s/step - loss: 0.5152 - acc: 0.7625 - val_loss: 0.8519 - val_acc: 0.5125
Epoch 15/15
10/10 [==============================] - 17s 2s/step - loss: 0.5381 - acc: 0.7563 - val_loss: 0.7191 - val_acc: 0.5000

figure-acc.png

実画像評価

最終評価用の画像データ6枚を使用

スクリーンショット 2019-04-14 18.14.37.png 期待値:平成  予測値:平成
---./data_org/evaluation/heisei1-2.jpg---
[[0.04057287]]
./data_org/evaluation/heisei1-2.jpgの予測結果は[[0.]]です.
スクリーンショット 2019-04-14 18.14.41.png 期待値:平成  予測値:平成 ※スコアぎりぎり
---./data_org/evaluation/heisei2-2.jpg---
[[0.4843383]]
./data_org/evaluation/heisei2-2.jpgの予測結果は[[0.]]です.
スクリーンショット 2019-04-14 18.14.18.png 期待値:令和  予測値:令和 ※スコアぎりぎり
---./data_org/evaluation/reiwa1-1.jpg---
[[0.5244837]]
./data_org/evaluation/reiwa1-1.jpgの予測結果は[[1.]]です.
スクリーンショット 2019-04-14 18.14.22.png

期待値:令和  予測値:令和

---./data_org/evaluation/reiwa2-2.jpg---
[[0.93729514]]
./data_org/evaluation/reiwa2-2.jpgの予測結果は[[1.]]です.
スクリーンショット 2019-04-14 18.14.27.png

期待値:令和  予測値:令和

---./data_org/evaluation/reiwa3-2.jpg---
[[0.9273448]]
./data_org/evaluation/reiwa3-2.jpgの予測結果は[[1.]]です.
スクリーンショット 2019-04-14 18.14.30.png

期待値:令和  予測値:令和

---./data_org/evaluation/reiwa4-2.jpg---
[[0.9319874]]
./data_org/evaluation/reiwa4-2.jpgの予測結果は[[1.]]です.
スクリーンショット 2019-04-14 18.14.34.png

期待値:令和  予測値:令和 ※スコアぎりぎり

---./data_org/evaluation/reiwa5-2.jpg---
[[0.6226176]]
./data_org/evaluation/reiwa5-2.jpgの予測結果は[[1.]]です.

感想

もっと明確に評価スコアが分かれると思いましたが、ぎりぎりのデータが数個ありました。
全体の結果は期待通りとなったものが多いですが、サンプル数が乏しく、本当に性能に問題ないのかは確認継続が必要だと考えています。残課題は下記の通り。
・過学習していないか、学習が足りないのではないか要確認
  →入力データのノイズがどれくらい影響している?
・ハイパーパラメータ調整
・汎化性能の評価

もし詳しい方がおられれば、ご指導頂ければと思います。

CodeingError対策

OSError: cannot identify image file './data_org/train/showa//.DS_Store'

DS_StoreはMacのメタデータのようです。python処理に不要であれば下記コマンド等で消しましょう。
$ find ./data_org/ -name .DS_Store | xargs rm

参考

令和-wikipedia
Python: コマンドライン引数とは?(超基礎)
macから.DS_Storeを消しさる
ImageDataGeneratorクラス
SequentialモデルでKerasを始めてみよう
そのモデル、過学習してるの?未学習なの?と困ったら

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?