目录
前言
当我们在进行深度学习模型训练的时候,往往会因为数据在epoch很多次后,loss值不在下降,便会认为模型已经收敛,训练的参数已经达到了一个极限。那么这时候其实可以通过微调,微调基础模型的高阶特征表示,以使它们与特定任务更相关。通俗的来说,如果你的模型的score达到90后便不再变化,我们可以通过微调让正确率达到92。
一、微调是什么
所谓微调:冻结模型库的底部的卷积层,共同训练新添加的分类器层和顶部部分卷积层。这样可以是的模型的预测结果更加接近特定任务。
值得注意的是:只有分类器已经训练好了,才能微调卷积基的顶部卷积层。如果有没有这样的话,刚开始的训练误差很大,微调之前这些卷积层学到的表示会在反向传播的过程中被破坏掉,意思就是我们只有在模型loss值不在下降之后才能使用微调。
二、微调步骤详解
1.冻结卷积基所有层
所谓的卷积基,其实就是我们用来做特征提取的层,例如预训练模型VGG16,深度为23层,我们要做的事情就是就是把这部分层冻结。其实也就是设置为不可训练。
freeze_layers=23
for i in range(freeze_layers):
model.layers[i].trainable = False
2.设置epoch
这里需要设置两个epoch,initial_epoch和epochs两个参数。这里需要解释一下为什么要设置initial_epoch,这个也叫作初始epoch,因为前面我们已经完成所有层的训练,这个初始的initial_epoch则需要接着前面的训练epoch,比如我前面训练了50个epoch,那么我们做微调就应该从51开始,这也是接着上一次训练的结果继续训练。如果我们的epochs参数设置为100,则会进行微调训练50个epoch。
model.fit_generator(
generator = train_dataloader,
steps_per_epoch = epoch_step,
validation_data = val_dataloader,
validation_steps = epoch_step_val,
epochs = end_epoch,
initial_epoch = start_epoch,
use_multiprocessing = True if num_workers > 1 else False,
workers = num_workers,
callbacks = callbacks
)
3.单独训练分类层
这里没什么要说的,直接进行训练即可。值得注意的是这个地方因为层数变少,我们可以适当加大batch_size,这样1是可以加快训练速度,二是可以提高训练精度。
4.解冻卷积基的一部分层
在上一步完成训练后,model这个类已经保存好了上一步生成的权重,我们接下来需要解冻一部分卷积基的层。比如我用的xception预训练模型,总层数是358层,那么我们就需要解冻58层,当然实际解冻的层数不定,一般来说不要超过百分之20,尽量解冻上层。因为上层的参数,更加接近训练目标。底层参数基本都是一些基础参数,对最终结果预测影响不大。
mid_layer=300
for i in range(mid_layer,len(model.layers)):
model.layers[i].trainable = True
5.联合解冻卷积层和分类(回归)层进行训练
需要注意的也是initial_epoch和epochs两个参数,要接着第三步的epoch进行训练。完成训练后,记得保存模型的权重。
总结
模型的微调是非常重要的,很多时候就是差这么一点精度,就导致模型的失败,但是模型的微调也只能做到锦上添花,深度学习最为重要的还是基础数据的处理。一个没有误差的样本,才能让模型有一个好的结果。