アプリ開発
「このブログはAidemy Premiumのカリキュラムの一環で、受講修了条件を満たすために公開しています。」
動作環境
・Google Colab
機械学習の手法
・CNN(vgg16転移学習)
テーマ:epoch数の調整とDropoutの有効性確認
0.乱数シードの固定
再現性の確保として以下のコードにて乱数を固定しています
random.seed(0)
tensorflow.random.set_seed(0)
np.random.seed(0)
1.元となるコード-cifar10を用いた飛行機と鳥の2クラス分類-
#from IPython.core.debugger import Pdb; Pdb().set_trace()
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.layers import Dense, Dropout, Flatten, Input
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras import optimizers
from tensorflow.keras.datasets import cifar10
# ----乱数固定------------------------------------------------------------------
import random
import tensorflow
random.seed(0)
tensorflow.random.set_seed(0)
np.random.seed(0)
# ----乱数固定------------------------------------------------------------------
# ----画像整理------------------------------------------------------------------
# cifar10読込
(X_train,y_train),(X_test,y_test) = cifar10.load_data()
# 256色(0~255)画像データの範囲を0~1に換算
X_train, X_test = X_train / 255., X_test / 255.
# 学習・検証に使う枚数を指定
train_num = 1000
test_num = 200
# 画像判定する枚数を指定
chk_num = 5
#cifar10から飛行機 (インデックス:0)と鳥(インデックス:2)を取り出し、1000枚を学習、200枚を検証に使う
train_ind = np.where((y_train == 0) | (y_train == 2))[0]
train_ind = train_ind[:train_num]
X_train, y_train = X_train[train_ind], y_train[train_ind]
test_ind = np.where((y_test == 0) | (y_test == 2))[0]
chk_ind = test_ind[:test_num+chk_num]#test_indを更新する前に画像判定用の処理を行う
test_ind = test_ind[:test_num]
X_chk, y_chk = X_test[chk_ind], y_test[chk_ind]#X_test, y_testを更新する前に画像判定用の処理を行う
X_test, y_test = X_test[test_ind], y_test[test_ind]
# 1-hotベクトル化
y_train = to_categorical(y_train)[:,[0,2]]
y_test = to_categorical(y_test)[:,[0,2]]
y_chk = to_categorical(y_chk)[:,[0,2]]
# ----画像整理------------------------------------------------------------------
# ----モデル作成----------------------------------------------------------------
# vgg16のインスタンスの生成(画像サイズ32*32,カラー画像)
input_tensor = Input(shape=(32, 32, 3))
vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
# モデル
top_model = Sequential()
top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dense(2, activation='softmax'))
# モデルの連結
model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))
# vgg16の重みの固定
for layer in model.layers[:19]:
layer.trainable = False
# 損失関数には交差エントロピーを採用
model.compile(loss='categorical_crossentropy',optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),metrics=['accuracy'])
# 学習実施
history = model.fit(X_train, y_train, batch_size=100, epochs=100, verbose=0, validation_data=(X_test, y_test))
#acc , val_accのプロット
plt.plot(history.history["accuracy"], label="acc", ls="-", marker="o")
plt.plot(history.history["val_accuracy"], label="val_acc", ls="-", marker="x")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()
#loss , val_lossのプロット
plt.plot(history.history["loss"], label="loss", ls="-", marker="o")
plt.plot(history.history["val_loss"], label="val_loss", ls="-", marker="x")
plt.ylabel("loss")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()
# 精度の評価
scores = model.evaluate(X_test, y_test, verbose=1)
print('Test loss:', scores[0])
print('Test accuracy:', scores[1])
# ----モデル作成----------------------------------------------------------------
# ----画像判定------------------------------------------------------------------
# 画像を一枚受け取り、飛行機か鳥かを判定して返す関数
def pred_cifar(img):
# 念のため32*32以外の画像にも対応させる
img = cv2.resize(img,(32,32))
# 判定実施
pred = np.argmax(model.predict(img.reshape(1,32,32,3)))
if pred == 0:
ans = "airplane"
else:
ans = "bird"
return ans
# 検証データの次の画像を、渡す画像の1枚目のインデックスにする
index = test_num
for i in range(chk_num):
# 判定する画像の表示
img = X_chk[index+i]
plt.imshow(img)
plt.show()
# 正解ラベルの表示
if np.all(y_chk[index+i] == [1., 0.]):
print("画像の種類:airplane")
else:
print("画像の種類:bird")
# pred_cifar関数に画像を渡して判定
print(pred_cifar(img))
# ----画像判定------------------------------------------------------------------
実行結果
7/7 [==============================] - 0s 10ms/step - loss: 0.4586 - accuracy: 0.8000
Test loss: 0.45864754915237427
Test accuracy: 0.800000011920929
画像の種類:airplane
1/1 [==============================] - 1s 526ms/step
bird
画像の種類:bird
1/1 [==============================] - 0s 30ms/step
bird
画像の種類:airplane
1/1 [==============================] - 0s 25ms/step
airplane
画像の種類:airplane
1/1 [==============================] - 0s 22ms/step
bird
画像の種類:airplane
1/1 [==============================] - 0s 19ms/step
airplane
2.Dropoutの導入
Dropout層のコードは以下となります
top_model.add(Dropout(rate =0.5))
導入したコードは以下となります
#from IPython.core.debugger import Pdb; Pdb().set_trace()
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.layers import Dense, Dropout, Flatten, Input
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.models import Model, Sequential
from tensorflow.keras import optimizers
from tensorflow.keras.datasets import cifar10
# ----乱数固定------------------------------------------------------------------
import random
import tensorflow
random.seed(0)
tensorflow.random.set_seed(0)
np.random.seed(0)
# ----乱数固定------------------------------------------------------------------
# ----画像整理------------------------------------------------------------------
# cifar10読込
(X_train,y_train),(X_test,y_test) = cifar10.load_data()
# 256色(0~255)画像データの範囲を0~1に換算
X_train, X_test = X_train / 255., X_test / 255.
# 学習・検証に使う枚数を指定
train_num = 1000
test_num = 200
# 画像判定する枚数を指定
chk_num = 5
#cifar10から飛行機 (インデックス:0)と鳥(インデックス:2)を取り出し、1000枚を学習、200枚を検証に使う
train_ind = np.where((y_train == 0) | (y_train == 2))[0]
train_ind = train_ind[:train_num]
X_train, y_train = X_train[train_ind], y_train[train_ind]
test_ind = np.where((y_test == 0) | (y_test == 2))[0]
chk_ind = test_ind[:test_num+chk_num]#test_indを更新する前に画像判定用の処理を行う
test_ind = test_ind[:test_num]
X_chk, y_chk = X_test[chk_ind], y_test[chk_ind]#X_test, y_testを更新する前に画像判定用の処理を行う
X_test, y_test = X_test[test_ind], y_test[test_ind]
# 1-hotベクトル化
y_train = to_categorical(y_train)[:,[0,2]]
y_test = to_categorical(y_test)[:,[0,2]]
y_chk = to_categorical(y_chk)[:,[0,2]]
# ----画像整理------------------------------------------------------------------
# ----モデル作成----------------------------------------------------------------
# vgg16のインスタンスの生成(画像サイズ32*32,カラー画像)
input_tensor = Input(shape=(32, 32, 3))
vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
# モデル
top_model = Sequential()
top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(rate =0.5))
top_model.add(Dense(2, activation='softmax'))
# モデルの連結
model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))
# vgg16の重みの固定
for layer in model.layers[:19]:
layer.trainable = False
# 損失関数には交差エントロピーを採用
model.compile(loss='categorical_crossentropy',optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),metrics=['accuracy'])
# 学習実施
history = model.fit(X_train, y_train, batch_size=100, epochs=100, verbose=0, validation_data=(X_test, y_test))
#acc , val_accのプロット
plt.plot(history.history["accuracy"], label="acc", ls="-", marker="o")
plt.plot(history.history["val_accuracy"], label="val_acc", ls="-", marker="x")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()
#loss , val_lossのプロット
plt.plot(history.history["loss"], label="loss", ls="-", marker="o")
plt.plot(history.history["val_loss"], label="val_loss", ls="-", marker="x")
plt.ylabel("loss")
plt.xlabel("epoch")
plt.legend(loc="best")
plt.show()
# 精度の評価
scores = model.evaluate(X_test, y_test, verbose=1)
print('Test loss:', scores[0])
print('Test accuracy:', scores[1])
# ----モデル作成----------------------------------------------------------------
# ----画像判定------------------------------------------------------------------
# 画像を一枚受け取り、飛行機か鳥かを判定して返す関数
def pred_cifar(img):
# 念のため32*32以外の画像にも対応させる
img = cv2.resize(img,(32,32))
# 判定実施
pred = np.argmax(model.predict(img.reshape(1,32,32,3)))
if pred == 0:
ans = "airplane"
else:
ans = "bird"
return ans
# 検証データの次の画像を、渡す画像の1枚目のインデックスにする
index = test_num
for i in range(chk_num):
# 判定する画像の表示
img = X_chk[index+i]
plt.imshow(img)
plt.show()
# 正解ラベルの表示
if np.all(y_chk[index+i] == [1., 0.]):
print("画像の種類:airplane")
else:
print("画像の種類:bird")
# pred_cifar関数に画像を渡して判定
print(pred_cifar(img))
# ----画像判定------------------------------------------------------------------
実行結果
7/7 [==============================] - 0s 15ms/step - loss: 0.4719 - accuracy: 0.7900
Test loss: 0.471892386674881
Test accuracy: 0.7900000214576721
画像の種類:airplane
1/1 [==============================] - 0s 144ms/step
bird
画像の種類:bird
1/1 [==============================] - 0s 19ms/step
bird
画像の種類:airplane
1/1 [==============================] - 0s 18ms/step
airplane
画像の種類:airplane
1/1 [==============================] - 0s 21ms/step
bird
画像の種類:airplane
1/1 [==============================] - 0s 19ms/step
airplane
Dropout導入前 Test loss: 0.45864754915237427
Test accuracy: 0.800000011920929
Dropout導入後 Test loss: 0.471892386674881
Test accuracy: 0.7900000214576721
epoch数100の場合、Dropoutを導入するとかえって性能が悪化してしまいました。
epoch数を変更することでDropoutに有効性が見られるか調査を行います。
3.epoch数の調整とDropoutの有効性確認
作成中
結論
作成中
この記事が気に入ったらサポートをしてみませんか?