【发布时间】:2019-11-29 00:44:42
【问题描述】:
我正在使用 BatchNormalization 层,我无法完全弄清楚我得到的数值结果。
假设我们将 BatchNormalization 用于计算机视觉。
我们有 4D 张量。
维度包括:批量大小、图片高度、图片宽度、通道。
如果我理解正确,BatchNormalization 会做的是:
- 在训练时:
- 对于每个批次,计算平均值 MU 和标准差 SIGMA。这是按通道完成的,并且跨越批次的所有图像的所有行和所有列。
- 保持MU(比如MÛ)和SIGMA(比如SIĜMA)的指数移动平均线所有批次
- 使用 MÛ 和 SIĜMA 标准化像素:normalized_pixel = ((input_pixel - MÛ) / sqrt(SIĜMA))
- 一个超参数 epsilon 被添加到 SIĜMA 以防止在训练期间 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各只有一个元素。 p>
我选择了 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)
当我使用 numpy 明确编写计算 ((((input_batch - MU) / math.sqrt(SIGMA)) * GAMMA) + BETA) 时,我得到了预期的结果。
但是,当我使用 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.]]]]
有人能解释一下是怎么回事吗?
谢谢,
朱利安
【问题讨论】:
标签: keras batch-normalization batchnorm