目录
一、迁移学习简介
迁移学习就是把预先定义好的模型,以及该模型在对应数据集上训练得到的参数迁移到新的模型,用来帮助新模型训练。通过迁移学习我们可以将模型已经学到的参数,分享给新模型从而加快并优化模型的学习效率,从而不用像大多数网络那样从零开始学习。对于小样本学习的也可以减少过拟合或者欠拟合问题。
迁移学习的几种实现方式:
Transfer Learning:冻结预训练模型的全部卷积层,只训练自己定制的全连接层。
Extract Feature Vector:先计算出预训练模型的卷积层对所有训练和测试数据的特征向量,然后抛开预训练模型,只训练自己定制的简配版全连接网络。
Fine-tuning:冻结预训练模型的部分卷积层(通常是靠近输入的多数卷积层,因为这些层保留了大量底层信息)甚至不冻结任何网络层,训练剩下的卷积层(通常是靠近输出的部分卷积层)和全连接层。
二、构建预训练模型
1、调用内置模型
调用tensorflow内置VGG19模型,下载该模型在"imagenet"数据集上预训练权重
net = keras.applications.VGG19(weights='imagenet', include_top=False,
pooling='max')
2、修改模型
冻结卷积层,将全连接层修改为自定义数据集对应分类数。
net.trainable = False
newnet = keras.Sequential([
net,
layers.Dense(5)
])
3、构建模型
newnet.build(input_shape=(4,224,224,3))
newnet.summary()
三、导入数据和预处理
1、设置batch size
根据模型参数量和硬件环境设定batch size大小
batchsz = 128
2、读取训练数据
images, labels, table = load_pokemon('pokemon',mode='train')
db_train = tf.data.Dataset.from_tensor_slices((images, labels))
db_train = db_train.shuffle(1000).map(preprocess).batch(batchsz)
3、读取验证数据
images2, labels2, table = load_pokemon('pokemon',mode='val')
db_val = tf.data.Dataset.from_tensor_slices((images2, labels2))
db_val = db_val.map(preprocess).batch(batchsz)
4、读取测试数据
images3, labels3, table = load_pokemon('pokemon',mode='test')
db_test = tf.data.Dataset.from_tensor_slices((images3, labels3))
db_test = db_test.map(preprocess).batch(batchsz)
5、预处理
def preprocess(x,y):
# x: 图片的路径,y:图片的数字编码
x = tf.io.read_file(x)
x = tf.image.decode_jpeg(x, channels=3)
x = tf.image.resize(x, [244, 244])
x = tf.image.random_flip_up_down(x)
x = tf.image.random_crop(x, [224,224,3])
x = tf.cast(x, dtype=tf.float32) / 255.
x = normalize(x)
y = tf.convert_to_tensor(y)
y = tf.one_hot(y, depth=5)
return x, y
四、模型训练
1、设置early_stopping
为防止过拟合,这里使用early_stopping,当模型在验证集上精度变化在min_delta以内,并且持续次数达到patience以后,模型训练即停止。
early_stopping = EarlyStopping(
monitor='val_accuracy',
min_delta=0.001,
patience=5
)
2、模型编译
设置优化器,损失函数和精度衡量标准
newnet.compile(optimizer=optimizers.Adam(lr=1e-3),
loss=losses.CategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
3、模型设置
设置训练集,验证集,验证频率,迭代次数以及回调函数
newnet.fit(db_train, validation_data=db_val, validation_freq=1, epochs=20,
callbacks=[early_stopping])
4、模型评估
训练结束后,使用evaluate函数进行模型评估,了解模型最终精度情况。
newnet.evaluate(db_test)
5、保存训练权重
newnet.save_weights('weights.ckpt')
五、模型预测
1、构建预测模型
net = keras.applications.VGG19(weights='imagenet', include_top=False,
pooling='max')
net.trainable = False
model= keras.Sequential([
net,
layers.Dense(5)
])
model.build(input_shape=(4,224,224,3))
2、导入权重
model.load_weights('weights.ckpt')
3、预测
logits = newnet.predict(x)
prob = tf.nn.softmax(logits, axis=1)
print(prob)
max_prob_index = np.argmax(prob, axis=-1)[0]
prob = prob.numpy()
max_prob = prob[0][max_prob_index]
print(max_prob)
max_index = np.argmax(logits, axis=-1)[0]
name = ['妙蛙种子', '小火龙', '超梦', '皮卡丘', '杰尼龟']
print(name[max_index])
测试图像:
预测结果:
tf.Tensor([[0.78470963 0.09179451 0.03650109 0.01834733 0.06864741]], shape=(1, 5), dtype=float32)
0.78470963
妙蛙种子
4、对比分析
使用同样测试图像在没有进行迁移学习训练的模型上进行测试,输出结果:
tf.Tensor([[0.46965462 0.0470721 0.20003504 0.11915307 0.16408516]], shape=(1, 5), dtype=float32)
0.46965462
妙蛙种子
从结果上看,两个模型都能准确预测,但输出的分类概率(迁移学习0.7847,非迁移学习0.4696),两者存在明显差别,可以看出使用迁移学习能够达到更好的拟合效果。