[keras][VGG] Transfer learning application

Environment configuration

Python 3.6
scikit-image 0.17.2
numpy 1.19.0
opencv-python 3.4.2.16
opencv-contrib-python 3.4.2.16

Program progress

Read training data

train_datagen = ImageDataGenerator(rescale=1./255,
                                  rotation_range = 45,
                                  width_shift_range = 0.2,
                                  height_shift_range = 0.2,
                                  shear_range = 0.2,
                                  zoom_range = 0.2,
                                  horizontal_flip=True)

train_gen = train_datagen.flow_from_directory("data/train",
                                             target_size = (240, 240),
                                             batch_size = 8,
                                             class_mode="categorical")

ImageDataGenerator

Data enhancement is possible;
reference link: Keras ImageDataGenerator

  • rescale: normalize the value from 0 to 255 to a value between 0 and 1;
  • rotation_range: Integer, the random rotation angle of the picture, the value is [0, 180], I think the default is generally counterclockwise;
  • width_shift_range: floating-point number, a certain ratio, the range of random horizontal shift of the picture, the value is [0, 1];
  • height_shift_range: floating-point number, a certain ratio, the amplitude of the random vertical translation of the picture, the value is [0, 1];
  • shear_range: Floating point number, indicating the degree of (counterclockwise) shear transformation;
  • zoom_range: floating point number, indicating the degree of random zooming, or a list of the form [lower, upper];
  • horizontal_flip: Boolean value, random horizontal flip;

Automatically classify pictures according to folders:
Insert picture description here

flow_from_directory

It can be numbered according to folders and automatically classified;
Insert picture description here
view the training data in a batch, there are 8 pictures in a batch, temp[0] is the picture, temp[1] is the label; the
Insert picture description here
Insert picture description here
Insert picture description here
Insert picture description here
data range is 0 ~ 1: one-
Insert picture description here
hot encoding completed:
Insert picture description here
Insert picture description here

Load pre-trained models online

VGG = keras.applications.vgg16.VGG16(weights="imagenet", include_top=False, input_shape=[240, 240, 3])

Insert picture description here
Or load locally accessed files:

from keras.models import load_model
VGG = load_model("model/VGG_Pretrained.h5")

View model information:
Insert picture description here
Insert picture description here

Add a classifier at the end of the model

from keras.layers import Dense, Flatten

x = VGG.layers[-1].output
x = Flatten()(x)
x = Dense(64, activation="sigmoid")(x)
predictions=Dense(5, activation="softmax")(x)

model = keras.Model(inputs=VGG.inputs, outputs=predictions)

Add a classifier behind the model. Note that the number of neurons in the output layer must be the same as the label. Flatten must be added, otherwise the dense layer cannot accept matrix input; in
simple terms, two layers of neurons are added. The more troublesome is the original Connect the models;

for layer in model.layers[:-2]:
    layer.trainable=False

Only train the last two layers;
Insert picture description here

Define optimizer

adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8)
model.compile(loss="categorical_crossentropy", optimizer=adam, metrics=["accuracy"])

Training model

model.fit_generator(train_gen, steps_per_epoch=12, epochs=10)

Insert picture description here
Save the trained model:
Insert picture description here

Load test data

import skimage.io as io
import skimage.transform as transform

img = io.imread("data/test/3.jpg")
img = img/255
img = transform.resize(img, output_shape=[240, 240])
print(img.shape)
plt.imshow(img)

Insert picture description here
start testing:

indices = {'紫葡萄': 0, '红苹果': 1, '绿葡萄': 2, '黄苹果': 3, '黄香蕉': 4}
output = model.predict(img.reshape([1, 240, 240, 3]))
print(output)

Insert picture description here

Output result

output_r has two numbers, which respectively indicate how many rows and how many columns the prediction result is:
Insert picture description here

Full source code

No redundant output information

# 完整版
import numpy as np
import keras
import matplotlib.pyplot as plt

from keras.models import Sequential
from keras.optimizers import Adam
from keras.utils.np_utils import to_categorical

from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(rescale=1./255,
                                  rotation_range = 45,
                                  width_shift_range = 0.2,
                                  height_shift_range = 0.2,
                                  shear_range = 0.2,
                                  zoom_range = 0.2,
                                  horizontal_flip=True)

train_gen = train_datagen.flow_from_directory("data/train",
                                             target_size = (240, 240),
                                             batch_size = 8,
                                             class_mode="categorical")
# 从网上下载预先存取好的模型
VGG = keras.applications.vgg16.VGG16(weights="imagenet", include_top=False, input_shape=[240, 240, 3])

# 或者直接从本地导入
# from keras.models import load_model
# VGG = load_model("model/VGG_Pretrained.h5")

# 在原模型末尾加入分类器
from keras.layers import Dense, Flatten

x = VGG.layers[-1].output
x = Flatten()(x)
x = Dense(64, activation="sigmoid")(x)
predictions=Dense(5, activation="softmax")(x)

model = keras.Model(inputs=VGG.inputs, outputs=predictions)

# 设置为只需要训练最后新加入的两层神经元
for layer in model.layers[:-2]:
    layer.trainable=False

# 定义优化器
adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8)
model.compile(loss="categorical_crossentropy", optimizer=adam, metrics=["accuracy"])

# 训练模型
model.fit_generator(train_gen, steps_per_epoch=12, epochs=10)

# 载入测试数据
import skimage.io as io
import skimage.transform as transform

img = io.imread("data/test/3.jpg")
img = img/255
img = transform.resize(img, output_shape=[240, 240])
# print(img.shape) # 查看图片信息
# plt.imshow(img)

# 结果展示
indices = {'紫葡萄': 0, '红苹果': 1, '绿葡萄': 2, '黄苹果': 3, '黄香蕉': 4}
output = model.predict(img.reshape([1, 240, 240, 3]))
# print(output)

# 使得结果更加清晰
output_r = np.where(output==np.max(output))
print(np.max(output_r[1])) # 表示预测结果的列编号

Guess you like

Origin blog.csdn.net/weixin_44092088/article/details/113061624