Tensorflow官网——迁移学习和微调部分解读

import matplotlib.pyplot as plt
import numpy as np
import os
import tensorflow as tf

#数据预处理
#数据下载
from tensorflow.keras.preprocessing import image_dataset_from_directory
_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'
path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=_URL, extract=True)
PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered')

train_dir = os.path.join(PATH, 'train')#连接两个或更多的路径名组件
validation_dir = os.path.join(PATH, 'validation')

BATCH_SIZE = 32
IMG_SIZE = (160, 160)

train_dataset = image_dataset_from_directory(train_dir, shuffle=True,
                                             batch_size=BATCH_SIZE, image_size=IMG_SIZE)
validation_dataset = image_dataset_from_directory(validation_dir, shuffle=True,
                                                  batch_size=BATCH_SIZE, image_size=IMG_SIZE)
class_names = train_dataset.class_names

val_batches = tf.data.experimental.cardinality(validation_dataset)
test_dataset = validation_dataset.take(val_batches // 5)#将其中的20%移至测试集
validation_dataset = validation_dataset.skip(val_batches // 5)#将其中的20%移至测试集
# print('Number of validation batches: %d' % tf.data.experimental.cardinality(validation_dataset))
# print('Number of test batches: %d' % tf.data.experimental.cardinality(test_dataset))

#配置数据集以提高性能
AUTOTUNE = tf.data.AUTOTUNE

train_dataset = train_dataset.prefetch(buffer_size=AUTOTUNE)
validation_dataset = validation_dataset.prefetch(buffer_size=AUTOTUNE)
test_dataset = test_dataset.prefetch(buffer_size=AUTOTUNE)

#使用数据扩充
data_augmentation = tf.keras.Sequential([
  tf.keras.layers.experimental.preprocessing.RandomFlip('horizontal'),
  tf.keras.layers.experimental.preprocessing.RandomRotation(0.2),
])

# for image, _ in train_dataset.take(1):
#   plt.figure(figsize=(10, 10))
#   first_image = image[0]
#   for i in range(9):
#     ax = plt.subplot(3, 3, i + 1)
#     augmented_image = data_augmentation(tf.expand_dims(first_image, 0))
#     plt.imshow(augmented_image[0] / 255)
#     plt.axis('off')
#   plt.show()

# 重新缩放像素值
preprocess_input = tf.keras.applications.mobilenet_v2.preprocess_input
rescale = tf.keras.layers.experimental.preprocessing.Rescaling(1./127.5, offset= -1)#若将像素值从 [0,255] 重新缩放为 [0, 1],那么Rescaling(1./255, offset= 0)

#从预训练卷积网络创建基础模型
# Create the base model from the pre-trained model MobileNet V2
IMG_SHAPE = IMG_SIZE + (3,)#IMG_SHAPE由[160,160]变为[160,160,3]
base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
                                               include_top=False,
                                               weights='imagenet')
image_batch, label_batch = next(iter(train_dataset)) #image_batch:[32,160,160,3],label_batch:[32,]
#将每个 160x160x3 图像转换为 5x5x1280的特征块
feature_batch = base_model(image_batch) #feature_batch:[32,5,5,1280]
print(feature_batch.shape)

##特征提取
#冻结卷积基 : 冻结可避免在训练期间更新给定层中的权重
base_model.trainable = False

# Let's take a look at the base model architecture
base_model.summary()

#添加分类头
global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
#feature_batch:[32,5,5,1280]-->feature_batch_average:[32,1280]
feature_batch_average = global_average_layer(feature_batch)#将特征转换成每个图像一个向量(包含 1280 个元素)
# print(feature_batch_average.shape)

#将这些特征转换成每个图像一个预测 : 正数预测 1 类,负数预测 0 类。
prediction_layer = tf.keras.layers.Dense(1) #只有一个输出值,prediction_batch:[32,1]
#feature_batch_average:[32,1280]->prediction_batch:(32,1)
prediction_batch = prediction_layer(feature_batch_average)
# print(prediction_batch.shape)

inputs = tf.keras.Input(shape=(160, 160, 3))
x = data_augmentation(inputs)
x = preprocess_input(x)# 重新缩放像素值
x = base_model(x, training=False)
x = global_average_layer(x)#添加分类头
x = tf.keras.layers.Dropout(0.2)(x)
outputs = prediction_layer(x)#将这些特征转换成每个图像一个预测
model = tf.keras.Model(inputs, outputs)

#编译模型
base_learning_rate = 0.0001
model.compile(optimizer=tf.keras.optimizers.Adam(lr=base_learning_rate),
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.summary()
print("len(model.trainable_variables)",len(model.trainable_variables))

#训练模型
initial_epochs = 10
loss0, accuracy0 = model.evaluate(validation_dataset)
print("initial loss: {:.2f}".format(loss0))
print("initial accuracy: {:.2f}".format(accuracy0))
history = model.fit(train_dataset,
                    epochs=initial_epochs,
                    validation_data=validation_dataset)

#学习曲线
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

plt.figure(figsize=(8, 8))
plt.subplot(2, 1, 1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.ylabel('Accuracy')
plt.ylim([min(plt.ylim()),1])
plt.title('Training and Validation Accuracy')

plt.subplot(2, 1, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.ylabel('Cross Entropy')
plt.ylim([0,1.0])
plt.title('Training and Validation Loss')
plt.xlabel('epoch')
plt.show()

#解冻模型的顶层

base_model.trainable = True
# 让我们来看看基础模型中有多少层。
print("Number of layers in the base model: ", len(base_model.layers))
# 从该层开始进行微调
fine_tune_at = 100
# 在“微调”图层之前冻结所有图层
for layer in base_model.layers[:fine_tune_at]:
  layer.trainable =  False

#编译模型
model.compile(loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
              optimizer = tf.keras.optimizers.RMSprop(learning_rate=base_learning_rate/10),
              metrics=['accuracy'])

#继续训练模型
fine_tune_epochs = 10
total_epochs =  initial_epochs + fine_tune_epochs
history_fine = model.fit(train_dataset,
                         epochs=total_epochs,
                         initial_epoch=history.epoch[-1],
                         validation_data=validation_dataset)

#学习曲线
acc += history_fine.history['accuracy']
val_acc += history_fine.history['val_accuracy']
loss += history_fine.history['loss']
val_loss += history_fine.history['val_loss']

plt.figure(figsize=(8, 8))
plt.subplot(2, 1, 1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.ylim([0.8, 1])
plt.plot([initial_epochs-1,initial_epochs-1],
          plt.ylim(), label='Start Fine Tuning')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(2, 1, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.ylim([0, 1.0])
plt.plot([initial_epochs-1,initial_epochs-1],
         plt.ylim(), label='Start Fine Tuning')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.xlabel('epoch')
plt.show()

#评估和预测
loss, accuracy = model.evaluate(test_dataset)
print('Test accuracy :', accuracy)

#Retrieve a batch of images from the test set
image_batch, label_batch = test_dataset.as_numpy_iterator().next()
predictions = model.predict_on_batch(image_batch).flatten()

# Apply a sigmoid since our model returns logits
predictions = tf.nn.sigmoid(predictions)
predictions = tf.where(predictions < 0.5, 0, 1)

print('Predictions:\n', predictions.numpy())
print('Labels:\n', label_batch)

plt.figure(figsize=(10, 10))
for i in range(9):
  ax = plt.subplot(3, 3, i + 1)
  plt.imshow(image_batch[i].astype("uint8"))
  plt.title(class_names[predictions[i]])
  plt.axis("off")
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
TensorFlow VGG迁移学习微调是一种利用预先训练的VGG模型,并在其基础上进行微调的方法。VGG是一种深度卷积神经网络模型,已在大规模图像分类任务上证明了其有效性。 迁移学习是指将在一个任务上训练好的模型应用于另一个任务上的技术。而VGG迁移学习微调则是将预训练的VGG模型应用于特定任务,并对其进行微调以提高性能。 在迁移学习微调过程中,首先加载预训练的VGG模型权重。然后,将模型的最后几层替换为适应特定任务的新层。这些新层通常是全连接层,用于针对任务的特定类别进行预测。 在微调中,新层的权重被随机初始化,并与预训练模型的权重一起进行训练。这样做是为了使模型能够更好地适应新任务,因为预训练模型的权重已经学习到了许多通用特征。 训练时,可以使用较小的学习率来微调预训练模型的权重,以避免对这些权重的大幅度更新。同样,需要在训练过程中使用较大的数据集,并进行适当的数据增强来避免过拟合。 通过VGG迁移学习微调,可以利用预训练模型的优势,减少在现有数据集上进行训练所需的时间和计算资源。此外,由于预训练模型已在大规模数据集上进行了训练,所以它们通常会具备良好的特征提取能力,从而为微调任务提供更好的初始特征。 总的来说,TensorFlow VGG迁移学习微调是一种利用预训练模型进行迁移学习的方法,可以提高特定任务的性能,并减少训练所需的资源和时间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值