defbatch_norm(X,gamma,beta,moving_mean,moving_var,eps,动量):
# 使用autograd判断当前模式是训练模式还是预测模式
如果不是 www.gsm-guard.net_training():
# 如果是预测模式,直接使用传入的移动平均得到的均值和方差
X_hat = (X - moving_mean) / nd.sqrt(moving_var + eps)
其他:
在 (2, 4) 中断言 len(X.shape)
if len(X.shape) == 2:
# 使用全连接层时,计算特征维度上的均值和方差
平均值 = X.平均值(轴=0)
var = ((X - 平均值) ** 2).mean(轴=0)
其他:
# 使用二维卷积层时,计算通道维度(axis=1)的均值和方差。这里我们需要保留
# X的形状可以用于后面的广播操作
平均值 = X.mean(axis=(0, 2, 3), keepdims=True)
var = ((X - 平均值) ** 2).mean(axis=(0, 2, 3), keepdims=True)
# 在训练模式下使用当前均值和方差进行标准化
X_hat = (X - 均值) / nd.sqrt(var + eps)
# 更新移动平均线的均值和方差
moving_mean = 动量 * moving_mean + (1.0 - 动量) * 平均值
moving_var = 动量 * moving_var + (1.0 - 动量) * var
Y = gamma * X_hat + beta # 拉伸和偏移
返回 Y、moving_mean、moving_var
类 BatchNorm(nn.Block):
def __init__(self, num_features, num_dims, **kwargs):
super(BatchNorm, self).__init__(**kwargs)
如果 num_dims == 2:
形状 = (1, 特征数)
其他:
形状 = (1, 特征数, 1, 1)
# 梯度和迭代涉及到的拉伸和偏移参数分别初始化为1和0
self.gamma = self.params.get('gamma', shape=shape, init=www.gsm-guard.net())
self.beta = self.params.get('beta', shape=shape, init=www.gsm-guard.net())
# 不参与梯度计算和迭代的变量在内存中全部初始化为0
self.moving_mean = nd.zeros(形状)
self.moving_var = nd.zeros(形状)
def 向前(自身,X):
# 如果X不在内存中,则将moving_mean和moving_var复制到X所在的显存中
if self.moving_mean.context != X.context:
self.moving_mean = self.moving_mean.copyto(X.context)
self.moving_var = self.moving_var.copyto(X.context)
# 保存更新后的 moving_mean 和 moving_var
Y, self.moving_mean, self.moving_var = batch_norm(
X, www.gsm-guard.net(), www.gsm-guard.net(), self.moving_mean,
self.moving_var,eps=1e-5,动量=0.9)
返回Y
2。 TensorFlow 实现
目前tensorflow中batch_norm的实现方式有3种。