caffe中BatchNorm层和Scale层实现批量归一化(batch-normalization)注意事项

caffe中实现批量归一化(batch-normalization)需要借助两个层:BatchNorm 和 Scale 
BatchNorm实现的是归一化 
Scale实现的是平移和缩放 
在实现的时候要注意的是由于Scale需要实现平移功能,所以要把bias_term项设为true 
另外,实现BatchNorm的时候需要注意一下参数use_global_stats,在训练的时候设为false,在测试的时候设为true 
use_global_stats = false 时采用滑动平均计算新的均值和方差 
use_global_stats = true 时会强制使用模型中存储的BatchNorm层均值与方差参数 


具体训练实现过程为(conv-batchnorm-scale-relu):
 

layer {
  bottom: "data"
  top: "conv1_1"
  name: "conv1_1"
  type: "Convolution"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
    num_output: 64
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "bn_conv1_1"
  type: "BatchNorm"
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  batch_norm_param {
    use_global_stats: false
  }
}
layer {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "scale_conv1_1"
  type: "Scale"
  param {
    lr_mult: 0.1
    decay_mult: 0
  }
  param {
    lr_mult: 0.1
    decay_mult: 0
  }
  scale_param {
    bias_term: true
  }
}
layer {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "relu1_1"
  type: "ReLU"
}

具体测试实现过程为(conv-batchnorm-scale-relu)(把use_global_stats由false设为true):

layer {
  bottom: "data"
  top: "conv1_1"
  name: "conv1_1"
  type: "Convolution"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
    num_output: 64
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "bn_conv1_1"
  type: "BatchNorm"
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  batch_norm_param {
    use_global_stats: true
  }
}
layer {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "scale_conv1_1"
  type: "Scale"
  param {
    lr_mult: 0.1
    decay_mult: 0
  }
  param {
    lr_mult: 0.1
    decay_mult: 0
  }
  scale_param {
    bias_term: true
  }
}
layer {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "relu1_1"
  type: "ReLU"
}

其实也没必要这么麻烦,因为在BathNorm层的源码中设定了如果use_global_stats缺省,那么在训练时为false,测试时为true,源代码为(caffe/src/caffe/layers/batch_norm_layer.cpp)第14行:

use_global_stats_ = this->phase_ == TEST;


在测试时为1,训练时为0,这样的话我们在代码里就不用设定use_global_stats的值了,这样上面的代码我们可以简化为(训练和测试时都一样):

layer {
  bottom: "data"
  top: "conv1_1"
  name: "conv1_1"
  type: "Convolution"
  param {
    lr_mult: 1
    decay_mult: 1
  }
  param {
    lr_mult: 2
    decay_mult: 0
  }
  convolution_param {
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
    num_output: 64
    pad: 1
    kernel_size: 3
  }
}
layer {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "bn_conv1_1"
  type: "BatchNorm"
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
  param {
    lr_mult: 0
    decay_mult: 0
  }
}
layer {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "scale_conv1_1"
  type: "Scale"
  param {
    lr_mult: 0.1
    decay_mult: 0
  }
  param {
    lr_mult: 0.1
    decay_mult: 0
  }
  scale_param {
    bias_term: true
  }
}
layer {
  bottom: "conv1_1"
  top: "conv1_1"
  name: "relu1_1"
  type: "ReLU"
}

 

备注:

可以看到这一层是batchnormal层,其中的参数设置,三个param中的lr_mult和decay_mult都设置为0

原因如下:

caffe中的batchnormal层中有三个参数(具体代表什么自行去caffe源码中看吧:均值、方差和滑动系数),训练时这三个参数是通过当前的数据计算得到的,并且不通过反向传播更新,因此必须将lr_mult和decay_mult都设置为0,因为caffe中这两个参数缺省值是默认为1;如果为1,则会通过反向传播更新该层的参数,这显然是错误的做法。

此外,对于参数use_global_stats:如果为真,则使用保存的均值和方差,否则采用滑动平均计算新的均值和方差。该参数缺省的时候,如果是测试阶段则等价为真,如果是训练阶段则等价为假。

moving_average_fraction:滑动平均的衰减系数,默认为0.999

eps:分母附加值,防止除以方差时出现除0操作,默认为1e-5(不同框架采用的默认值不一样)
 

更重要的一点:由于BN层中会做归一化处理,因此BN层前的那个卷积层应当将bias关闭,因为BN的操作会做一个减去均值的操作,因此卷积层有没有bias都会被这个减法操作去除掉,所以这时候bias不起作用,因此将其关闭可以减少参数量且不影响模型准确率。

 

convolution_param {
       num_output: 32
       bias_term: false
       pad: 1
       kernel_size: 3
       stride: 2
       weight_filler {
         type: "msra"
       }
}

同时,由于caffe中,Scale层不需要对两个参数正则化,所以设置如下:

param {
lr_mult: 1
decay_mult: 0
}
param {
lr_mult: 1
decay_mult: 0
}

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NineDays66

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值