PythonMania

普段はロボットとAIを組み合わせて色々作ってます。Python関係以外も色々投稿していくと思います。

【Python】画像認識 - kerasで InceptionResNetV2をfine-tuningしてみる 【DeepLearning】

f:id:mizuhiki0111:20190430180019p:plain


今回は InceptionResNetV2 モデルをfine-tuningしてみたいと思います。




基本的な流れは以前紹介したVGG16やXceptionと同様ですが、

InceptionResNetV2の場合は学習させる画像のサイズを139以上に設定しないとエラーが起きます。

keras.io





また固定する層の数も変更が必要なので、ここら辺は調整してみてください。





以下コードです。


#必要なライブラリの読み込み

from sklearn.model_selection import train_test_split
import numpy as np
from PIL import Image
import os
from glob import glob
from sklearn.preprocessing import LabelEncoder
import cv2
from keras.utils import np_utils
from matplotlib import pyplot as plt
import pandas as pd



#画像のサイズ指定
ScaleTo = 150
seed = 7
n_categories = 12

#トレーニングデータの読み込み
data_dir ="../input/train"
path = "../input/train/*/*.png"
files = glob(path)

trainImg = []
trainLabel = []
j = 1
num = len(files)

#画像データをリストに格納
for img in files:
    print(str(j) + "/" + str(num) , end="\r")
    trainImg.append(cv2.resize(cv2.imread(img) ,(ScaleTo,ScaleTo)))
    #trainLabel.append(img.split("/")[-2])
    j += 1


#ラベルをリストに格納
for dir in os.listdir(data_dir):
    if dir == ".DS_Store":
        continue
    dir1 = data_dir + "/" + dir
    label = dir

    for file in os.listdir(dir1):
        if file != "Thumbs.db":

            trainLabel.append(label)


# kerasに渡すためにnumpy配列に変換。
image_list = np.asarray(trainImg)
label_list = pd.DataFrame(trainLabel)


clearTrainImg = []
examples = [];getEx = True

for img in image_list:
    #ぼかしを入れてノイズを除去
    blurImg = cv2.GaussianBlur(img ,(5,5),0)
    #RGBからHSVに変換
    hsvImg = cv2.cvtColor(blurImg , cv2.COLOR_BGR2HSV)
    #マスクを作成
    lower_green = (25,40,50)
    upper_green = (75,255,255)
    mask = cv2.inRange(hsvImg , lower_green ,upper_green)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11))
    mask = cv2.morphologyEx(mask , cv2.MORPH_CLOSE,kernel)

    #ブールマスクの作成
    bMask = mask > 0

    #マスクの適用
    #空のイメージの作成
    clear = np.zeros_like(img , np.uint8)
    #オリジナル画像にブールマスクを適用
    clear[bMask] = img[bMask]

    clearTrainImg.append(clear)


for i in range(8):
    plt.subplot(2, 4, i + 1)
    plt.imshow(clearTrainImg[i])


clearTrainImg = np.asarray(clearTrainImg)
clearTrainImg.shape
# クラスの形式を変換
le = LabelEncoder()
le = le.fit(label_list)
label_list = le.transform(label_list)
label_list
label_list = np_utils.to_categorical(label_list)
label_list

X_train, X_test, y_train, y_test = train_test_split(clearTrainImg, label_list, test_size=0.33, random_state=0)



from keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
        rotation_range=180,  # randomly rotate images in the range
        zoom_range = 0.1, # Randomly zoom image
        width_shift_range=0.1,  # randomly shift images horizontally
        height_shift_range=0.1,  # randomly shift images vertically
        horizontal_flip=True,  # randomly flip images horizontally
        vertical_flip=True  # randomly flip images vertically
    )
datagen.fit(X_train)











#モデル作成・学習
from keras.applications.inception_resnet_v2 import InceptionResNetV2
from keras.models import Model
import tensorflow as tf
import keras
from tensorflow import keras
from keras.layers import Conv2D, MaxPooling2D,Input
from keras.layers import Dense, Dropout, Flatten, Activation,GlobalAveragePooling2D,Input
from keras.models import Sequential
from keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint
from keras.optimizers import Adam
from keras import optimizers

nb_classes = 12

# InceptionResNetV2のロード。FC層は不要なので include_top=False
input_tensor = Input(shape=(ScaleTo, ScaleTo,3))
inception_v3 = InceptionResNetV2(include_top=False, weights='imagenet', input_tensor=input_tensor)

# FC層の作成
top_model = Sequential()
top_model.add(Flatten(input_shape=inception_v3.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(nb_classes, activation='softmax'))

#  InceptionResNetV2とFC層を結合してモデルを作成(完成図が上の図)
inception_v3_model = Model(input=inception_v3.input, output=top_model(inception_v3.output))

# InceptionResNetV2の一部の重みを固定(frozen)
for layer in inception_v3_model.layers[:775]:
    layer.trainable = False

# 多クラス分類を指定
inception_v3_model.compile(loss='categorical_crossentropy',
          optimizer=optimizers.SGD(lr=1e-3, momentum=0.9),
          metrics=['accuracy'])
inception_v3_model.summary()


#モデルの層数を確認
print("{}層".format(len(inception_v3_model.layers)))



#学習の実行
hist = inception_v3_model.fit_generator(datagen.flow(X_train, y_train, batch_size=75),
                        epochs=35, validation_data=(X_test, y_test),
                        steps_per_epoch=X_train.shape[0])


#モデルの評価
print(inception_v3_model.evaluate(X_train, y_train)) #トレーニングの精度
print(inception_v3_model.evaluate(X_test, y_test))  #テスト精度


#パラメータの保存
model.save_weights('../content/weights.h5')