tf.keras.layers.BatchNormalization(axis=-1,
momentum=0.99,
epsilon=0.001,
center=True,
scale=True,
beta_initializer='zeros',
gamma_initializer='ones',
moving_mean_initializer='zeros',
moving_variance_initializer='ones',
beta_regularizer=None,
gamma_regularizer=None,
beta_constraint=None,
gamma_constraint=None,
**kwargs
)
批量标准化层应用了一种转换,使得数据的均值趋于0,标准差趋于1。该层实现的公式如下图所示。输入向量x,输出向量y。
批标准化层在训练和推理期间的工作方式不同。
在训练期间,也就是使用fit()函数或者调用参数模型training=True时,对于输入的数据batch,输出为gamma * (batch - mean(batch)) / sqrt(var(batch) + epsilon) + beta。
在推理期间,也就是使用predict()函数、evaluate()函数或者调用参数模型training=False时,对于输入的数据batch,输出为gamma * (batch - moving_mean) / sqrt(moving_var + epsilon) + beta,其中moving_mean = moving_mean * momentum + mean(batch) * (1 - momentum),moving_var = moving_var * momentum + var(batch) * (1 - momentum)。moving_mean和moving_var这两个变量只在每个训练期间结束后更新,在推理期间不更新。
另外可通过传递scale=False和center=False来禁用gamma、beta这两个参数。
正常情况下,大多数参数都不会被用到,所以只需知道这一层是用来干嘛的,什么时候需要用到这一层就行。可以参考一下这个链接。
https://zhuanlan.zhihu.com/p/24810318
BatchNormalization 广泛用于 Keras 内置的许多高级卷积神经网络架构,比如 ResNet50、Inception V3 和 Xception。BatchNormalization 层通常在卷积层或密集连接层之后使用。
原始论文讲在CNN中一般应作用与非线性激活函数之前,但是,在caffenet-benchmark-batchnorm中,作者基于caffenet在ImageNet2012上做了如下对比实验:
从上图可以看出,放在前后的差异并不是很大,甚至放在激活函数之后效果可能会更好。
# 放在非线性激活函数之前
model.add(tf.keras.layers.Conv2D(256, 2, 2)))
model.add(tf.keras.layers.BatchNormalization())
model.add(tf.keras.layers.Activation('relu'))
# 放在激活函数之后
model.add(tf.keras.layers.Conv2D(64, (3, 3), activation='relu'))
model.add(tf.keras.layers.BatchNormalization())
tf.keras.layers.LayerNormalization(
axis=-1,
epsilon=0.001,
center=True,
scale=True,
beta_initializer='zeros',
gamma_initializer='ones',
beta_regularizer=None,
gamma_regularizer=None,
beta_constraint=None,
gamma_constraint=None,
**kwargs
)
层标准化层的做法是根据样本的特征数做归一化。在每一个时刻,层标准化层对每一个样本都分别计算所有特征的均值和标准差。计算过程如下:
对于一个有k个特征的样本inputs的每一个batch x_i,计算每个batch的均值和方差。
mean_i = sum(x_i[j] for j in range(k)) / k
var_i = sum((x_i[j] - mean_i) ** 2 for j in range(k)) / k
然后计算一个归一化的x_i_normalized,包含一个用于数值稳定的因子epsilon。
x_i_normalized = (x_i - mean_i) / sqrt(var_i + epsilon)
最后将x_i_normalized乘上两个可学习的参数gamma和beta。
output_i = x_i_normalized * gamma + beta
如果center和scale两个参数为False,那么上述过程的beta和gamma参数将会被禁用。
这里参考官网的一个例子:
>>> data = tf.constant(np.arange(10).reshape(5, 2) * 10, dtype=tf.float32)
>>> data
>>> layer = tf.keras.layers.LayerNormalization(axis=1)
>>> layer(data)
可以看出,不同于批标准化层,层归一化层是将每个batch(也就是每一列)的数据来进行归一化。这里的axis=1表示每一个batch所在的维度为1。
最后,用一张图来表示BatchNormalization函数和LayerNormalization函数的区别: