caffe fine-tune策略

来源:互联网 发布:java webservice传xml 编辑:程序博客网 时间:2024/05/24 06:22

               caffe fine-tune策略
  现在随着深度学习技术的迅速发展,深度学习技术在图像和语音方向的应用已经很成熟了。目前工程上应用深度学习一般源于数据的限制都是在ImageNet pre-trained model的基础上进行微调—fine-tune。由于ImageNet数以百万计带标签的训练集数据,使得如CaffeNet之类的预训练的模型具有非常强大的泛化能力,这些预训练的模型的中间层包含非常多一般性的视觉元素,我们只需要对他的后几层进行微调,在应用到我们的数据上,通常就可以得到非常好的结果。
  微调的目的是使别人训练好的模型更适合自己的数据,因此,微调的数据一般都是适合自己应用的数据。但是,大牛建议,在微调是不要全部使用自己的数据,应该将自己的数据和原始训练数据混合在一起,并逐步增加自己的数据的比例,这样效果可能会好一些(自己也没有试过)。
  微调的步骤可以参考我的另一篇博客: http://blog.csdn.net/xjz18298268521/article/details/52061410
下面介绍一下我在微调的时候的遇到的一些问题和解决方法以及参数的选择
   参数的一般设置:

  • base_lr:初始学习率,这个是非常重要的一个参数;
  • momentum:一般设置为0.9,如果base_lr特别低的话也可以设置为0.99或0.99等
  • weight_decay:默认0.005,可以适当调整,类似于正则化项;
  • 如果训练的时候loss值很大不降,则需要降低学习率(可以降低base_lr值)。
      以前我微调的时候全连接层的lr_mult和decay_mult都是按照默认的1和2,后来网上有人说对于最后一个全连接层需要增大其学习率,所以其两个lr_mult,如分别设置层10和20。
               这里写图片描述
    微调的迭代次数:
      以前我微调的时候最大迭代次数设置的很小一般就几千次,最后训练的模型的效果也还行,主要是一开始我的数据集比较干净,所以微调的时候模型很快就收敛了。最近我在参加竞赛拿到的数据是非常不干净的,按照原来的策略导致最后训练的模型不是很理想。后来我增大最后一个全连接层的学习率参数(lr_mult设置为10,20),最大迭代次数增加(我的增加到30000),主要是我发现在训练的时候虽然accuracy在几千次迭代后就饱和了,但是发现loss随着迭代还会在降低(不过收敛的很缓慢)。
    step_size:
       我平时微调的时候lr_policy一般是选择step,学习率变化策略,常见的有fixed(固定), inv,step等。选择step后,后面需要选择学习率变换的步长stepsize。例如:stepsize: 1000,代表迭代1000次后你的学习率将改变一次。我一开始stepsize设置很小,后来网上有人说stepsize最好是设置大一点,我最大迭代次数30000,stepsize10000次降低学习率十分之一。
    test_interval:
       这个参数代表的是你训练迭代多少次进行测试一次,这个参数是不影响训练模型的性能的,一般我是设置为500,让训练的迭代次数多一点,测试的效果可能会好点。
    batch_size:
      在train_val.prototxt文件中有训练中随机梯度下降法的batch_size大小的设置,要是硬件支持,batch_size一般设置大点会好点,我用的是titan x,一般caffenet微调的时候一般是train和test都是设置为100,微调vgg的时候需要降低batch_size,不然会因为显存不够导致电脑重启。在训练的过程中如果发现loss值震荡的很厉害可以适当的增大batch_size的值。
    下面给出一个比较经典的微调策略的网站:
    http://lamda.nju.edu.cn/weixs/project/CNNTricks/CNNTricks.html
    里面说明的微调策略是根据你的数据的大小和pre-train模型的数据的相似性来确定的,如下图所示:
    这里写图片描述
    另外看了一篇博客记录微调的一些参数解释:
    1. finetune的过程相当于继续训练,跟直接训练的区别是初始化的时候:
        直接训练是按照网络定义指定的方式初始化(如高斯随机初始化);
         finetune是用你已经有的参数文件来初始化(就是之前训练好的caffemodel);
    2. 这个问题有两种情况:比如有4个全连接层A->B->C->D
      你希望C层的参数不会改变,C前面的AB层的参数也不会改变,这种情况也就是D层的梯度不往前反向传播到D层的输入blob(也就是C层的输出blob 没有得到梯度),你可以通过设置D层的propagate_down为false来做到。propagate_down的数量与输入blob的数量相同,假如你某个层有2个输入blob,那么你应该在该layer的Param里面写上两行:
         propagate_down : 0 # 第1个输入blob不会得到反向传播的梯度
          propagate_down : 0 # 第2个输入blob不会得到反向传播的梯度
      这样的话,你这个layer的梯度就不会反向传播啦,前面的所有layer的参数也就不会改变了。
        你希望C层的参数不会改变,但是C前面的AB层的参数会改变,这种情况,只是固定了C层的参数,C层得到的梯度依然会反向传播给前面的B层。只需要将对应的参数blob的学习率调整为0:
      你在layer里面加上param { lr_mult: 0 }就可以了,比如全连接层里面:
      layer {
      type: “InnerProduct”
      param { # 对应第1个参数blob的配置,也就是全连接层的参数矩阵的配置
      lr_mult: 0 # 学习率为0,其他参数可以看caffe.proto里面的ParamSpec这个类型
      }
      param { # 对应第2个参数blob的配置,也就是全连接层的偏置项的配置
      lr_mult: 0 # 学习率为0
      }
0 0
原创粉丝点击