如何fine tuning

先看一个示例

keras入门 —在预训练好网络模型上进行fine-tune
https://blog.csdn.net/hnu2012/article/details/72179437
我们的方法是这样的:

  • 首先载入VGG16的权重
  • 接下来在初始化好的VGG网络上添加我们预训练好的模型
  • 最后将最后一个卷积块进行训练,其它层冻结,然后以很低的学习率开始训练:
  •  我们只选择最后一个卷积块进行训练,是因为训练样本很少,而VGG模型层数很多,全部训练肯定不能训练好,会过拟合。
    
  •   其次fine-tune时由于是在一个已经训练好的模型上进行的,故权值更新应该是一个小范围的,以免破坏预训练好的特征。
    

在这里插入图片描述

为什么要fine-tuning?###

我们有自己的图像识别任务,然而我们的数据集太小,直接进行训练很容易出现过拟合现象
所以比较好的解决方案是先在一个大数据集中训练以提取比较准确的浅层特征,然后再针对这个训练过的网络利用我们的数据集进行训练,那么效果就会好很多。这个过程就是fine-tuning。

model zoo###
大家都注意到了这个情况,所以
(1)FeifeiLi带头创建imagenet,这个图像库非常巨大,满足我们预先训练的各种要求,另外近期Google发布Open Images,包含900w labeled images,媲美Imagenet dataset。
(2)有些网络结构非常经典,比如Alexnet,Googlenet,VGGnet,ResNet等等,如果我们想利用这些网络去做自己的应用,就首先要把它们在大数据集(imagenet等等)中训练,然后再用自己的数据训练;显然前面一步是重复的步骤,并且非常耗时耗力(可能花费数台机器数周时间)。所以针对上述问题各种深度学习库(caffe、Tensorflow、torch)等等就预先用经典网络训练在imagenet上训练,把模型(各个参数)公布网上,我们直接拿来用即可,省去了大量pre-train的时间。这些模型(参数)就是model zoo

how to fine-tuning###
1.在imagenet训练最终输出是1000个分类,所以网络结构大概是经典网络—全连接层(前面)—最后的全连接层(1000输出)。
2.如果我们要进行fine-tuning
我们设计自己的网络
(1)经典网络—全连接层(前面)—最后的全连接层(我们的类别输出)
(2)经典网络—全连接层(all new)
(3)经典网络—卷积池化层(new)-全连接层(all new)
上述三种分别对应网络改动从小到大,对应的学习速率会有所区别。
在改动过程中,网络名称相同的参数会直接搬过来,不同的会根据设置初始化
一定注意改动过程中size要匹配!

作者:陈继科
链接:https://www.jianshu.com/p/0bccc60c7819
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

FineTuning机制的分析

为什么用FineTuning
使用别人训练好的网络模型进行训练,前提是必须和别人用同一个网络,因为参数是根据网络而来的。当然最后一层是可以修改的,因为我们的数据可能并没有1000类,而只有几类。把最后一层的输出类别和层的名称改一下。用别人的参数、修改后的网络和自己的数据进行训练,使得参数适应自己的数据,这样一个过程,通常称之为微调(fine tuning). 也就是说,我们所拥有的数据很小,不足以训练一个网络,这是用别人训练过的参数以及网络训练我们自己的数据的过程就是微调(fine tuning)。

怎么FineTunning
Fine tuning 之所以有效的原因是,用到的网络是同一个网络,用到的参数是别人已经训练好的数据,所以在准确率上会有保证,这时候再稍微调整别人训练好的参数,往往会能达到我们想要的效果。

调整net文件
因为我们自己的数据集变化了,所以要修改net网络文件,大部分的内容都不变,变的只有data层、output层、batch的大小、前几层的学习率。data层需要改成我们自己的数据,output层的修改主要包括层的名字(使用不同的名字,预训练网络中该层的参数会重新初始化)和输出类别数目,并且要减小batch的大小,但是要和GPU的大小成比例。

对于学习率的调整是很重要的,如果有的层的参数不需要更新,可以把学习率设置为0.比如有4个全连接层,希望C层的参数不会改变,C前面的AB层的参数也不会改变,这种情况也就是D层的梯度不往前反向传播到D层的输入blob(也就是C层的输出blob 没有得到梯度),你可以通过设置D层的学习率为0,layer的梯度就不会反向传播了,前面的所有layer的参数也就不会改变了。对于有参数的更新的层,学习率可以减小10倍或100倍(最后一层除外),对于最后一层的学习率可以提高10倍,加快学习速率,因为该层需要重新学习。

调整solver文件
solver.prototxt文件中的参数一般只需要修改net训练网络的名称、学习率、最大迭代次数和snapshot。首先将net从预训练使用的net换为现在使用的net,然后降低学习率(一般降低10倍或者100倍),同时,将最大迭代次数和snapshot的数目相对减少。

Fine Tuning的原理
Fine tuning的原理就是利用已知的网络结构和已知的网络参数,修改output层为我们自己的层,微调最后一层前的所有层的参数,加大最后一层的学习率,因为最后一层我们需要重新学习,所以与其它层相比要有相对较大的学习率,这样就有效利用了深度神经网络强大的泛化能力,又免去了设计复杂的模型以及耗时良久的训练,所以fine tuning是当数据量不足时的一个比较合适的选择。

fine-tuning的作用

查找的一些关于fine-tuning的解释

在网络训练中,第一层特征并不特化到任务上,特征是如何注册那个从一般到特殊的,详细参考NIPS2014上Bengio大神的文章:How transferable are features in deep neural networks?

