迁移学习技巧以及如何更好的finetune 模型经验总结

本文参考自如下文章https://blog.csdn.net/u014381600/article/details/71511794 

                                        https://blog.csdn.net/qq_28659831/article/details/78985797

仅方便自己学习使用 如有侵权 请联系删除

文章参考翻译自cs231n 

其实我们常用的直接finetune pre-trained model就属于迁移学习(Transfer Learning)的一种。因为我们很少在训练一个新任务时从零开始训练,一个是由于训练时间限制,另一个时训练样本过大存储空间也不一定允许,如ImageNet数据经济120万张图片,1000个类别,是很麻烦的从头开始训练(train from scratch)。因此我们的迁移学习通常有三种情况: 
1:把预训练的CNN模型当做特征提取器: 
得到在ImageNet数据库上pre-trained后的CNN模型,去掉最后一层全连接层(因为最后一层的输出是1000个类别的概率,在自己的问题上不适用,因为一般你的类别也并不是1000类),然后将剩下的全部网络结构当做一个特征提取器,原来的网络最后一层的输出就是你的特征,然后将该特征输入一个SVM分类器或者softmax分类器就可以快速实现你自己的分类任务。 
2:finetune model 
这也是最常用的,因为一般我们并不会简单的把模型像1一样当做特征提取器使用,而是让模型去fit我们的训练数据,使得性能更好。因此我们除了像第一步里面一样去掉最后一个FC层伊以外,在网络训练过程中还要更新权重,进行BP传导(方法见下文)。最简单粗暴的就是对修改后的全部网络层进行权重更新(当自己的数据库较大时),但是当我们本身任务的数据库较小时,为了避免过拟合,我们需要对网络的前几层固定参数(不更新权重),而只更新网络结构的后面几层。这是因为网络的前几层得到的特征是比较基础local的特征,基本适用于全部任务(边缘,角点特征),而网络层数越高的层,和数据库全局信息联系越紧密,(网络越靠后,信息越global,越靠前,越local,local的信息是多数情况共享的,而global的信息和原图紧密相关)。

下面根据你本身数据库的特点有几种情况可参考: 
1:新的数据库较小,并且和pre-trained model所使用的训练数据库相似度较高: 
由于数据库较小,在进行finetune存在overfit的风险,又由于数据库和原始数据库相似度较高,因此二者不论是local feature还是global feature都比较相近,所以此时最佳的方法是把CNN网络当做特征提取器然后训练一个分类器进行分类 
2:新的数据库较大,并且和pre-trained model所使用的训练数据库相似度较高: 
很明显,此时我们不用担心overfit,因此对全部网络结构进行finetune是较好的。 
3:新的数据库较小,并且和pre-trained model所使用的训练数据库差异很大: 
由于数据库较小,不适合进行finetune,由于数据库差异大,应该在单独训练网络结构中较高的层,前面几层local的就不用训练了,直接固定权值。在实际中,这种问题下较好的解决方案一般是从网络的某层开始取出特征,然后训练SVM分类器。 
3:新的数据库较大,并且和pre-trained model所使用的训练数据库差异很大: 
本来由于数据库较大,可以从头开始训练的,但是在实际中更偏向于训练整个pre-trained model的网络。

其他建议: 
1:不要随意移除原始结构中的层或者更改其参数,因为网络结构传导是一层接着一层的,你改了某层的参数,在往后传导的过程中就可能得不到预想的结果。 
2:Learning rates学习率:不应该设置的太大,因为我们finetune的前提就是这个模型的权重很多是有意义的,但是你学习率过大的话就会存在更新过快,破坏了原来好的权重信息,一般在finetune时学习率一般设置在1e-5,从头开始训练的话可以设置的大一点:1e-3.

翻译完成,接下来讲一下在tensorflow和caffe中如何实现只更新网络中的某些层的权重,而保持某些层参数固定:

A:caffe中一个较好的参考 
不更新权重的意思就是改层的学习率始终为0,因此在网络中将对应的参数设置为0:

