BN原理、做用:
函数参数讲解:
BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
1.num_features:通常输入参数为batch_sizenum_featuresheight*width,即为其中特征的数量,即为输入BN层的通道数;
2.eps:分母中添加的一个值,目的是为了计算的稳定性,默认为:1e-5,避免分母为0;
3.momentum:一个用于运行过程当中均值和方差的一个估计参数(个人理解是一个稳定系数,相似于SGD中的momentum的系数);
4.affine:当设为true时,会给定能够学习的系数矩阵gamma和beta
通常来讲pytorch中的模型都是继承nn.Module类的,都有一个属性trainning指定是不是训练状态,训练状态与否将会影响到某些层的参数是不是固定的,好比BN层或者Dropout层。一般用model.train()指定当前模型model为训练状态,model.eval()指定当前模型为测试状态。
同时,BN的API中有几个参数须要比较关心的,一个是affine指定是否须要仿射,还有个是track_running_stats指定是否跟踪当前batch的统计特性。容易出现问题也正好是这三个参数:trainning,affine,track_running_stats。
其中的affine指定是否须要仿射,也就是是否须要上面算式的第四个,若是affine=False则γ=1,β=0,而且不能学习被更新。通常都会设置成affine=True。
trainning和track_running_stats,track_running_stats=True表示跟踪整个训练过程当中的batch的统计特性,获得方差和均值,而不仅是仅仅依赖与当前输入的batch的统计特性。相反的,若是track_running_stats=False那么就只是计算当前输入的batch的统计特性中的均值和方差了。当在推理阶段的时候,若是track_running_stats=False,此时若是batch_size比较小,那么其统计特性就会和全局统计特性有着较大误差,可能致使糟糕的效果。
若是BatchNorm2d的参数track_running_stats设置False,那么加载预训练后每次模型测试测试集的结果时都不同;track_running_stats设置为True时,每次获得的结果都同样。
running_mean和running_var参数是根据输入的batch的统计特性计算的,严格来讲不算是“学习”到的参数,不过对于整个计算是很重要的。BN层中的running_mean和running_var的更新是在forward操做中进行的,而不是在optimizer.step()中进行的,所以若是处于训练中泰,就算不进行手动step(),BN的统计特性也会变化。
python
model.train() #处于训练状态 for data , label in self.dataloader: pred =model(data) #在这里会更新model中的BN统计特性参数,running_mean,running_var loss=self.loss(pred,label) #就算不进行下列三行,BN的统计特性参数也会变化 opt.zero_grad() loss.backward() opt.step()
这个时候,要用model.eval()转到测试阶段,才能固定住running_mean和running_var,有时候若是是先预训练模型而后加载模型,从新跑测试数据的时候,结果不一样,有一点性能上的损失,这个时候基本上是training和track_running_stats设置的不对。
若是使用两个模型进行联合训练,为了收敛更容易控制,先预训练好模型model_A,而且model_A内还有若干BN层,后续须要将model_A做为一个inference推理模型和model_B联合训练,此时但愿model_A中的BN的统计特性量running_mean和running_var不会乱变化,所以就须要将model_A.eval()设置到测试模型,不然在trainning模式下,就算是不去更新模型的参数,其BN都会变化,这将致使和预期不一样的结果。
函数