(1)fine tuning的过程其实就是用训练好的参数(可以从已训练好的模型中获得)初始化自己的网络,然后用自己的数据接着训练,参数的调整方法与from scratch训练过程一样(梯度下降)。对于初始化过程,我们可以称自己的网络为目标网络,训练好的模型对应网络为源网络,要求目标网络待初始化的层要与源网络的层相同(层的名字、类型以及层的设置参数等等均相同)。

(2)Fine-tuning已经成为了使用DL网络的一个常用技巧(trick)。个人认为在使用深度网络做图像处理任务时,使用一个在大的数据集上预训练好的模型(ex:caffe在imagenet上训练的caffeNet, VGG16…)在自己数据上微调往往可以得到比直接用自己数据训练更好的效果,这是因为在imagenet上预训练的模型参数从微调一开始就处于一个较好的位置,这样微调能够更快的使网络收敛。对于相同类别的任务我们可以默认这样去做比较好,比如我们可以直接利用caffe在imageNet classification task 预训练的模型做一些其他的分类任务。然而当我们要做一个不同的任务,比如在imageNet上做Detection,那么可能直接拿在imagenet分类任务上预训练的模型进行微调就不是最好的了。分类考虑的是图像的一个语义信息,无论目标出现在哪里判定出类别就算正确,而检测不一样,还需要知道目标的确切位置,所以对于检测任务,我们也可以使用微调这个trick,但使用的预训练网络是在目标级别数据库上训练的(图像就是一个完整目标或者图像中所有目标都有标记—Bounding Boxes Infomation)。

(3)一般我们在训练from scratch的时候往往要在一些超大型的数据集上训练,一个目的是为了让训练得到的特征(尤其是底层特征)更加多样。而从genertive pre-training到discriminative fine-tuning的过程是一个对泛化特征进行面向task的特化的过程。首先,如果你将底层特征可视化出来,会发现底层特征多是一些边、角之类的基础几何形状,高层特征可能会发生一些有趣的变化,直接反映出你的task。 在大数据集上进行 pretrain 的目的之一是为了获得丰富、一般化的底层特征,换言之就是学到丰富的“基础几何形状”。有了这些丰富的基础几何形状,等过渡到小数据集上 finetune 的时候,就可以通过它们组合出上层具有强判别力的特征。此时,如果你再将组合出来的上层特征可视化,就会发现它们已经有模有样了,见上面辛博的配图。反之,如果你直接在小数据集上训练,那么就难以获得丰富的、一般化的基础几何形状,也就难以“描绘出”栩栩如生的上层特征。底层特征非常重要,如果底层特征不够好,特征类型不够充分,很可能训练不出来好的高层抽象。这就是为什么需要在大规模数据集上进行genertive training的原因之一。

(3)从我们的实验经验上来看,网络越深,底层的参数越难得到有效训练,这也是为什么经常有人用 vggNet finetune 的原因之一.
使用 backpropagation 进行训练的时候残差逐层传递,有可能到底层的时候残差就很小了(gradient vanishing),导致底层的参数train 不动. 这也是楼上辛同学的图里底层 feature map 没有什么改变的原因之一,因为底层参数本身就很难得到训练.
(4)finetune 就是直接从别人已经训练好的网络上拷贝参数,然后针对自己的数据训练新的模型。

这时候需要比较小的 learning_rate, 因为要在不破坏原有模型的情况下 fit 自己的数据,finetune 的好处就是可以直接获得我们难以或者无法训练的底层参数。

(5)在目标检测中,会使用VGG、Resnet、zf、Alexnet等基础网络作为特征提取器。然后调用预训练好的网络(输出pool5的feature map,详情参考这篇博客),根据特定任务进行fine-tuning(有实验证明:如果不进行fine-tuning,也就是你直接把预训练模型当做万金油使用,类似于HOG、SIFT一样做特征提取,不针对特定的任务。然后把提取的特征用于分类,结果发现p5的精度竟然跟f6、f7差不多,而且f6提取到的特征还比f7的精度略高;如果你进行fine-tuning了,那么在rcnn中f7、f6的提取到的特征最后训练的svm分类器的精度就会飙涨),据此我们明白了一个道理,如果不针对特定任务进行fine-tuning,而是把CNN当做特征提取器,卷积层所学到的特征其实就是基础的共享特征提取层,就类似于SIFT算法一样,可以用于提取各种图片的特征,而f6、f7所学习到的特征是用于针对特定任务的特征。打个比方:对于人脸性别识别来说,一个CNN模型前面的卷积层所学习到的特征就类似于学习人脸共性特征,然后全连接层所学习的特征就是针对性别分类的特征了。

题外话:在RCNN中还有另外一个疑问:CNN训练的时候,本来就是对bounding box的物体进行识别分类训练,是一个端到端的任务,在训练的时候最后一层softmax就是分类层,那么为什么作者闲着没事干要先用CNN做特征提取(提取fc7层数据),然后再把提取的特征用于训练svm分类器?这个是因为svm训练和cnn训练过程的正负样本定义方式各有不同,导致最后采用CNN softmax输出比采用svm精度还低。

事情是这样的,cnn在训练的时候,对训练数据做了比较宽松的标注,比如一个bounding box可能只包含物体的一部分,那么我也把它标注为正样本,用于训练cnn;采用这个方法的主要原因在于因为CNN容易过拟合,所以需要大量的训练数据,所以在CNN训练阶段我们是对Bounding box的位置限制条件限制的比较松(IOU只要大于0.5都被标注为正样本了);

然而svm训练的时候,因为svm适用于少样本训练,所以对于训练样本数据的IOU要求比较严格:IOU<0.7的都当成负样本(rcnn训练的是svm二分类这里会存在正负样本不均衡情况,要对负样本下采样或者对正样本上采样)。我们只有当bounding box把整个物体都包含进去了,我们才把它标注为物体类别,然后训练svm。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值