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
)
posted @ 2022-03-03 22:05  白菜茄子  阅读(295)  评论(0编辑  收藏  举报