データには、kaggleからダウンロードした果物の画像を用います。https://www.kaggle.com/moltean/fruits kerasはGoogleで開発され、GoogleのTensorFlowをバックエンドで用いるAPIラッパーで、コーディングが簡単になります。https://ymgsapo.com/2019/08/22/fruits-deep-learning/ Anacondaの場合、conda install numpy、conda install matplotlib、conda install pandas、conda install keras-gpu等でインストールしてください。condaでインストールできない場合は、pip install ternsorflow kerasのようにpipでインストールしてください。
from keras import layers
from keras import models
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
#from keras.layers import Activation, Dense
#from keras.utils.np_utils import to_categorical
import numpy as np
import matplotlib.pyplot as plt
import os
1.データを用意する
train_path = './image_fruits/fruits-360/Training/' # 訓練画像の存在するローカルディレクトリ
test_path = './image_fruits/fruits-360/Test/' # 試験画像の存在するローカルディレクトリ
TARGET = ["Apple Golden 1",
"Avocado",
# "Banana",
# "Blueberry",
"Cherry 1",
"Clementine",
"Grape Pink",
# "Kaki",
"Kiwi",
# "Lemon",
# "Mango",
"Nectarine",
# "Onion Red",
"Orange",
"Peach",
"Strawberry",
"Tamarillo"]
# "Tomato 1"]
train_images = []
test_images = []
for i in TARGET:
subdir = '{}'.format(i)
# print("train images:{}".format(len(os.listdir(train_path + "/" + subdir +"/"))))
# print("test images:{}".format(len(os.listdir(test_path + "/" + subdir + "/"))))
train_images.append(len(os.listdir(train_path + "/" + subdir +"/")))
test_images.append(len(os.listdir(test_path + "/" + subdir + "/")))
print("train images:", train_images )
print("test images: ", test_images )
IMG_WIDTH = 40 # 統一する画像の横幅
IMG_HEIGHT = 40 # 統一する画像の縦幅
CHANNELS = 3
TRAIN_BATCH_SIZE = 48 # ミニバッチ学習に使われるバッチサイズ、[重要]データの枚数を割り切れるように
VALID_BATCH_SIZE = 50 # ミニバッチ学習に使われるバッチサイズ、[重要]データの枚数を割り切れるように
train_datagen = ImageDataGenerator(rescale = 1./255) # 画素数のリスケーリング係数
train_generator = train_datagen.flow_from_directory(
train_path,
target_size = (IMG_WIDTH, IMG_HEIGHT), #自動的に指定サイズにリサイズ default256,256
batch_size = TRAIN_BATCH_SIZE, # 一度に処理する画像の枚数
classes = TARGET, # サブディレクトリリスト
class_mode = "categorical" #複数クラスの分類、カテゴリごとに正解フラグ、binary 二値のラベル
)
validation_datagen = ImageDataGenerator(rescale = 1./255)
validation_generator = validation_datagen.flow_from_directory(
test_path,
target_size = (IMG_WIDTH, IMG_HEIGHT),
batch_size = VALID_BATCH_SIZE,
classes = TARGET,
class_mode = "categorical"
)
2.ニューラルネットワークの作成
model = models.Sequential()
model.add(layers.Conv2D(32, # 2次元の畳み込みレイヤー、出力フィルター数32
(3, 3), # カーネルサイズ 畳み込みウインドウの幅と高さ
activation = "relu", # 活性化関数 ランプ関数、正規化線形関数
input_shape = (IMG_WIDTH, IMG_HEIGHT, CHANNELS)))
# 空間データのマックスプーリング演算
model.add(layers.MaxPooling2D((2, 2))) # ダウンスケール係数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),
padding = "SAME")) # valid or same
model.add(layers.Flatten()) # 入力を平滑化する
model.add(layers.Dropout(0.5)) # 過学習防止
model.add(layers.Dense(512, # 通常の全結合NN
activation = "relu"))
model.add(layers.Dense(len(TARGET),
activation = "sigmoid"))
model.summary()
3.学習
#model.compile(loss = keras.losses.categorical_crossentropy,
model.compile(loss = "categorical_crossentropy",
# optimizer = keras.optimizers.RMSprop(lr = 1e-4, decay = 1e-6),
optimizer = optimizers.RMSprop(lr = 1e-4, decay = 1e-6),
metrics = ['accuracy'])
STEP_SIZE_TRAIN = train_generator.n//train_generator.batch_size # 切り捨て除算
STEP_SIZE_VALID = validation_generator.n//validation_generator.batch_size
print("train_generator.n:", train_generator.n)
print("valid_generator.n:", validation_generator.n)
print("STEP_SIZE_TRAIN:", STEP_SIZE_TRAIN)
print("STEP_SIZE_VALID:", STEP_SIZE_VALID)
history = model.fit_generator(train_generator,
steps_per_epoch = STEP_SIZE_TRAIN,
epochs = 20,
validation_data = validation_generator,
validation_steps = STEP_SIZE_VALID)
4.可視化
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)
plt.figure(figsize=(8, 8))
#plt.style.use('fivethirtyeight')
plt.subplot(211)
plt.plot(epochs, acc, "bo", label = "Training Acc")
plt.plot(epochs, val_acc, "r", label = "Validation Acc")
plt.title("model accuracy")
plt.legend()
plt.subplot(212)
plt.plot(epochs, loss, "ko", label = "Training Loss")
plt.plot(epochs, val_loss, "g", label = "Validation Loss")
plt.legend()
plt.title("model loss")
plt.xlabel("epochs")
plt.show()