天天看點

pytorch之BatchNorm

為了解決

Internal Covariate Shift

問題引入,該問題具體表現為:

  • 中間層輸入分布總是變化,增加了模型拟合的難度。
  • 中間層輸入分布會使輸出逐漸靠近激活函數梯度較小的地方,導緻梯度消失

BatchNorm就是在深度神經網絡訓練過程中使得每一層神經網絡的輸入保持相同分布的,在輸入到激活函數之前,對每個mini-batch輸入,做如下處理:

pytorch之BatchNorm

整個的過程如下圖所示,訓練過程為第1-6行,這裡需要注意BN層引入了可訓練參數的 β \beta β和 γ \gamma γ。

假設有K個激活函數,每個

mini-batch

在傳入每個激活函數之前,需要經過一個BN層

inference

的過程為第7-11行,

inference

過程輸出應該完全由輸入決定,使用固定的均值和方差(對于隻有一個測試集,也無法統計均值和方差)。

這裡固定的均值和方差,通過使用對應位置的(某個激活函數之前)所有mini-batch的均值的期望作為均值,所有mini-batch的方差的無偏估計作為方差(第10行)

pytorch之BatchNorm

圖檔來自論文Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

pytorch中包含多種計算BatchNorm方法,下面将一一介紹

BatchNorm1d

y = x − E [ x ] Var ⁡ [ x ] + ϵ ∗ γ + β y=\frac{x-\mathrm{E}[x]}{\sqrt{\operatorname{Var}[x]+\epsilon}} * \gamma+\beta y=Var[x]+ϵ

​x−E[x]​∗γ+β

β \beta β和 γ \gamma γ的初始值為0,1。

傳入BatchNorm1d的參數如下:

  • num_features

    需要進行Normalization的那個次元大小 C C C,輸入的次元可以是 ( N , C ) (N,C) (N,C)和 ( N , C , L ) (N,C,L) (N,C,L)
  • eps

    上述公式中的 ϵ \epsilon ϵ,防止分母為 ,預設為

    1e-5

  • momentum

    用于計算

    inference

    過程的均值和方差(滑動平均),預設為

    0.1

  • affine

    是否使用可訓練參數的 β \beta β和 γ \gamma γ,預設為

    True

  • track_running_stats

    是否記錄上一個

    mini-batch

    的均值

    running_mean

    和方差

    running_var

    。如果是,通過滑動平均的方式得到

    inference

    時的均值和方差;如果不是,則需要在

    inference

    時重新計算。

track_running_stats=True

時,

momentum

使用如下:

running_mean = momentum * running_mean + (1 - momentum) * x_mean
running_var = momentum * running_var + (1 - momentum) * x_var
           

inference

直接使用最後的

running_mean

running_var

作為固定的均值和方差

import torch
import torch.nn as nn
import numpy as np
import math


def validation(x):
    """
    驗證函數
    :param x:
    :return:
    """
    x = np.array(x)
    avg = np.mean(x, axis=0)
    std2 = np.var(x, axis=0)

    x_avg = [[item for item in avg] for _ in range(x.shape[0])]
    x_std = [[math.pow(item, 1 / 2) for item in std2] for _ in range(x.shape[0])]
    x_ = (x - np.array(x_avg)) / np.array(x_std)
    return x_


# With Learnable Parameters
# m = nn.BatchNorm1d(4)
# Without Learnable Parameters
m = nn.BatchNorm1d(4, affine=False)
x = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]]
input = torch.tensor(x, dtype=torch.float)
output = m(input)
print(output)

res = validation(x)
print("valiadation:\n", res)
           

輸出:

tensor([[-1.2247, -1.2247, -1.2247, -1.2247],
        [ 0.0000,  0.0000,  0.0000,  0.0000],
        [ 1.2247,  1.2247,  1.2247,  1.2247]])
valiadation:
 [[-1.22474487 -1.22474487 -1.22474487 -1.22474487]
 [ 0.          0.          0.          0.        ]
 [ 1.22474487  1.22474487  1.22474487  1.22474487]]
           

也可以輸入三維張量:

m = nn.BatchNorm1d(4, affine=False)
x = [[[1, 1], [2, 2], [3, 3], [4, 4]], [[2, 2], [3, 3], [4, 4], [5, 5]], [[3, 3], [4, 4], [5, 5], [6, 6]]]
input = torch.tensor(x, dtype=torch.float)
print(input.size())
output = m(input)
print(output)
           

輸出:

torch.Size([3, 4, 2])
tensor([[[-1.2247, -1.2247],
         [-1.2247, -1.2247],
         [-1.2247, -1.2247],
         [-1.2247, -1.2247]],

        [[ 0.0000,  0.0000],
         [ 0.0000,  0.0000],
         [ 0.0000,  0.0000],
         [ 0.0000,  0.0000]],

        [[ 1.2247,  1.2247],
         [ 1.2247,  1.2247],
         [ 1.2247,  1.2247],
         [ 1.2247,  1.2247]]])
           

BatchNorm2d

同上BatchNorm1d

y = x − E [ x ] Var ⁡ [ x ] + ϵ ∗ γ + β y=\frac{x-\mathrm{E}[x]}{\sqrt{\operatorname{Var}[x]+\epsilon}} * \gamma+\beta y=Var[x]+ϵ

​x−E[x]​∗γ+β

β \beta β和 γ \gamma γ的初始值為0,1。

  • num_features

    需要進行Normalization的那個次元大小 C C C,輸入的次元可以是 ( N , C , H , W ) (N, C, H, W) (N,C,H,W)

BatchNorm3d

同上BatchNorm1d

y = x − E [ x ] Var ⁡ [ x ] + ϵ ∗ γ + β y=\frac{x-\mathrm{E}[x]}{\sqrt{\operatorname{Var}[x]+\epsilon}} * \gamma+\beta y=Var[x]+ϵ

​x−E[x]​∗γ+β

β \beta β和 γ \gamma γ的初始值為0,1。

  • num_features

    需要進行Normalization的那個次元大小 C C C,輸入的次元可以是 ( N , C , D , H , W ) (N, C, D, H, W) (N,C,D,H,W)

繼續閱讀