批量归一化

批量归一化

一般情况下,在数据的预处理过程中会对样本特征进行归一化处理(将均值变为0方差为1),使得优化求解过程中数值更加稳定,收敛的更快一些。
但是对于深层网络模型而言会变得复杂:矩阵的乘法,使得网络中一些层的输入值不在一个数量级,那么训练过程中会造成不稳定。数学上的解释更加直接的说法,给定批量输入,批量归一化对网络某一层激活函数前的输入进行归一化,使批量呈标准正态分布。

简化的批量归一化层

手动实现Batch Normal

分为全连接和二维卷积两种情况
可能会对二维卷积中gamma,beta的维度会有疑问?其次对于二维卷积每一个通道都要做归一,且要保证维度(4)不变(正确广播)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from mxnet import nd

def batch_normal(X,gamma,beta,eps=1e-5):
#表示全连接层,输入格式为 batchsize x feature
if len(X.shape) == 2:
mean = X.mean(axis=0)
variance = ((X-mean)**2).mean(axis=0)
#表示二维卷积,输入格式为 batchsize x channel x height,weight
else:
mean = X.mean(axis=(0,2,3),keepdims=True)
print('mean的shape',mean.shape)
variance = ((X-mean)**2).mean(axis=(0,2,3),keepdims=True)
X_hat = (X-mean)/nd.sqrt(variance+eps)
print('gamma的shape',gamma.reshape(mean.shape))
return gamma.reshape(mean.shape)*X_hat+beta.reshape(mean.shape)

# a = nd.arange(6).reshape((3,2))
# print(a)
# b = batch_normal(a,gamma=nd.array([1.,1.]),beta=nd.array([0,0]))
# print(b)

a = nd.arange(18).reshape((1,2,3,3))
print(a)
b = batch_normal(a,gamma=nd.array([1.,1.]),beta=nd.array([0,0]))
print(b)

训练和测试期间的Batch_Normal

训练期间的Batch_Normal没什么好说的。测试中一般采用移动平均的方法来近似计算,参考Gluon官方教程。然而,训练过程中实在没感觉Batch_Normal的收敛快的优势。