我正在使用BatchNormalization层,但我无法弄清楚我得到的数值结果。
让我们考虑一下我们将 BatchNormalization 用于计算机视觉。
我们有 4D 张量。
维度是:批量大小、图像高度、图像宽度、通道。
如果我理解正确,BatchNormalization 会做的是:
- 训练时:
- 对于每个批次,计算平均MU和标准偏差SIGMA。这是按通道完成的,并且跨越批次的所有图像的所有行和所有列。
- 在所有批次中保持MU(例如MÛ)和SIGMA(例如SIĜMA )的指数移动平均值
- 使用MÛ和SIĜMA归一化像素:normalized_pixel = ((input_pixel - MÛ) / sqrt(SIĜMA))
- 如果SIĜMA在训练期间的某一时刻变为空,则将超参数epsilon添加到SIĜMA以防止除以零: normalized_pixel = ((input_pixel - MÛ) / sqrt(SIĜMA + epsilon))
- 使用缩放参数GAMMA和偏移参数BETA重新缩放归一化像素:output_pixel = ((GAMMA x normalized_pixel) + BETA)
- GAMMA和BETA是可训练的参数,它们在训练期间进行了优化
- 在推理时:
- MÛ和SIĜMA现在是固定参数,就像GAMMA和BETA
- 相同的计算适用
现在,我的问题来了……
首先,我只对推理时发生的事情感兴趣。我不关心训练,我认为MÛ、SIĜMA、GAMMA和BETA是固定参数。
我写了一段 python 来测试(1, 3, 4, 1)张量上的 BatchNormalization。由于只有一个通道,因此 MÛ、SIĜMA、GAMMA和BETA各只有 1 个元素。
我选择了MÛ = 0.0,SIĜMA = 1.0,GAMMA = 1.0和BETA = 0.0,所以 BatchNormalization 没有效果。
这是代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy
import keras
import math
input_batch = numpy.array(
[[
[[ 1.0], [ 2.0], [ 3.0], [ 4.0]],
[[ 5.0], [ 6.0], [ 7.0], [ 8.0]],
[[ 9.0], [10.0], [11.0], [12.0]]
]],
dtype=numpy.float32
)
MU = 0.0
SIGMA = 1.0
GAMMA = 1.0
BETA = 0.0
input_layer = keras.layers.Input(
shape = (
None,
None,
1
)
)
BatchNormalization_layer = keras.layers.BatchNormalization(
axis=-1,
#epsilon=0.0,
center=True,
scale=True
)(
input_layer
)
model = keras.models.Model(
inputs = [input_layer],
outputs = [BatchNormalization_layer]
)
model.layers[1].set_weights(
(
numpy.array([GAMMA], dtype=numpy.float32),
numpy.array([BETA], dtype=numpy.float32),
numpy.array([MU], dtype=numpy.float32),
numpy.array([SIGMA], dtype=numpy.float32),
)
)
print model.predict(input_batch)
print ((((input_batch - MU) / math.sqrt(SIGMA)) * GAMMA) + BETA)
当我((((input_batch - MU) / math.sqrt(SIGMA)) * GAMMA) + BETA)
使用 numpy 明确编写计算时,我得到了预期的结果。
但是,当我使用 keras.layers.BatchNormalization 层执行计算时,我得到了类似的结果,只是存在某种舍入误差或不精确:
Using TensorFlow backend.
[[[[ 0.9995004]
[ 1.9990008]
[ 2.9985013]
[ 3.9980016]]
[[ 4.997502 ]
[ 5.9970026]
[ 6.996503 ]
[ 7.996003 ]]
[[ 8.995503 ]
[ 9.995004 ]
[10.994504 ]
[11.994005 ]]]]
[[[[ 1.]
[ 2.]
[ 3.]
[ 4.]]
[[ 5.]
[ 6.]
[ 7.]
[ 8.]]
[[ 9.]
[10.]
[11.]
[12.]]]]
当我使用 MU*、SIGMA*、GAMMA 和 BETA 的值时,输出会受到预期的影响,所以我相信我正确地向层提供了参数。
我还尝试将图层的超参数 epsilon 设置为 0.0。它会稍微改变结果,但不能解决问题。
Using TensorFlow backend.
[[[[ 0.999995 ]
[ 1.99999 ]
[ 2.999985 ]
[ 3.99998 ]]
[[ 4.999975 ]
[ 5.99997 ]
[ 6.9999647]
[ 7.99996 ]]
[[ 8.999955 ]
[ 9.99995 ]
[10.999945 ]
[11.99994 ]]]]
[[[[ 1.]
[ 2.]
[ 3.]
[ 4.]]
[[ 5.]
[ 6.]
[ 7.]
[ 8.]]
[[ 9.]
[10.]
[11.]
[12.]]]]
有人可以解释发生了什么吗?
谢谢,
朱利安