深度學習原理與框架- batch_normalize(歸一化操作)


1. batch_normalize(歸一化操作),公式:傳統的歸一化公式 (number - mean) / std, mean表示均值, std表示標准差

而此時的公式是 scale * (num - mean) / std + beta  #scale 和 beta在計算的過程中會進行不斷的更新,以使得數據可以產生多樣性的分步

即 經過一次卷積層后,進行一次歸一化操作,同時進行一次激活操作

   x = conv_layer(x, [5, 5, 3, 64], 1)
   x = batch_normalize(x, is_training)
   x = tf.nn.relu(x)

歸一化操作,比如x = [32, 32, 64, 128]  第一個32表示寬,第二個32表示長,64表示通道數,128表示feature_map的個數

使用batch_mean, batch_var = tf.nn.moments(x, [0, 1, 2]), 求出前三個通道的均值和標准差,此時的維度為(128, )

在訓練的過程中,因為每次獲得的圖像個數都是batch_size, 因此使用動量平均的方法,來獲得平均的均值和標准差

 使用tf.Variable()構造pop_mean 和 pop_var, trainable = FALSE

使用train_mean = tf.assign(pop_mean, pop_mean*decay + batch_mean*(1-decay))  # pop_mean表示上一次的均值,batch_mean表示當前的x的均值 

使用train_var = tf.assign(pop_var, pop_var*decay + batch_var*(1-decay))  # pop_var表示上一次的標准差, batch_var表示當前的x的標准差

使用with tf.control_dependecies([train_mean, train_var]):  在執行batch_normalization的時候會對train_mean 和 train_var進行操作,更新pop_mean 和 pop_var 

               return tf.nn.batch_normalization(x,  batch_mean, batch_var, beta, scale, epsilon),  

下面是代碼:

def batch_normalize(x, is_training, decay=0.99, epsilon=0.001):
    # 定義訓練過程中的歸一化操作
    def bn_train():
        # 獲得前三個通道的均值和標准差
        batch_mean, batch_var = tf.nn.moments(x, axes=[0, 1, 2])
        # 均值獲得動量平均的均值,即pop_mean * decay + batch_mean * (1-decay)
        train_mean = tf.assign(pop_mean, pop_mean * decay + batch_mean * (1 - decay))
        # 標准差獲得動量平均的標准差,即pop_var * decay + batch_var * (1 - decay)
        train_var = tf.assign(pop_var, pop_var * decay + batch_var * (1 - decay))
        # 使用tf.control_dependencies表示在執行下一步操作前,會進行train_mean和train_var操作,進行參數的更新
        with tf.control_dependencies([train_mean, train_var]):
            # 進行歸一化操作
            return tf.nn.batch_normalization(x, batch_mean, batch_var, beta, scale, epsilon)
    # 定義測試階段的歸一化操作
    def bn_inference():
        # 使用訓練過程中的動量平均的平均值和標准差,作為均值和標准差的輸入
        return tf.nn.batch_normalization(x, pop_mean, pop_var, beta, scale, epsilon)
    # 獲得最后一個通道數,即features的個數
    dim = x.get_shape().as_list()[-1]
    # 構造beta, 即偏差, 用於與歸一化后的數據進行相加操作, 在訓練過程中會進行更新操作
    beta = tf.get_variable(
        name='beta',
        shape=[dim],
        dtype=tf.float32,
        initializer=tf.truncated_normal_initializer(stddev=0.0),
        trainable=True)
    # 構造scale,用於與歸一化后的數據進行相乘操作,在訓練過程中進行更新
    scale = tf.get_variable(
        name='scale',
        shape=[dim],
        dtype=tf.float32,
        initializer=tf.truncated_normal_initializer(stddev=0.1),
        trainable=True)
    # 用於構建動量平均的平均值
    pop_mean = tf.get_variable(
        name='pop_mean',
        shape=[dim],
        dtype=tf.float32,
        initializer=tf.constant_initializer(0.0),
        trainable=False)
    # 用於構建動量平均的標准差
    pop_var = tf.get_variable(
        name='pop_var',
        shape=[dim],
        dtype=tf.float32,
        initializer=tf.constant_initializer(1.0),
        trainable=False)
    # 如果is_training 等於 True,執行bn_train操作,否者執行bn_inference操作
    return tf.cond(is_training, bn_train, bn_inference)

 


免責聲明!

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



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