【问题标题】:Understanding the keras.layers.BatchNormalization computation理解 keras.layers.BatchNormalization 计算
【发布时间】:2019-11-29 00:44:42
【问题描述】:

我正在使用 BatchNormalization 层,我无法完全弄清楚我得到的数值结果。

假设我们将 BatchNormalization 用于计算机视觉。

我们有 4D 张量。

维度包括:批量大小图片高度图片宽度通道

如果我理解正确,BatchNormalization 会做的是:

  1. 在训练时:
    • 对于每个批次,计算平均值 MU 和标准差 SIGMA。这是按通道完成的,并且跨越批次的所有图像的所有行和所有列。
    • 保持MU(比如)和SIGMA(比如SIĜMA)的指数移动平均线所有批次
    • 使用 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 )
    • GAMMABETA 是可训练的参数,它们在训练期间进行了优化
  2. 在推理时:
    • SIĜMA 现在是固定参数,就像 GAMMABETA
    • 应用相同的计算

现在,我的问题来了……

首先,我只对推理时发生的事情感兴趣。 我不关心训练,我认为 SIĜMAGAMMABETA 是固定参数.

我写了一段 python 来测试 (1, 3, 4, 1) 张量上的 BatchNormalization。 由于只有一个频道,SIĜMAGAMMABETA各只有一个元素。 p>

我选择了 MÛ = 0.0SIĜMA = 1.0GAMMA = 1.0BETA = 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


    【解决方案1】:

    我研究了 tensorflow 代码(keras 将其称为后端)。 在batch_normalization的代码中,我读到:

      # 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 中设置 epsilon = 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  ]]]]
    

    【讨论】:

      猜你喜欢
      • 2021-02-23
      • 1970-01-01
      • 1970-01-01
      • 2014-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-13
      • 2018-04-13
      相关资源
      最近更新 更多