こんにちは、絶賛プログラミング勉強中のtomoです。
Aidemyで画像認識について勉強し始めて1ヶ月が経ったので、学習成果として投稿します。
#はじめに
突然ですが、皆さん「緑茶の中でも選ばれてしまう緑茶は何か」と問われたら何と答えますか?
おそらく50%以上の人は「綾鷹」と答えるかと思います。
この記事では、そんな綾鷹を画像認識によって人々に選ばせるAIを作成します。
#Aidemyで学習した内容
「ディープラーニングで画像認識モデルを作ってみよう!」ルートで8つのコースを学びました。
特に「CNNを用いた画像認識」コースにおいて学んだ技術を複数使用しています。
(後述する目次の「⑵モデルを構築/学習する」の仕組みを学べます。)
#目次
・実装概要
・AIの作成
⑴Iphoneで撮った写真を学習/検証データにする
⑵モデルを構築/学習する
①シンプルにモデルを構築する
②データを拡張する
③dropoutを追加する
⑶綾鷹を選ばせるプログラムを作る
・おわりに
・(2018/06/23)追加検証
#実装概要
以下の3点を実装します。
・緑茶のペットボトルの写真から、商品名を予測
・予測結果が綾鷹である場合、「選ばれたのは、綾鷹でした。」と表示
・綾鷹でない場合、「綾鷹を選んでください。(もしかして:あなたが選んでいるのは
「(緑茶の名前)」ではありませんか?)」と表示
#AIの作成
早速AIを作成していきます。
以下の流れで進めます。
⑴Iphoneで撮った写真を学習/検証データにする
⑵予測モデルを構築/学習する
⑶綾鷹を選ばせるプログラムを作る
##⑴Iphoneで撮った写真を学習/検証データにする
今回予測の対象とする緑茶は以下の10種類とします。
ジャケ写のようになりました。
各種緑茶について、42枚ずつ撮影します。
ちなみに、お茶を500枚近く撮影する姿を家族に見られ、「お前大丈夫か?」と心配されました。
撮影したデータについて、以下のコードでラベリング(画像データと商品名の紐付け)を実施し、学習/検証データを用意します。
なお、各商品ごとにディレクトリを作成し、画像データを格納しているのを前提としてます。
#ラベリングによる学習/検証データの準備
from PIL import Image
import os, glob
import numpy as np
import random, math
#画像が保存されているルートディレクトリのパス
root_dir = "パス"
# 商品名
categories = ["綾鷹","お〜いお茶 抹茶入り","なごみ","お〜いお茶 新茶",
"綾鷹 茶葉のあまみ","お〜いお茶","伊右衛門","お〜いお茶 濃い茶",
"生茶","お〜いお茶 新緑"]
# 画像データ用配列
X = []
# ラベルデータ用配列
Y = []
#画像データごとにadd_sample()を呼び出し、X,Yの配列を返す関数
def make_sample(files):
global X, Y
X = []
Y = []
for cat, fname in files:
add_sample(cat, fname)
return np.array(X), np.array(Y)
#渡された画像データを読み込んでXに格納し、また、
#画像データに対応するcategoriesのidxをY格納する関数
def add_sample(cat, fname):
img = Image.open(fname)
img = img.convert("RGB")
img = img.resize((150, 150))
data = np.asarray(img)
X.append(data)
Y.append(cat)
#全データ格納用配列
allfiles = []
#カテゴリ配列の各値と、それに対応するidxを認識し、全データをallfilesにまとめる
for idx, cat in enumerate(categories):
image_dir = root_dir + "/" + cat
files = glob.glob(image_dir + "/*.jpg")
for f in files:
allfiles.append((idx, f))
#シャッフル後、学習データと検証データに分ける
random.shuffle(allfiles)
th = math.floor(len(allfiles) * 0.8)
train = allfiles[0:th]
test = allfiles[th:]
X_train, y_train = make_sample(train)
X_test, y_test = make_sample(test)
xy = (X_train, X_test, y_train, y_test)
#データを保存する(データの名前を「tea_data.npy」としている)
np.save("保存先パス/tea_data.npy", xy)
##⑵予測モデルを構築/学習する
モデルは畳み込みニューラルネットワーク(CNN)を使います。
シンプルなモデルから始め、精度をあげる工夫を追加していきます。
###①シンプルにモデルを構築する
まずはシンプルにモデルを構築します。
#モデルの構築
from keras import layers, models
model = models.Sequential()
model.add(layers.Conv2D(32,(3,3),activation="relu",input_shape=(150,150,3)))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64,(3,3),activation="relu"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation="relu"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128,(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(10,activation="sigmoid")) #分類先の種類分設定
#モデル構成の確認
model.summary()
「model.summary()」でモデル構成を確認できます。
続いて、モデルをコンパイルします。
#モデルのコンパイル
from keras import optimizers
model.compile(loss="binary_crossentropy",
optimizer=optimizers.RMSprop(lr=1e-4),
metrics=["acc"])
先ほど作成した学習/検証データを読み込み、データの正規化といった学習に向けた準備をします。
#データの準備
from keras.utils import np_utils
import numpy as np
categories = ["綾鷹","お〜いお茶 抹茶入り","なごみ","お〜いお茶 新茶",
"綾鷹 茶葉のあまみ","お〜いお茶","伊右衛門","お〜いお茶 濃い茶",
"生茶","お〜いお茶 新緑"]
nb_classes = len(categories)
X_train, X_test, y_train, y_test = np.load("保存した学習データ・テストデータのパス")
#データの正規化
X_train = X_train.astype("float") / 255
X_test = X_test.astype("float") / 255
#kerasで扱えるようにcategoriesをベクトルに変換
y_train = np_utils.to_categorical(y_train, nb_classes)
y_test = np_utils.to_categorical(y_test, nb_classes)
準備したデータを使ってモデルを学習させます。
#モデルの学習
model = model.fit(X_train,
y_train,
epochs=10,
batch_size=6,
validation_data=(X_test,y_test))
epochごとに学習結果が表示されます。
Train on 336 samples, validate on 84 samples
Epoch 1/10
336/336 [==============================] - 20s 59ms/step - loss: 0.3543 - acc: 0.8887 - val_loss: 0.3321 - val_acc: 0.9000
Epoch 2/10
336/336 [==============================] - 20s 60ms/step - loss: 0.3214 - acc: 0.9000 - val_loss: 0.3152 - val_acc: 0.9000
Epoch 3/10
336/336 [==============================] - 19s 57ms/step - loss: 0.2802 - acc: 0.9012 - val_loss: 0.2602 - val_acc: 0.9083
Epoch 4/10
336/336 [==============================] - 20s 59ms/step - loss: 0.2119 - acc: 0.9179 - val_loss: 0.2072 - val_acc: 0.9262
Epoch 5/10
336/336 [==============================] - 20s 60ms/step - loss: 0.1548 - acc: 0.9423 - val_loss: 0.1791 - val_acc: 0.9345
Epoch 6/10
336/336 [==============================] - 21s 63ms/step - loss: 0.1217 - acc: 0.9536 - val_loss: 0.1331 - val_acc: 0.9488
Epoch 7/10
336/336 [==============================] - 20s 59ms/step - loss: 0.0950 - acc: 0.9664 - val_loss: 0.1264 - val_acc: 0.9536
Epoch 8/10
336/336 [==============================] - 21s 62ms/step - loss: 0.0747 - acc: 0.9759 - val_loss: 0.1395 - val_acc: 0.9429
Epoch 9/10
336/336 [==============================] - 20s 60ms/step - loss: 0.0646 - acc: 0.9792 - val_loss: 0.1314 - val_acc: 0.9476
Epoch 10/10
336/336 [==============================] - 19s 58ms/step - loss: 0.0513 - acc: 0.9830 - val_loss: 0.1073 - val_acc: 0.9631
学習が完了しましたら、学習結果をグラフで表示します。
#学習結果を表示
import matplotlib.pyplot as plt
acc = model.history['acc']
val_acc = model.history['val_acc']
loss = model.history['loss']
val_loss = model.history['val_loss']
epochs = range(len(acc))
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('精度を示すグラフのファイル名')
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('損失値を示すグラフのファイル名')
6epoch目から精度が下がって(損失値が上がって)います。データ数が少なく、過学習を起こしていると思われます。
学習結果を保存しておきます。
#モデルの保存
json_string = model.model.to_json()
open('保存先パス/tea_predict.json', 'w').write(json_string)
#重みの保存
hdf5_file = "保存先パス/tea_predict.hdf5"
model.model.save_weights(hdf5_file)
続いて、学習させたモデルについて、未知のデータでテストします。(データ拡張は未実施)
一応、テストデータを準備するためのコードを貼っておきます。
from PIL import Image
import os, glob
import numpy as np
import random, math
# 画像が保存されているディレクトリのパス
root_dir = "パス"
# 画像が保存されているフォルダ名
categories = ["綾鷹","お〜いお茶 抹茶入り","なごみ","お〜いお茶 新茶",
"綾鷹 茶葉のあまみ","お〜いお茶","伊右衛門","お〜いお茶 濃い茶",
"生茶","お〜いお茶 新緑"]
X = [] # 画像データ
Y = [] # ラベルデータ
# フォルダごとに分けられたファイルを収集
#(categoriesのidxと、画像のファイルパスが紐づいたリストを生成)
allfiles = []
for idx, cat in enumerate(categories):
image_dir = root_dir + "/" + cat
files = glob.glob(image_dir + "/*.jpg")
for f in files:
allfiles.append((idx, f))
for cat, fname in allfiles:
img = Image.open(fname)
img = img.convert("RGB")
img = img.resize((150, 150))
data = np.asarray(img)
X.append(data)
Y.append(cat)
x = np.array(X)
y = np.array(Y)
np.save("保存先のパス/tea_data_test_X_150.npy", x)
np.save("保存先のパス/tea_data_test_Y_150.npy", y)
作成したテストデータを用いてモデルの予測精度を測ります。
# モデルの精度を測る
#評価用のデータの読み込み
eval_X = np.load("保存先のパス/tea_data_test_X_150.npy")
eval_Y = np.load("保存先のパス/tea_data_test_Y_150.npy")
#Yのデータをone-hotに変換
from keras.utils import np_utils
test_Y = np_utils.to_categorical(test_Y, 10)
score = model.model.evaluate(x=test_X,y=test_Y)
print('loss=', score[0])
print('accuracy=', score[1])
予測結果です。正解率は93.4%ですね。
100/100 [==============================] - 2s 20ms/step
loss= 1.02928255677
accuracy= 0.934000020027
その他、精度をあげるであろう手法をいくつか試していきます。
###②データを拡張する
①では、画像数が少ないことから、過学習を起こしているように見えました。
そのため、KerasのImageDataGeneratorを使って画像を水増しします。
#画像の水増し
import os
import glob
import numpy as np
from keras.preprocessing.image import ImageDataGenerator,
load_img, img_to_array, array_to_img
# 画像を拡張する関数
def draw_images(generator, x, dir_name, index):
save_name = 'extened-' + str(index)
g = generator.flow(x, batch_size=1, save_to_dir=output_dir,
save_prefix=save_name, save_format='jpeg')
# 1つの入力画像から何枚拡張するかを指定(今回は50枚)
for i in range(50):
bach = g.next()
# 出力先ディレクトリの設定
output_dir = "出力先のディレクトリパス"
if not(os.path.exists(output_dir)):
os.mkdir(output_dir)
# 拡張する画像の読み込み
images = glob.glob(os.path.join("画像の保存先ディレクトリのパス", "*.jpg"))
# ImageDataGeneratorを定義
datagen = ImageDataGenerator(rotation_range=30,
width_shift_range=20,
height_shift_range=0.,
zoom_range=0.1,
horizontal_flip=True,
vertical_flip=True)
:]
# 読み込んだ画像を順に拡張
for i in range(len(images)):
img = load_img(images[i])
img = img.resize((150, 150))
x = img_to_array(img)
x = np.expand_dims(x, axis=0)
draw_images(datagen, x, output_dir, i)
うまく複製できているか確認します。
ん?、ちょっと画像が粗いように思えます。①の時点で確認して気付けって話ですが。
「img.resize((150, 150))」を「img.resize((250, 250))」に変更して再度水増しします。
このレベルであれば十分目で判断できますね。
①と同じようにモデルを学習させます。
(各種パスの修正、また、モデルのinput sizeを2502503に修正する必要があります。)
以下、学習結果です。
Train on 3360 samples, validate on 840 samples
Epoch 1/10
3360/3360 [==============================] - 604s 180ms/step - loss: 0.3157 - acc: 0.9002 - val_loss: 0.2828 - val_acc: 0.9008
Epoch 2/10
3360/3360 [==============================] - 618s 184ms/step - loss: 0.2446 - acc: 0.9086 - val_loss: 0.2084 - val_acc: 0.9198
Epoch 3/10
3360/3360 [==============================] - 608s 181ms/step - loss: 0.1824 - acc: 0.9320 - val_loss: 0.1750 - val_acc: 0.9323
Epoch 4/10
3360/3360 [==============================] - 613s 183ms/step - loss: 0.1400 - acc: 0.9470 - val_loss: 0.1241 - val_acc: 0.9551
Epoch 5/10
3360/3360 [==============================] - 1054s 314ms/step - loss: 0.1068 - acc: 0.9610 - val_loss: 0.1053 - val_acc: 0.9625
Epoch 6/10
3360/3360 [==============================] - 572s 170ms/step - loss: 0.0795 - acc: 0.9717 - val_loss: 0.0733 - val_acc: 0.9735
Epoch 7/10
3360/3360 [==============================] - 564s 168ms/step - loss: 0.0639 - acc: 0.9775 - val_loss: 0.0681 - val_acc: 0.9723
Epoch 8/10
3360/3360 [==============================] - 3426s 1s/step - loss: 0.0480 - acc: 0.9837 - val_loss: 0.0707 - val_acc: 0.9737
Epoch 9/10
3360/3360 [==============================] - 635s 189ms/step - loss: 0.0380 - acc: 0.9871 - val_loss: 0.0577 - val_acc: 0.9770
Epoch 10/10
3360/3360 [==============================] - 653s 194ms/step - loss: 0.0277 - acc: 0.9907 - val_loss: 0.0376 - val_acc: 0.9867
精度上がってますね。
テストデータを250*250に変更した上で作成し、予測精度を測ります。
100/100 [==============================] - 5s 51ms/step
loss= 0.377869169712
accuracy= 0.975000026226
正解率97.5%、水増し前より4%上昇しました。
###③dropoutを追加する
過学習を抑制するdropoutをモデルに追加します。
#モデルの構築
from keras import layers, models
model = models.Sequential()
model.add(layers.Conv2D(32,(3,3),activation="relu",input_shape=(250,250,3)))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(64,(3,3),activation="relu"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation="relu"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation="relu"))
model.add(layers.MaxPooling2D((2,2)))
model.add(layers.Flatten())
model.add(layers.Dropout(0.5))
model.add(layers.Dense(512,activation="relu"))
model.add(layers.Dense(10,activation="sigmoid"))
②と同様に学習させます。
以下、学習結果。
Train on 3360 samples, validate on 840 samples
Epoch 1/10
3360/3360 [==============================] - 568s 169ms/step - loss: 0.3291 - acc: 0.8956 - val_loss: 0.2981 - val_acc: 0.9000
Epoch 2/10
3360/3360 [==============================] - 596s 177ms/step - loss: 0.2635 - acc: 0.9058 - val_loss: 0.2276 - val_acc: 0.9129
Epoch 3/10
3360/3360 [==============================] - 647s 192ms/step - loss: 0.2097 - acc: 0.9197 - val_loss: 0.1930 - val_acc: 0.9274
Epoch 4/10
3360/3360 [==============================] - 694s 206ms/step - loss: 0.1734 - acc: 0.9338 - val_loss: 0.1612 - val_acc: 0.9400
Epoch 5/10
3360/3360 [==============================] - 710s 211ms/step - loss: 0.1406 - acc: 0.9457 - val_loss: 0.1403 - val_acc: 0.9446
Epoch 6/10
3360/3360 [==============================] - 669s 199ms/step - loss: 0.1135 - acc: 0.9565 - val_loss: 0.1111 - val_acc: 0.9550
Epoch 7/10
3360/3360 [==============================] - 597s 178ms/step - loss: 0.0921 - acc: 0.9654 - val_loss: 0.0819 - val_acc: 0.9731
Epoch 8/10
3360/3360 [==============================] - 592s 176ms/step - loss: 0.0736 - acc: 0.9736 - val_loss: 0.0707 - val_acc: 0.9773
Epoch 9/10
3360/3360 [==============================] - 596s 177ms/step - loss: 0.0583 - acc: 0.9793 - val_loss: 0.0585 - val_acc: 0.9790
Epoch 10/10
3360/3360 [==============================] - 588s 175ms/step - loss: 0.0474 - acc: 0.9836 - val_loss: 0.0496 - val_acc: 0.9819
テストデータで予測精度を測ります。
100/100 [==============================] - 5s 52ms/step
loss= 0.516686134338
accuracy= 0.967000012398
ありゃ、精度が下がりました。
②は過学習に至る前であり、単に学習効率が下がったということでしょうか。
損失率を0.25に下げて再度学習してみます。
Train on 3360 samples, validate on 840 samples
Epoch 1/10
3360/3360 [==============================] - 583s 173ms/step - loss: 0.3241 - acc: 0.8952 - val_loss: 0.2866 - val_acc: 0.9037
Epoch 2/10
3360/3360 [==============================] - 571s 170ms/step - loss: 0.2450 - acc: 0.9087 - val_loss: 0.2085 - val_acc: 0.9226
Epoch 3/10
3360/3360 [==============================] - 563s 167ms/step - loss: 0.1822 - acc: 0.9326 - val_loss: 0.1853 - val_acc: 0.9299
Epoch 4/10
3360/3360 [==============================] - 603s 180ms/step - loss: 0.1407 - acc: 0.9469 - val_loss: 0.1332 - val_acc: 0.9525
Epoch 5/10
3360/3360 [==============================] - 567s 169ms/step - loss: 0.1136 - acc: 0.9576 - val_loss: 0.1001 - val_acc: 0.9650
Epoch 6/10
3360/3360 [==============================] - 574s 171ms/step - loss: 0.0895 - acc: 0.9676 - val_loss: 0.0888 - val_acc: 0.9648
Epoch 7/10
3360/3360 [==============================] - 584s 174ms/step - loss: 0.0693 - acc: 0.9750 - val_loss: 0.0750 - val_acc: 0.9742
Epoch 8/10
3360/3360 [==============================] - 570s 170ms/step - loss: 0.0547 - acc: 0.9811 - val_loss: 0.0532 - val_acc: 0.9799
Epoch 9/10
3360/3360 [==============================] - 579s 172ms/step - loss: 0.0446 - acc: 0.9846 - val_loss: 0.0545 - val_acc: 0.9788
Epoch 10/10
3360/3360 [==============================] - 563s 168ms/step - loss: 0.0334 - acc: 0.9888 - val_loss: 0.0433 - val_acc: 0.9842
テストデータの予測結果。やはり②の方が精度が高いです。
100/100 [==============================] - 5s 53ms/step
loss= 0.432936085963
accuracy= 0.973000030518
ただ、グラフを見る限り、dropoutの損失率を0.5にした時が最もうまく学習できているようです。
今回はepoch数を10で固定していますが、epoch数を増やした時にdropoutが過学習を抑制し、さらに高い精度が出るのでは、、と思います。(後述の「(2018/06/23)追加検証」で検証しています。)
##⑶綾鷹を選ばせるプログラムを作る
②のモデルを採択し、綾鷹を選ばせるプログラムを作ります。
#綾鷹を選ばせるプログラム
from keras import models
from keras.models import model_from_json
from keras.preprocessing import image
import numpy as np
#保存したモデルの読み込み
model = model_from_json(open('保存先のフォルダ/tea_predict.json').read())
#保存した重みの読み込み
model.load_weights('保存先のフォルダ/tea_predict.hdf5')
categories = ["綾鷹","お〜いお茶 抹茶入り","なごみ","お〜いお茶 新茶","綾鷹 茶葉のあまみ",
"お〜いお茶","伊右衛門","お〜いお茶 濃い茶","生茶","お〜いお茶 新緑"]
#画像を読み込む
img_path = str(input())
img = image.load_img(img_path,target_size=(250, 250, 3))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
#予測
features = model.predict(x)
#予測結果によって処理を分ける
if features[0,0] == 1:
print ("選ばれたのは、綾鷹でした。")
elif features[0,4] == 1:
print ("選ばれたのは、綾鷹(茶葉のあまみ)でした。")
else:
for i in range(0,10):
if features[0,i] == 1:
cat = categories[i]
message = "綾鷹を選んでください。(もしかして:あなたが選んでいるのは「" + cat + "」ではありませんか?)"
print(message)
さて、テストしてみましょう。
出力結果:
選ばれたのは、綾鷹(茶葉のあまみ)でした。
出力結果:
綾鷹を選んでください。(もしかして:あなたが選んでいるのは「なごみ」ではありませんか?)
出力結果:
選ばれたのは、綾鷹でした。
出力結果:
綾鷹を選んでください。(もしかして:あなたが選んでいるのは「お〜いお茶 新緑」ではありませんか?)
問題なく予測できました。
#おわりに
前述したepoch数の変更だけでなく、活性化関数、損失関数といったモデルの変更、画像データの白色化といった前処理など、まだまだ精度をあげる余地があります。
今回は一旦の投稿となりましたが、そういった機械学習の面白さに気づくとこができました。
今後は画像認識だけでなく、自然言語処理などにも挑戦し、また、kaggleにもチャレンジしようかと思います。
お読みいただき、ありがとうございました。
※記事にミスや改善点等ありましたら、ご指摘いただけると幸いです。
#(2018/06/23)追加検証
epoch数を10から15に増やして精度を検証しました。
対象は②のモデル(画像水増しのみ)と、③のモデル(dropoutを追加)のうち損失率を0.5としたモデルです。
まずは②のモデルを再度学習させます。
学習結果は以下の通り。
Train on 3360 samples, validate on 840 samples
Epoch 1/15
3360/3360 [==============================] - 571s 170ms/step - loss: 0.3126 - acc: 0.8946 - val_loss: 0.2541 - val_acc: 0.9065
Epoch 2/15
3360/3360 [==============================] - 580s 173ms/step - loss: 0.2143 - acc: 0.9204 - val_loss: 0.1797 - val_acc: 0.9306
Epoch 3/15
3360/3360 [==============================] - 561s 167ms/step - loss: 0.1543 - acc: 0.9429 - val_loss: 0.1335 - val_acc: 0.9506
Epoch 4/15
3360/3360 [==============================] - 595s 177ms/step - loss: 0.1162 - acc: 0.9567 - val_loss: 0.1060 - val_acc: 0.9575
Epoch 5/15
3360/3360 [==============================] - 583s 174ms/step - loss: 0.0855 - acc: 0.9686 - val_loss: 0.0832 - val_acc: 0.9683
Epoch 6/15
3360/3360 [==============================] - 559s 166ms/step - loss: 0.0658 - acc: 0.9765 - val_loss: 0.0654 - val_acc: 0.9767
Epoch 7/15
3360/3360 [==============================] - 572s 170ms/step - loss: 0.0481 - acc: 0.9833 - val_loss: 0.0574 - val_acc: 0.9788
Epoch 8/15
3360/3360 [==============================] - 568s 169ms/step - loss: 0.0396 - acc: 0.9862 - val_loss: 0.0402 - val_acc: 0.9862
Epoch 9/15
3360/3360 [==============================] - 563s 168ms/step - loss: 0.0296 - acc: 0.9907 - val_loss: 0.0674 - val_acc: 0.9763
Epoch 10/15
3360/3360 [==============================] - 582s 173ms/step - loss: 0.0242 - acc: 0.9925 - val_loss: 0.0316 - val_acc: 0.9885
Epoch 11/15
3360/3360 [==============================] - 580s 173ms/step - loss: 0.0180 - acc: 0.9941 - val_loss: 0.0447 - val_acc: 0.9837
Epoch 12/15
3360/3360 [==============================] - 586s 174ms/step - loss: 0.0140 - acc: 0.9965 - val_loss: 0.0272 - val_acc: 0.9910
Epoch 13/15
3360/3360 [==============================] - 569s 169ms/step - loss: 0.0127 - acc: 0.9962 - val_loss: 0.0286 - val_acc: 0.9896
Epoch 14/15
3360/3360 [==============================] - 567s 169ms/step - loss: 0.0117 - acc: 0.9973 - val_loss: 0.0198 - val_acc: 0.9927
Epoch 15/15
3360/3360 [==============================] - 555s 165ms/step - loss: 0.0067 - acc: 0.9983 - val_loss: 0.0350 - val_acc: 0.9874
8epoch目からうまく学習が進んでいませんね。
100/100 [==============================] - 5s 51ms/step
loss= 0.384550094604
accuracy= 0.97600001812
正解率は97.6%。0.1%精度が上がりました。
続いて、③の損失率を0.5としたモデルを再度学習させます。
Train on 3360 samples, validate on 840 samples
Epoch 1/15
3360/3360 [==============================] - 577s 172ms/step - loss: 0.3261 - acc: 0.8910 - val_loss: 0.2827 - val_acc: 0.9006
Epoch 2/15
3360/3360 [==============================] - 568s 169ms/step - loss: 0.2429 - acc: 0.9095 - val_loss: 0.2026 - val_acc: 0.9261
Epoch 3/15
3360/3360 [==============================] - 578s 172ms/step - loss: 0.1865 - acc: 0.9318 - val_loss: 0.1787 - val_acc: 0.9342
Epoch 4/15
3360/3360 [==============================] - 564s 168ms/step - loss: 0.1458 - acc: 0.9458 - val_loss: 0.1369 - val_acc: 0.9474
Epoch 5/15
3360/3360 [==============================] - 572s 170ms/step - loss: 0.1184 - acc: 0.9563 - val_loss: 0.1229 - val_acc: 0.9521
Epoch 6/15
3360/3360 [==============================] - 566s 168ms/step - loss: 0.0937 - acc: 0.9662 - val_loss: 0.1051 - val_acc: 0.9642
Epoch 7/15
3360/3360 [==============================] - 559s 166ms/step - loss: 0.0750 - acc: 0.9735 - val_loss: 0.0887 - val_acc: 0.9664
Epoch 8/15
3360/3360 [==============================] - 561s 167ms/step - loss: 0.0629 - acc: 0.9784 - val_loss: 0.0599 - val_acc: 0.9776
Epoch 9/15
3360/3360 [==============================] - 560s 167ms/step - loss: 0.0500 - acc: 0.9827 - val_loss: 0.0586 - val_acc: 0.9771
Epoch 10/15
3360/3360 [==============================] - 573s 171ms/step - loss: 0.0408 - acc: 0.9857 - val_loss: 0.0434 - val_acc: 0.9844
Epoch 11/15
3360/3360 [==============================] - 638s 190ms/step - loss: 0.0362 - acc: 0.9873 - val_loss: 0.0350 - val_acc: 0.9877
Epoch 12/15
3360/3360 [==============================] - 568s 169ms/step - loss: 0.0272 - acc: 0.9910 - val_loss: 0.0392 - val_acc: 0.9865
Epoch 13/15
3360/3360 [==============================] - 561s 167ms/step - loss: 0.0234 - acc: 0.9926 - val_loss: 0.0483 - val_acc: 0.9825
Epoch 14/15
3360/3360 [==============================] - 579s 172ms/step - loss: 0.0220 - acc: 0.9932 - val_loss: 0.0332 - val_acc: 0.9869
Epoch 15/15
3360/3360 [==============================] - 562s 167ms/step - loss: 0.0161 - acc: 0.9945 - val_loss: 0.0262 - val_acc: 0.9901
これでも10epoch目から過学習気味のようです。
100/100 [==============================] - 6s 58ms/step
loss= 0.36878341198
accuracy= 0.97700001955
正解率は97.7%。今までで一番高い精度です。
「dropoutを追加して学習効率が下がっただけで、epoch数を増やせば高い精度が出るのではないか」と推測しましたが、その通りになったのではないかと思います。
あとは過学習を抑えるために損失率を少しずつあげていけば、より高い正解率になると思います。