## 迁移学习简述
迁移学习 (Transfer Learning) 是一种机器学习方法,就是把为任务 A 开发的已经训练好的模型参数作为初始点,重新迁移使用在为任务 B 开发模型中,来帮助新模型的训练。
TensorFlow Hub 是一个用于促进机器学习模型中可复用部分再次进行探索与发布的库,主要将预训练过的 TensorFlow 模型片段再次利用到新的任务上。迁移学习的经典做法,即首先使用 transfer learning 对数据集进行训练,经过一定的 Epoch 批次之后,再改用 fine tuning 的方法,接着刚才训练过的模型即训练权重集继续进行训练,可以得到较好的效果。
EfficientNet 是 Google 公司开发的全新的神经网络模型。原码看我
## 利用 Efficientnet 进行猫狗识别实战
- 数据准备
使用 Kaggle 比赛猫狗大战的数据集 Kaggle Cats and Dogs Dataset。点击下载
猫狗图片在文件夹 PetImages 中,共有图片 25000 张,为了节约时间,我们选取每类 900 张图片用于训练,100 张用于测试。 - 训练数据
首先需要导入 Efficientnet:import efficientnet.keras as efk(安装:pip install efficientnet)
训练参数设置:
batch_size = 30
width = 300
height = 300
epochs = 10
NUM_TRAIN = 900
NUM_TEST = 100
dropout_rate = 0.2
input_shape = (height, width, 3)
图像尺寸根据选择模型相应变化:
本次实验设置训练轮数为 10,共 900 张图片作为训练数据,100 张图片作为测试数据。
- 使用 Efficientnet 迁移学习:
base_model = efk.EfficientNetB3(weights='imagenet', include_top=False, input_shape=input_shape)
top_model = tf.keras.models.Sequential()
model=base_model
top_model.add(tf.keras.layers.GlobalMaxPooling2D(name="gap"))
if dropout_rate > 0:
top_model.add(tf.keras.layers.Dropout(dropout_rate, name="dropout_out"))
top_model.add(tf.keras.layers.Dense(2, activation='softmax', name="fc_out"))
model = tf.keras.models.Model(inputs = model.input,outputs = top_model(model.output))
base_model.trainable = False
model.compile(loss='categorical_crossentropy', optimizer=tf.keras.optimizers.RMSprop(lr=2e-5),
metrics=['acc'])
使用 model.summary() 查看网络模型参数:
- 训练模型
训练网络模型,并将训练好后的网络模型文件保存,函数 fit 和 fit_generator 均可以使用,此处使用 fit。
history_tl = model.fit(
train_data,
train_label,
steps_per_epoch= NUM_TRAIN//batch_size,
epochs=epochs,
validation_data=(valid_data,valid_label),
validation_steps= NUM_TEST//batch_size,
shuffle=True,
verbose=1)
- 结果可视化
输出 Training 和 Validation 的 accuracy 及 loss 图:
def plot_training(history):
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_x = range(len(acc))
plt.plot(epochs_x, acc, 'bo', label='Training acc')
plt.plot(epochs_x, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs_x, loss, 'bo', label='Training loss')
plt.plot(epochs_x, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
- 训练结果
对数据集进行训练,总共训练 10 轮。训练数据共 900 张图片,其中猫和狗各 450 张,测试数据共 100 张图片,其中猫和狗各 50 张。以下是 EfficientnetB0 和 EfficientnetB1 的训练结果,大家可以看看 3~7 的结果,此处不再展示。
使用 EfficientnetB0 训练结果:
第一轮结束准确率到达 74%, 第二轮达到 82%,第 10 轮达到 100%。
Training 和 Validation 的 accuracy 及 loss 图:)
使用 EfficientnetB1 训练结果:
第一轮结束准确率到达 20%, 第二轮达到 27%,第 10 轮达到 94%。
Training 和 Validation 的 accuracy 及 loss 图:
- 模型载入
训练中利用 save 函数将模型保存为 h5 文件:
再次使用时不需要重新训练数据,导入 load_model 函数,然后在对应路径下使用函数导出保存的模型。
from tensorflow.keras.models import load_model
model = load_model('./transdata/my_model.h5')
使用该模型预测分类结果
def predict_image(img_path):
img = Image.open(img_path)
img = img.resize((height, width))
x=np.array(img)
x = x.reshape((1,) + x.shape)
result = model.predict([x])[0][0]
if result > 0.5:
animal = "cat"
else:
animal = "dog"
result = 1 - result
return animal, result
输入图像路径,使用 model.predict 函数就可以预测对应类别,如果需要批量预测的话可以自己修改代码实现。
全部代码
import tensorflow as tf
import efficientnet.tfkeras as efk
from keras.utils import to_categorical
import os
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
batch_size = 30
width = 300
height = 300
epochs = 10
NUM_TRAIN = 900
NUM_TEST = 100
dropout_rate = 0.2
input_shape = (height, width, 3)
path_cat='./transdata/PetImages/Cat/'
path_dog='./transdata/PetImages/Dog/'
def load_data():
data=np.empty((1000,width,height,3),dtype="float32")
label=np.empty((1000,))
imgcat=os.listdir(path_cat)
imgdog=os.listdir(path_dog)
cnt=0
for i in range(0,500):
img=Image.open(path_cat+str(i)+".jpg")
arr=np.array(img)
arr.resize((width,height,3))
data[cnt,:,:,:]=arr
label[cnt]=0
cnt+=1
img=Image.open(path_dog+str(i)+".jpg")
arr=np.array(img)
arr.resize((width,height,3))
data[cnt,:,:,:]=arr
label[cnt]=1
cnt+=1
return data,label
data,label=load_data()
label = to_categorical(label)
train_data=data[:900]
train_label=label[:900]
valid_data=data[900:1000]
valid_label=label[900:1000]
train_label = to_categorical(train_label)
valid_label = to_categorical(valid_label)
base_model = efk.EfficientNetB3(weights='imagenet', include_top=False, input_shape=input_shape)
top_model = tf.keras.models.Sequential()
model=base_model
top_model.add(tf.keras.layers.GlobalMaxPooling2D(name="gap"))
if dropout_rate > 0:
top_model.add(tf.keras.layers.Dropout(dropout_rate, name="dropout_out"))
top_model.add(tf.keras.layers.Dense(2, activation='softmax', name="fc_out"))
model = tf.keras.models.Model(inputs = model.input,outputs = top_model(model.output))
base_model.trainable = False
model.compile(loss='categorical_crossentropy', optimizer=tf.keras.optimizers.RMSprop(lr=2e-5),
metrics=['acc'])
history_tl = model.fit(
train_data,
train_label,
steps_per_epoch= NUM_TRAIN//batch_size,
epochs=epochs,
validation_data=(valid_data,valid_label),
validation_steps= NUM_TEST//batch_size,
shuffle=True,
verbose=1)
model.save('./transdata/my_model3.h5')
def plot_training(history):
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_x = range(len(acc))
plt.plot(epochs_x, acc, 'bo', label='Training acc')
plt.plot(epochs_x, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs_x, loss, 'bo', label='Training loss')
plt.plot(epochs_x, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
plot_training(history_tl)
因为本人也是刚开始学习,使用难免有理解不到位的地方,欢迎各位大佬指正,也欢迎大家交流讨论。
部分内容参考此博客。
https://blog.csdn.net/qq_47043529/article/details/105871957