silver lining's blog

对于finetune的理解

Finetune问题


大家好,一直很困惑caffe在做fine-tuning时,有两个问题:

  1. 如果将imagenet训练得到的网络最后的softmax层的输出由1000改为20,那么用自己的数据进行训练后,之前net中的卷积层,全连接层的参数是否会发生更新?
  2. 假设fine-tune时网络参数发生变化,我不想让某些特定层的参数在fine-tuning的时候发生变化,是否可以将这些层的学习率置0?
1
2
3
4
作者:朱坚升
链接:http://www.zhihu.com/question/35754716/answer/66561128
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

解释Finetune过程


  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里面写上两行:

      1
      2
      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 }就可以了,比如全连接层里面:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    layer {
    type: "InnerProduct"
    param { # 对应第1个参数blob的配置,也就是全连接层的参数矩阵的配置
    lr_mult: 0 # 学习率为0,其他参数可以看caffe.proto里面的ParamSpec这个类型
    }
    param { # 对应第2个参数blob的配置,也就是全连接层的偏置项的配置
    lr_mult: 0 # 学习率为0
    }
    }