一、总结
一句话总结:
【微调是指将预训练网络的前几层解冻】:微调是指将预训练网络的前几层解冻,在猫狗分类的例子中,可以看到准确率从90到94,提高了4个百分点
【先训练好分类层】:微调的话,注意先把dense层(分类层)训练好,再低学习率的训练网络最后几层
# 冻结直到某一层的所有层 conv_base.trainable = True set_trainable = False for layer in conv_base.layers: if layer.name == 'block5_conv1': set_trainable = True if set_trainable: layer.trainable = True else: layer.trainable = False
1、模型微调(fine-tuning)?
【一种模型复用方法】:另一种广泛使用的模型复用方法是模型微调(fine-tuning),与特征提取互为补充。
【微调是指将前几层解冻】:对于用 于特征提取的冻结的模型基,微调是指将其顶部的几层“解冻”,并将这解冻的几层和新增加的 部分(本例中是全连接分类器)联合训练
【略微调整抽象表示】:之所以叫作微调,是因为它只是略微调 整了所复用模型中更加抽象的表示,以便让这些表示与手头的问题更加相关。
2、只有上面的分类器已经训练好了,才能微调卷积基的顶部几层?
【只有分类器训练好了才能微调】:前面说过,冻结VGG16 的卷积基是为了能够在上面训练一个随机初始化的分类器。同理, 只有上面的分类器已经训练好了,才能微调卷积基的顶部几层。
【没训练好,微调的话,误差很大】:如果分类器没有训练好,那么训练期间通过网络传播的误差信号会特别大,微调的几层之前学到的表示都会被破坏。
3、微调网络的步骤?
(1) 在已经训练好的基网络(base network)上添加自定义网络。
(2) 冻结基网络。 (3) 训练所添加的部分。
(4) 解冻基网络的一些层。
(5) 联合训练解冻的这些层和添加的部分。
4、为什么不微调更多层?为什么不微调整个卷积基?
【靠底部的层编码的是更加通用的可复用特征】:卷积基中更靠底部的层编码的是更加通用的可复用特征,而更靠顶部的层编码的是更专 业化的特征。
【微调顶部的层更有用】:微调这些更专业化的特征更加有用,因为它们需要在你的新问题上改变用 途。微调更靠底部的层,得到的回报会更少。 训练的参数越多,过拟合的风险越大。卷积基有1500 万个参数,所以在你的小型数据 集上训练这么多参数是有风险的。
5、微调使用的优化器的特点?
【学习率非常小的 RMSProp 优化器】:现在你可以开始微调网络。我们将使用学习率非常小的 RMSProp 优化器来实现。之所以让 学习率很小,是因为对于微调的三层表示,我们希望其变化范围不要太大。太大的权重更新可 能会破坏这些表示。
model.compile(loss='binary_crossentropy', optimizer=optimizers.RMSprop(lr=1e-5), metrics=['acc'])
6、注意,从损失曲线上看不出与之前相比有任何真正的提高(实际上还在变差)。你可能感到 奇怪,如果损失没有降低,那么精度怎么能保持稳定或提高呢?
【影响精度的是损失值的分布,而非平均】:图中展示的是逐点(pointwise)损失值的平均值,但影响精度的是损失值的分布,而不是平均值,因为精度是 模型预测的类别概率的二进制阈值。即使从平均损失中无法看出,但模型也仍然可能在改进。
7、使用预训练网络知识点总结?
【卷积神经网络在小数据集上也挺好用】:卷积神经网络是用于计算机视觉任务的最佳机器学习模型。即使在非常小的数据集上也 可以从头开始训练一个卷积神经网络,而且得到的结果还不错。
【数据增强解决小数据集的过拟合】:在小型数据集上的主要问题是过拟合。在处理图像数据时,数据增强是一种降低过拟合 的强大方法。
【使用预训练网络来实现特征提取】:利用特征提取,可以很容易将现有的卷积神经网络复用于新的数据集。对于小型图像数 据集,这是一种很有价值的方法。
【对预训练网络实现微调】:作为特征提取的补充,你还可以使用微调,将现有模型之前学到的一些数据表示应用于 新问题。这种方法可以进一步提高模型性能。
8、计算测试集准确率?
model的evaluate方法:test_loss, test_acc = model.evaluate(test_generator, steps=50)
test_generator = test_datagen.flow_from_directory( test_dir, target_size=(150, 150), batch_size=20, class_mode='binary') test_loss, test_acc = model.evaluate(test_generator, steps=50) print('test acc:', test_acc)
二、5.3-4、猫狗分类(使用预训练网络-微调模型)
博客对应课程的视频位置:
import pandas as pd
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.keras.applications import VGG16
# 把vgg模型弄过来
conv_base = VGG16(weights='imagenet',
# include_top=False表示不包含dense层
include_top=False,
input_shape=(150, 150, 3))
# C:\Users\Fan Renyi\.keras\models\vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
import os
base_dir = 'E:\\78_recorded_lesson\\001_course_github\\AI_dataSet\\dogs-vs-cats\\cats_and_dogs_small'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')
test_dir = os.path.join(base_dir, 'test')
from tensorflow.keras import models
from tensorflow.keras import layers
model = models.Sequential()
model.add(conv_base)
model.add(layers.Flatten())
model.add(layers.Dense(256, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.summary()
conv_base.trainable = False
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import optimizers
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
# 注意,不能增强验证数据
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
train_dir, # 目标目录
target_size=(150, 150), # 将所有图像的大小调整为 150×150
batch_size=20,
class_mode='binary') # 因为使用了binary_crossentropy 损失,所以需要用二进制标签
validation_generator = test_datagen.flow_from_directory(
validation_dir,
target_size=(150, 150),
batch_size=20,
class_mode='binary')
model.compile(loss='binary_crossentropy',
optimizer=optimizers.RMSprop(lr=2e-5),
metrics=['acc'])
history = model.fit(
train_generator,
steps_per_epoch=100,
epochs=30,
validation_data=validation_generator,
validation_steps=50)
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, 'b--', label='Training acc')
plt.plot(epochs, val_acc, 'r-', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs, loss, 'b--', label='Training loss')
plt.plot(epochs, val_loss, 'r-', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
仅微调卷积基最后的两三层
# 冻结直到某一层的所有层
conv_base.trainable = True
set_trainable = False
for layer in conv_base.layers:
if layer.name == 'block5_conv1':
set_trainable = True
if set_trainable:
layer.trainable = True
else:
layer.trainable = False
for layer in conv_base.layers:
print(layer)
print(layer.trainable)
微调模型
model.compile(loss='binary_crossentropy',
optimizer=optimizers.RMSprop(lr=1e-5),
metrics=['acc'])
history = model.fit(
train_generator,
steps_per_epoch=100,
epochs=100,
validation_data=validation_generator,
validation_steps=50)
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, 'b--', label='Training acc')
plt.plot(epochs, val_acc, 'r-', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs, loss, 'b--', label='Training loss')
plt.plot(epochs, val_loss, 'r-', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
这些曲线看起来包含噪声。为了让图像更具可读性,你可以将每个损失和精度都替换为指数 移动平均值,从而让曲线变得平滑。
使曲线变得平滑
def smooth_curve(points, factor=0.8):
smoothed_points = []
for point in points:
if smoothed_points:
previous = smoothed_points[-1]
# 上一个节点*0.8+当前节点*0.2
smoothed_points.append(previous * factor + point * (1 - factor))
else:
# 添加point
smoothed_points.append(point)
return smoothed_points
plt.plot(epochs,smooth_curve(acc), 'b--', label='Smoothed training acc')
plt.plot(epochs,smooth_curve(val_acc), 'r-', label='Smoothed validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs,smooth_curve(loss), 'b--', label='Smoothed training loss')
plt.plot(epochs,smooth_curve(val_loss), 'r-', label='Smoothed validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
测试数据上最终评估这个模型
test_generator = test_datagen.flow_from_directory(
test_dir,
target_size=(150, 150),
batch_size=20,
class_mode='binary')
test_loss, test_acc = model.evaluate_generator(test_generator, steps=50)
print('test acc:', test_acc)
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:《python深度学习》笔记—5.3-4、猫狗分类(使用预训练网络-微调模型) - Python技术站