文章目錄
- 前言
- 一、BN
- 二、LN
- 三、IN
- 四、GN
前言
歸一化層,目前主要有這幾個方法,
1、Batch Normalization(2015)
2、Layer Normalization(2016)
3、Instance Normalization(2017)
4、Group Normalization(2018)
區別:

將輸入的影像shape記為[N, C, H, W],這幾個方法主要的區別就是在:
Batch Norm是在batch上,對NHW做歸一化,就是對每個單一通道輸入進行歸一化,這樣做對小batchsize效果不好;
Layer Norm在通道方向上,對CHW歸一化,就是對每個深度上的輸入進行歸一化,主要對RNN作用明顯;
Instance Norm在影像像素上,對HW做歸一化,對一個影像的長寬即對一個像素進行歸一化,用在風格化遷移;
Group Norm將channel分組,有點類似于LN,只是GN把channel也進行了劃分,細化,然后再做歸一化;
Switchable Norm是將BN、LN、IN結合,賦予權重,讓網路自己去學習歸一化層應該使用什么方法,
以上摘自https://blog.csdn.net/qq_41997920/article/details/89945972?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163927665316780265454206%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163927665316780265454206&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-1-89945972.first_rank_v2_pc_rank_v29&utm_term=Layer+Norm%EF%BC%8CGroup+Norm&spm=1018.2226.3001.4187
一、BN

我們在對資料訓練之前會對資料集進行歸一化,歸一化的目的歸一化的目的就是使得預處理的資料被限定在一定的范圍內(比如[0,1]或者[-1,1]),從而偏差大的樣本資料導致的不良影響,而且資料如果偏差大,我們設定學習率就要很小,這樣會降低訓練速度;另外統一資料規模可以讓機器更容易學習,
雖然輸入層的資料,已經歸一化,后面網路每一層的輸入資料的分布一直在發生變化,前面層訓練引數的更新將導致后面層輸入資料分布的變化,必然會引起后面每一層輸入資料分布的改變,而且,網路前面幾層微小的改變,后面幾層就會逐步把這種改變累積放大,訓練程序中網路中間層資料分布的改變稱之為:“Internal Covariate Shift(內部協方差漂移)”,BN的提出,就是要解決在訓練程序中,中間層資料分布發生改變的情況,所以就引入了BN的概念,來消除這種影響,
另外,如果在每一層加入激活函式,以sigmoid為例,當橫軸趨向于無窮大時梯度會消失,用BN層可以將偏差大的資料拉回0附近的梯度敏感地帶,所以在每次傳入網路的資料每一層的網路都進行一次BN,將資料拉回正態分布,這樣做使得資料分布一致且避免了梯度消失,
此外,internal corvariate shift和covariate shift是兩回事,前者是網路內部,后者是針對輸入資料,比如我們在訓練資料前做歸一化等預處理操作,
需要注意的是在使用小batch-size時BN會破壞性能,當具有分布極不平衡二分類任務時也會出現不好的結果,分布不均的分類任務也會出現這種情況,因為BN計算每一個batch的期望和標準差,我們希望的是計算出來的期望和標準差能代表整個資料上的分布規律,如果小的batch-size歸一化,可能會和整體差別較大,均值和方差不足以代替整個資料分布,
BN實際使用時需要計算并且保存某一層神經網路batch的均值和方差等統計資訊,對于對一個固定深度的前向神經網路(DNN,CNN)使用BN,很方便;但對于RNN來說,sequence的長度是不一致的,換句話說RNN的深度不是固定的,不同的time-step需要保存不同的statics特征,可能存在一個特殊sequence比其他sequence長很多,這樣training時,計算很麻煩,
總結:
1、有BN層時,學習率不一定設定的非常小;
2、梯度消失可以被解決;
3、初始化對引數的影響小了,因為如果初始化偏差較大,經過BN也會拉回一個正常范圍,
4、有解決過擬合的效果,假設有噪聲也會被歸一化,
pytorch實作torch.nn.BatchNorm1d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
num_features: 來自期望輸入的特征數,該期望輸入的大小為’batch_size x num_features [x width]’
eps: 為保證數值穩定性(分母不能趨近或取0),給分母加上的值,默認為1e-5,
momentum: 動態均值和動態方差所使用的動量,默認為0.1,
affine: 布林值,當設為true,給該層添加可學習的仿射變換引數,
track_running_stats:布林值,當設為true,記錄訓練程序中的均值和方差;
手動實作:
x_shape:[B, C, H, W],則計算第0、2、3軸的方差和均值,
import numpy as np
def Batchnorm(x, gamma, beta, bn_param):
# x_shape:[B, C, H, W]
running_mean = bn_param['running_mean']
running_var = bn_param['running_var']
results = 0.
eps = 1e-5
x_mean = np.mean(x, axis=(0, 2, 3), keepdims=True)
x_var = np.var(x, axis=(0, 2, 3), keepdims=True0)
x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
results = gamma * x_normalized + beta
# 因為在測驗時是單個圖片測驗,這里保留訓練時的均值和方差,用在后面測驗時用
running_mean = momentum * running_mean + (1 - momentum) * x_mean
running_var = momentum * running_var + (1 - momentum) * x_var
bn_param['running_mean'] = running_mean
bn_param['running_var'] = running_var
return results, bn_param
二、LN
與BN不同的是,LN對每一層的所有神經元進行歸一化;

