实际任务中,往往会需要多步训练,或者将两个网络拼成一个网络,那么将新的小模型拼接在已经训练好的主干网络上训练,如何做到只训练新支,而不破坏原主干网络已经训练好的weight,这就需要锁住训练,保证网络只更新新支的weight。
锁住训练需要三步:
1、将需要锁住的层的w和b的学习率lr_mult设置为0;
将该层的学习率置0,只是固定了该层的参数,即该层的参数将不更新,该层得到的梯度依然会反向传播到前面的层,前面的层的参数依然会更新。
2、将需要锁住的层中含有BN 层的use_global_stats改为true;
use_global_stats==true时会强制使用模型中存储的BatchNorm层均值与方差参数,而非基于当前batch内计算均值和方差。
use_global_stats为false的时候通过moving average策略计算模型中最终存储的均值和方差
3、若要阻止反向传播,则在该层添加参数propagate_down: 0。
propagate_down的设置使得前面的所有层都不会得到反向传播,即前面所有的层的参数都不会更新,具体使用方法:
layer{
name: "conv2_3x3"
type: "ConvolutionData"
bottom: "pool1_3x3"
top: "conv2_3x3"
param{
lr_mult: 1
decay_mult: 1
}
propagate_down: 0
convolution_param {
num_output: 64
bias_term: false
pad: 1
kernel_size: 3
stride: 1
weight_filler {
type: "xavier"
}
}
}
-
Example
如上图的网络结构,是经常会涉及到的情况。黄色节点(ABCD)该支是主干网络,当我们想在主干网络上再接一个小网络,完成特定任务,目的是公用ABC三层公共层,节省模型大小。那么就需要只训练EF两层,而保证主干网络的ABCD层都不被改动。那么,这种任务的网络该如何训练呢?
1、在E层通过添加propagate_down: 0,来锁住ABC三层,保证这三层参数不更新。
2、在D层中,若有学习率则将lr_mult设置为0,若有use_global_stats,则设置为true;保证D层的参数不更新。