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




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM