理解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(比如)和SIGMA(比如SIĜMA)的指数移动平均值
    • 使用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)
    • GAMMABETA是可训练的参数,在训练过程中进行了优化
  • 在推断时:
    • SIĜMA现在是固定参数,就像伽马β
    • 同样的计算也适用
  • 现在,我的问题来了

    首先,我只对推理时发生的事情感兴趣。 我不关心训练,我认为<强> m> ,<强> Si-Ma<<强>,<强>伽玛< /强>和<强>β为固定参数。

    我编写了一段python来测试(1,3,4,1)张量上的批处理规范化。 由于只有一个通道,SIĜMA伽马β各只有一个元素

    我选择了MÛ=0.0SIĜMA=1.0伽马=1.0贝塔=0.0,因此批次标准化没有效果

    代码如下:

    #!/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  ]]]]