tensorflow学习024——迁移学习代码实现
C:\Users\admin.keras,在电脑的这个文件夹中存在两个子文件夹,datasets是数据集,models是模型,我们可以将常见使内置用的数据集和模型参数放在两个文件夹中,可以不用运行下载了。
微调是冻结模型库的底部的卷积层,共同训练新添加的分类器层和顶部部分卷积层。底部的卷积层是一些通用的特征,所以一般不需要调整。微调允许我们“微调”基础模型中的高阶特征表示,以使它们与特定的任务更相关。
只有分类器已经训练好了,才能微调卷积基的顶部卷积层,斗则刚开始的训练误差很大,微调之前这些卷积层学到的表示会被破坏掉。
微调步骤:
1)在与训练卷积基上添加自定义层
2)冻结卷积基所有层
3)训练添加的分类层
4)解冻卷积基的一部分高层
5)联合训练解冻的卷积层和添加的自定义层
数据链接:https://pan.baidu.com/s/1-nLlW6Nng1pAvrxwEfHttA
提取码:vt8p
点击查看代码
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import glob
import os
train_image_path = glob.glob(r'E:\WORK\tensorflow\dataset\dc_2000\train\*\*.jpg')
print(len(train_image_path))
print(train_image_path[:5])
train_image_label = [int(p.split("\\")[-2] == 'cat') for p in train_image_path]
def load_preprosess_image(path,label):
image = tf.io.read_file(path)
image = tf.image.decode_jpeg(image,channels=3)
image = tf.image.resize(image,[256,256])
image = tf.cast(image,tf.float32)
image = image / 255
return image,label
train_image_ds = tf.data.Dataset.from_tensor_slices((train_image_path,train_image_label))
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_image_ds = train_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE)
BATCH_SZIE = 32
train_count = len(train_image_path)
train_image_ds = train_image_ds.shuffle(train_count).repeat().batch(BATCH_SZIE)
test_image_path = glob.glob(r'E:\WORK\tensorflow\dataset\dc_2000\test\*\*.jpg')
test_image_label = [int(p.split("\\")[-2] == 'cat') for p in test_image_path]
test_image_ds = tf.data.Dataset.from_tensor_slices((test_image_path,test_image_label))
test_image_ds = test_image_ds.map(load_preprosess_image,num_parallel_calls=AUTOTUNE)
test_image_ds = test_image_ds.repeat().batch(BATCH_SZIE)
test_count = len(test_image_path)
conv_base = tf.keras.applications.VGG16(weights='imagenet',include_top=False)
# 使用imagenet训练的参数,False不包括全连接部分,将Dense层去掉,也就是只使用在imagenet上训练获得的卷积基
print(conv_base.summary()) # 最后的输出结果维度为(None,None,None,512)
model = tf.keras.Sequential()
model.add(conv_base)
model.add(tf.keras.layers.GlobalAveragePooling2D()) # 这个作用是将上面的四维输出的后三维扁平化为一维 比flatten更高效,因为不需要什么训练参数
model.add(tf.keras.layers.Dense(512,activation='relu'))
model.add(tf.keras.layers.Dense(1,activation='sigmoid'))
print(model.summary())
conv_base.trainable = False # 使得conv_base部分参数冻结,不可训练
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
loss='binary_crossentropy',
metrics=['acc'])
history = model.fit(
train_image_ds,
steps_per_epoch=train_count//BATCH_SZIE,
epochs=5,
validation_data=test_image_ds,
validation_steps=test_count//BATCH_SZIE
)
# 微调
conv_base.trainable = True # 解冻所有的卷积层 此时共有卷积层len(conv_base.layers)=19
for layer in conv_base.layers[:-3]:
layer.trainable = False # 将前16层冻结,最后三层可以训练
model.compile(loss="binary_crossentropy",
optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),
metrics=['accuracy']) # 微调的时候学习速率要更低
initial_epoches = 5 # 上面初始训练是5轮
fine_tune_epoches = 5 # 微调的时候也训练5轮
total_epoches = initial_epoches + fine_tune_epoches # 总共训练的轮数
history = model.fit(
train_image_ds,
steps_per_epoch= train_count // BATCH_SZIE,
epochs=total_epoches,
initial_epoch= initial_epoches,
validation_data=test_image_ds,
validation_steps=test_count//BATCH_SZIE
)
作者:孙建钊
出处:http://www.cnblogs.com/sunjianzhao/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。