LN中同層神經元輸入擁有相同的均值和方差,不同的輸入樣本有不同的均值和方差;
BN中則針對不同神經元輸入計算均值和方差,同一個batch中的輸入擁有相同的均值和方差,
LN不依賴于batch的大小和輸入sequence的深度,因此可以用于batchsize為1和RNN中對邊長的輸入sequence的normalize操作,
pytorchtorch.nn.LayerNorm(normalized_shape, eps=1e-05, elementwise_affine=True)
normalized_shape: 輸入尺寸
[?×normalized_shape[0]×normalized_shape[1]×…×normalized_shape[?1]]
eps: 為保證數值穩定性(分母不能趨近或取0),給分母加上的值,默認為1e-5,
elementwise_affine: 布林值,當設為true,給該層添加可學習的仿射變換引數,
手動實作:
x_shape:[B, C, H, W],則計算第1、2、3軸的方差和均值,
def Layernorm(x, gamma, beta):
# x_shape:[B, C, H, W]
results = 0.
eps = 1e-5
x_mean = np.mean(x, axis=(1, 2, 3), keepdims=True)
x_var = np.var(x, axis=(1, 2, 3), keepdims=True0)
x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
results = gamma * x_normalized + beta
return results
三、IN

BN注重對每一個batch進行歸一化,保證資料分布的一致,因為判別模型中的結果取決與資料的整體分布,在影像風格中,生成結果主要依賴某個影像實體,所以此時對整個batch歸一化不適合了,需要對但像素進行歸一化,可以加速模型的收斂,并且保持每個影像實體之間的獨立性!
? 在目前的GAN和style transfer的任務中,目前的IN norm要好于BN,IN主要用于對單張影像的資料做處理,而BN主要是對Bacth的資料做處理,由于BN在訓練時每個batch的均值和方差會由于shuffle都會改變,所以可以理解為一種資料增強,而IN可以理解為對資料做一個歸一化的操作,
?? 換句話說,BN的計算是要受其他樣本影響的,由于每個batch的均值和標準差不穩定,對于單個資料而言,相對于是引入了噪聲,但在分類這種問題上,結果和資料的整體分布有關系,因此需要通過BN獲得資料的整體分布,而instance norm的資訊都是來自于自身的圖片,相當于對全域資訊做了一次整合和調整,在影像轉換這種問題上,BN獲得的整體資訊不會帶來任何收益,帶來的噪聲反而會榷訓實體之間的獨立性,
?? 總而言之,對于分類這種high level的問題,使用BN優于IN, 對于Low level問題,IN優于BN,
??
pytorch實作:torch.nn.InstanceNorm1d(num_features, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)
num_features: 來自期望輸入的特征數,該期望輸入的大小為’batch_size x num_features [x width]’
eps: 為保證數值穩定性(分母不能趨近或取0),給分母加上的值,默認為1e-5,
momentum: 動態均值和動態方差所使用的動量,默認為0.1,
affine: 布林值,當設為true,給該層添加可學習的仿射變換引數,
track_running_stats:布林值,當設為true,記錄訓練程序中的均值和方差;
手動實作:
def Instancenorm(x, gamma, beta):
# x_shape:[B, C, H, W]
results = 0.
eps = 1e-5
x_mean = np.mean(x, axis=(2, 3), keepdims=True)
x_var = np.var(x, axis=(2, 3), keepdims=True0)
x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
results = gamma * x_normalized + beta
return results
四、GN

Group Normalization(GN)是針對Batch Normalization(BN)在batch size較小時錯誤率較高而提出的改進演算法,因為BN層的計算結果依賴當前batch的資料,當batch size較小時(比如1、2、4這樣),該batch資料的均值和方差的代表性較差,因此對最后的結果影響也較大, GN將channel方向分group,然后每個group內做歸一化,算(C//G)HW的均值,這樣與batchsize無關,不受其約束,
pytorch實作:torch.nn.GroupNorm(num_groups, num_channels, eps=1e-05, affine=True)
num_groups:需要劃分為的groups
num_features: 來自期望輸入的特征數,該期望輸入的大小為’batch_size x num_features [x width]’
eps: 為保證數值穩定性(分母不能趨近或取0),給分母加上的值,默認為1e-5,
momentum: 動態均值和動態方差所使用的動量,默認為0.1,
affine: 布林值,當設為true,給該層添加可學習的仿射變換引數,
手動實作:
def GroupNorm(x, gamma, beta, G=16):
# x_shape:[B, C, H, W]
results = 0.
eps = 1e-5
x = np.reshape(x, (x.shape[0], G, x.shape[1]/16, x.shape[2], x.shape[3]))
x_mean = np.mean(x, axis=(2, 3, 4), keepdims=True)
x_var = np.var(x, axis=(2, 3, 4), keepdims=True0)
x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
results = gamma * x_normalized + beta
return results
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/379541.html
標籤:其他