在layer里面加上param { lr_mult: 0 }就可以了,比如全连接层里面:
layer {
    type: "InnerProduct"
    param { # 对应第1个参数blob的配置,也就是全连接层的参数矩阵W的配置
         lr_mult: 0 # 学习率为0,其他参数可以看caffe.proto里面的ParamSpec这个类型
    }
    param { # 对应第2个参数blob的配置,也就是全连接层的偏置项b的配置
        lr_mult: 0 # 学习率为0
    }
}
  • B:tensorflow中
    train_params =network.all_params
    new_train_params=[]
    for ij in train_params:
        print ij
    new_train_params=train_params[3:]
    for kk in new_train_params:
        print kk
#    exit()
    optimizer = tf.train.AdamOptimizer(learning_rate=model_config['learning_rate']).minimize(cost,var_list=new_train_params)

在写优化函数时,var_list的含义就是需要BP更新权重的层,格式是list,可以根据网络结构自己指定,

new_train_params=train_params[3:]#指定只前三层不更新,只更新后面的层

参加比赛学到的深度学习调参trick: 
1:多类问题考虑到样本不平衡问题 
trian test split时候采用各个类别内部按比例分割的思路(StratifiedShuffleSplit) 
2:数据预处理, 
2.1:清理重复数据,使用dHash:差异值哈希。精确度较高,且速度也非常快来判断,参考博客 这里写链接内容 
后面数据增广,测试数据增广方案差不多前提下,这一步数据清洗能够提高1-2个百分点,很重要!!! 

2.2:数据增强不只是有faster rcnn一种截取方式,还有(FCIS) https://github.com/msracver/FCIS (CAM) http://cnnlocalization.csail.mit.edu/

迁移学习及防止网络过拟合的几种tricks

问题一:为什么用一个数据集训练好的网络换一个数据集的表现并不是那么好?

会上解答:这不是过拟合的问题,这是域迁移(domain bias)问题。比如在动物图片的分类上做的很好的网络并不一定会在家具的分类上表现很好。

解决方案:这是迁移学习(transfer learning)领域研究的问题。对于域偏移问题目前主要的解决方法有以下几个:

(1)fine tune。直接用原来的网络中的相关参数,作为新的初始参数,用小的学习率重新训练。这种方法相当于重新训练,代价大。

(2)one-shot learning,zero-shot learning,few-shot learning。不需要、或利用新的数据集中很少的样本利用已有模型完成迁移学习。

(3)segment everything。(学习中)

问题二:防止过拟合的几种方法

会上解答:
(1)数据增广。对原始图像进行旋转放大裁切加噪声等,防止网络记住一幅图像。
加入L1/L2正则项。

(2)dropout。

(3)BN。Relu函数随着横坐标的增大趋于无穷大,当某个值很大会产生很大的激活值,网络很不稳定;BN将数据归一化,防止产生很大的激活值,BN+sigmoid、BN+Relu可以产生很好的激活值。

(4)cross validation(train,val/test)。之所以设置test和validation,是防止用test数据集刷分的现象,单独给validation测试训练效果,防止在test上“作弊”。就像ImageNet比赛每次Validation数据集公布后排名都会发生风云突变。

问题三:网络的浅层共享和高层共享问题

会上解答:
(1)浅层共享。即用浅层提取的特征做多个任务,浅层关注细节特征,感受野很小。对于分割和检测这样的任务,浅层上关注的特征是一样的,这样做浅层共享更经济。
(2)高层共享。即用高层提取的特征做多个任务。比如两张图片,是不同域的,一个是动漫的,一个是真人的,浅层是不一样的(比如纹理上的细节),但高层是一样的(比如人的轮廓),用一个网络的高层去同时做动漫和真人的轮廓检测是可以做到的。

问题四:1×1卷积的作用

会上解答:比如一个4通道到8通道的普通卷积,用一个3×3的卷积核去卷积,不仅要考虑每个通道height和width上的卷积,还要考虑channel上的卷积,一次每次卷积是跨通道的cross-channel卷积,需要计算4×3×3×8次卷积;若先在各个通道上先用3×3卷积,不跨通道卷积,得到一个4通道的中间层,再用一个1×1的卷积核去跨通道卷积4通道中间层得到8通道的输出层,只需要计算4×3×3+1×1×8次,却可以得到和普通卷积差不多的特征。这样的计算量的减少对于深层的网络来说是巨大的。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值