本文重点介绍BatchNorm的定义和相关特性,并介绍了其详细实现和具体应用。希望可以帮助大家加深对其理解。
嗯嗯,闲话少说,我们直接开始吧!
BatchNorm是2015年提出的网络层,这个层具有以下特性:
易于训练:由于网络权重的分布随这一层的变化小得多,因此我们可以使用更高的学习率。我们在训练中收敛的方向没有那么不稳定,这样我们就可以更快地朝着loss收敛的方向前进。
提升正则化:尽管网络在每个epoch都会遇到相同的训练样本,但每个小批量的归一化是不同的,因此每次都会稍微改变其值。
提升精度:可能是由于前面两点的结合,论文提到他们获得了比当时最先进的结果更好的准确性。
BatchNorm所做的是确保接收到的输入具有平均值0和标准偏差1。
本文中介绍的算法如下:

下面是我自己用pytorch进行的实现:
import numpy as np
import torch
from torch import nn
from torch.nn import Parameter
class BatchNorm(nn.Module):
def __init__(self, num_features, eps=1e-5, momentum=0.1):
super().__init__()
self.gamma = Parameter(torch.Tensor(num_features))
self.beta = Parameter(torch.Tensor(num_features))
self.register_buffer("moving_avg", torch.zeros(num_features))
self.register_buffer("moving_var", torch.ones(num_features))
self.register_buffer("eps", torch.tensor(eps))
self.register_buffer("momentum", torch.tensor(momentum))
self._reset()
def _reset(self):
self.gamma.data.fill_(1)
self.beta.data.fill_(0)
def forward(self, x):
if self.training:
mean = x.mean(dim=0)
var = x.var(dim=0)
self.moving_avg = self.moving_avg * momentum + mean * (1 - momentum)
self.moving_var = self.moving_var * momentum + var * (1 - momentum)
else:
mean = self.moving_avg
var = self.moving_var
x_norm = (x - mean) / (torch.sqrt(var + self.eps))
return x_norm * self.gamma + self.beta
这里对其进行补充说明如下:
这似乎总是有帮助的,所以没有理由不使用它。通常它出现在全连接层/卷积层和激活函数之间。但也有人认为,最好把它放在激活层之后。我找不到任何关于激活函数之后使用它的论文,所以最安全的选择是按照每个人的做法,在激活函数前使用它。
列举下关于实际应用中BatchNorm的技巧总结如下: