• tf.layers.batch_normalization 介绍


    Batch Normalization在TensorFlow中有三个接口调用 (不包括slim、Keras模块中的),分别是:

    通过观察这三个接口的参数列表可以得到一个初步的结论,tf.layers.batch_normalizationtf.contrib.layers.batch_norm可以用来构建待训练的神经网络模型,而tf.nn.batch_normalization一般只用来构建推理模型。简洁起见,本文把神经网络模型分为训练模式和推理模式(包括推理、测试和评估等)。由于tf.contrib包的不稳定性,本文将主要介绍如何使用tf.layers.batch_normalization这个方法在模型中添加BN layer

    tf.layers.batch_normalization()方法

    方法接口如下:

    tf.layers.batch_normalization(
        inputs,
        axis=-1,
        momentum=0.99,
        epsilon=0.001,
        center=True,
        scale=True,
        beta_initializer=tf.zeros_initializer(),
        gamma_initializer=tf.ones_initializer(),
        moving_mean_initializer=tf.zeros_initializer(),
        moving_variance_initializer=tf.ones_initializer(),
        beta_regularizer=None,
        gamma_regularizer=None,
        beta_constraint=None,
        gamma_constraint=None,
        training=False,
        trainable=True,
        name=None,
        reuse=None,
        renorm=False,
        renorm_clipping=None,
        renorm_momentum=0.99,
        fused=None,
        virtual_batch_size=None,
        adjustment=None
    )

    这里有几个重要参数需要注意:

    • axis的值取决于按照input的哪一个维度进行BN,例如输入为channel_last format,即[batch_size, height, width, channel],则axis应该设定为4,如果为channel_first format,则axis应该设定为1.
    • momentum的值用在训练时,滑动平均的方式计算滑动平均值moving_mean和滑动方差moving_variance。 后面做更详细的说明。
    • centerTrue时,添加位移因子beta到该BN层,否则不添加。添加beta是对BN层的变换加入位移操作。注意,beta一般设定为可训练参数,即trainable=True
    • scaleTrue是,添加缩放因子gamma到该BN层,否则不添加。添加gamma是对BN层的变化加入缩放操作。注意,gamma一般设定为可训练参数,即trainable=True
    • training表示模型当前的模式,如果为True,则模型在训练模式,否则为推理模式。要非常注意这个模式的设定,这个参数默认值为False。如果在训练时采用了默认值False,则滑动均值moving_mean和滑动方差moving_variance都不会根据当前batch的数据更新,这就意味着在推理模式下,均值和方差都是其初始值,因为这两个值并没有在训练迭代过程中滑动更新。

    TensorFlow的api文档中对该方法标星出了Note警示如下:



    TensorFlow中模型训练时的梯度计算、参数优化等train_op并没有依赖滑动均值moving_mean和滑动方差moving_variance,则moving_meanmoving_variance不会自动更新,所以必须加入负责更新这些参数的update_ops到依赖中,且应该在执行前向计算结束后、后向计算开始前执行update_ops,所以添加依赖的位置不能出错。实际中,只需要在构建模型代码中,添加完所有BN层之后获取update_ops就不会出错,切记!切记!这是TensorFlow的图计算模式造成的编程影响,在其他深度学习框架中可能会有差别。

    Batch Normalization的作用

    1. 效果
      该方法出自Sergey Ioffe和Christian Szegedy的《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》一文,BN方法到底能否减少Internal Covariate Shift可能还无法下最终结论 (参见《How Does Batch Normalization Help Optimization?》),但的确可以加速训练平稳收敛!所以,BatchNorm成为了居家旅行、训练模型之必备layer。
    2. 计算
      BatchNorm的具体计算/变换如图 (见论文):
       
      Batch Normalizing Transform, applied to activation x over a mini-batch.
      用大白话描述就是,计算出当前batch的每个channel的均值mean,计算出当前batch的每个channel的方差variance,令输入减去均值再除以标准差delta,得到normalized输出x-hat,最后乘以scale参数gamma,加上shift参数beta,得到最终变换后的输出y
    3. BN层在train与inference时的差别
      在训练时,我们可以计算出batch的均值和方差,迭代训练过程中,均值和方差一直在发生变化。但是在推理时,均值和方差是固定的,它们在训练过程中就被确定下来。《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》中给出的确定方式和TensorFlow中存在不同,这里我们介绍TensorFlow中的方式,即采用滑动平均MovingAverage的方法,公式为: moving_average_value * momentum + value * (1 - momentum),其中value为当前batch的平均值或方差,moving_average_value为滑动均值或滑动方差。
      最终,模型训练完毕后,在推理时使用滑动平均值moving_mean和滑动方差moving_variance对feature maps进行变换。
    4. 在模型中的哪些位置插入BN层
      推荐在Conv层或FC层之后,非线性变换激活层之前插入BN层。原因见论文:
       
      where to insert BN layers

    TensorFlow中的BatchNorm实现链

    tf.layers.batch_normalization -->
    tf.layers.BatchNormalization -->
    tf.python.keras.layers.BatchNormalization -->
    keras.backend.normalize_batch_in_training -->
    keras.backend._fused_normalize_batch_in_training -->
    tf.python.ops.nn.fused_batch_norm

    tf.python.keras.layers.BatchNormalization -->
    keras.backend.moving_average_update -->
    tf.python.training import moving_averages.moving_averages

    前半部分主要是对batch_norm的变换,后半部分是对滑动均值的更新。

    后记

    写这篇文章是为了介绍BatchNorm在TensorFlow中的正确使用方法。作者曾因为没有正确传递training参数给tf.layers.batch_normalization,导致模型在训练完成后所有moving_mean都是0,所有moving_variance都是1.0,在读取并量化模型进行batch norm fold时,无法读入这两个参数,提示NoneType错误。经过研究一番才发现是调用tf.layers.batch_normalization方法是必须pass正确的模式。



     
     

    链接:https://www.jianshu.com/p/437fb1a5823e



  • 相关阅读:
    React.memo()使用教程
    React组件什么时候render
    redux-thunk使用教程
    Redux数据持久化
    Mac 中安装 nvm: 切换Node 不同版本
    上传文件类型选择
    Python获取软件安装列表
    Java读取text文件
    负载均衡
    远程调用
  • 原文地址:https://www.cnblogs.com/fclbky/p/12636842.html
Copyright © 2020-2023  润新知