理解keras.layers.BatchNormalization计算
我正在玩批量标准化层,我不能完全理解我得到的数值结果理解keras.layers.BatchNormalization计算,keras,batch-normalization,batchnorm,Keras,Batch Normalization,Batchnorm,我正在玩批量标准化层,我不能完全理解我得到的数值结果 我们考虑在计算机视觉中使用BonnrnMul归化。 我们有4D张量 尺寸为:批量大小,图像高度,图像宽度,通道 如果我理解正确,BatchNormalization将做的是: 培训时: 对于每批,计算平均值MU和标准偏差SIGMA。这是按通道完成的,并访问批处理的所有图像的所有行和所有列 在所有批次中保持MU(比如MÛ)和SIGMA(比如SIĜMA)的指数移动平均值 使用MÛ和SIĜMA对像素进行规格化:normalized_pixel=(
我们考虑在计算机视觉中使用BonnrnMul归化。
我们有4D张量 尺寸为:批量大小,图像高度,图像宽度,通道 如果我理解正确,BatchNormalization将做的是:- 对于每批,计算平均值MU和标准偏差SIGMA。这是按通道完成的,并访问批处理的所有图像的所有行和所有列
- 在所有批次中保持MU(比如MÛ)和SIGMA(比如SIĜMA)的指数移动平均值
- 使用MÛ和SIĜMA对像素进行规格化:normalized_pixel=((输入_pixel-MÛ)/sqrt(SIĜMA))
- 如果在训练期间SIĜMA在某一点变为空,则将超参数epsilon添加到SIĜMA以防止被零除:normalizedĜu pixel=((输入Ĝpixel-MÛ)/sqrt(SIĜMA+epsilon))
- 使用缩放参数GAMMA和偏移参数BETA重新缩放标准化像素:输出像素=((GAMMA x标准化像素)+BETA)
- GAMMA和BETA是可训练的参数,在训练过程中进行了优化
- MÛ和SIĜMA现在是固定参数,就像伽马和β
- 同样的计算也适用
#!/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.]]]]
有人能解释一下发生了什么事吗
谢谢
Julien我深入研究了tensorflow代码(keras称之为后端)。 在batch_规范化代码中,我读到:
# Set a minimum epsilon to 1.001e-5, which is a requirement by CUDNN to
# prevent exception (see cudnn.h).
min_epsilon = 1.001e-5
epsilon = epsilon if epsilon > min_epsilon else min_epsilon
解释为什么在keras中设置ε=0.0不起作用
在脚本中考虑epsilon时,我得到了正确的结果
((((input_batch - MU) / math.sqrt(SIGMA + EPSILON)) * GAMMA) + BETA)
Using TensorFlow backend.
[[[[ 0.99503714]
[ 1.9900743 ]
[ 2.9851115 ]
[ 3.9801486 ]]
[[ 4.975186 ]
[ 5.970223 ]
[ 6.96526 ]
[ 7.960297 ]]
[[ 8.955335 ]
[ 9.950372 ]
[10.945409 ]
[11.940446 ]]]]
[[[[ 0.99503714]
[ 1.9900743 ]
[ 2.9851115 ]
[ 3.9801486 ]]
[[ 4.975186 ]
[ 5.970223 ]
[ 6.96526 ]
[ 7.960297 ]]
[[ 8.955335 ]
[ 9.950372 ]
[10.945409 ]
[11.940446 ]]]]