深度學習基礎知識(三)— Normalization 規範化 操作
- 2020 年 1 月 2 日
- 筆記
參考資料:
知乎專欄 – 張俊林 – 深度學習中的Normalization模型 – https://zhuanlan.zhihu.com/p/43200897
知乎專欄 – Juliuszh – 詳解深度學習中的Normalization,BN/LN/WN – https://zhuanlan.zhihu.com/p/33173246
CSDN 部落格 – 夏洛的網 – https://blog.csdn.net/liuxiao214/article/details/81037416
1、引言
Normalization的中文翻譯一般叫做「規範化」,是一種對數值的特殊函數變換方法,也就是說假設原始的某個數值是x,套上一個起到規範化作用的函數,對規範化之前的數值x進行轉換,形成一個規範化後的數值,即

所謂規範化,是希望轉換後的數值 x_bar 滿足一定的特性,至於對數值具體如何變換,跟規範化目標有關,
也就是說f()函數的具體形式,不同的規範化目標導致具體方法中函數所採用的形式不同。
總結性描述:
將越來越偏的分布拉回到標準化的分布,使得激活函數的輸入值落在激活函數對輸入比較敏感的區域,
從而使梯度變大,加快學習收斂速度,避免梯度消失的問題。
2、神經元工作原理
下圖是神經元工作的示意圖:

在介紹深度學習Normalization前,我們先普及下神經元的活動過程。深度學習是由神經網路來體現對輸入數據的函數變換的,而神經網路的基礎單元就是網路神經元,一個典型的神經元對數據進行處理時包含兩個步驟的操作
步驟一:對輸入數據進行線性變換,產生凈激活值

x是輸入,w是權重參數,b是偏置,w和b是需要進過訓練學習的網路參數。
步驟二:套上非線性激活函數,神經網路的非線性能力來自於此,
目前深度學習最常用的激活函數是ReLu函數: x' = ReLu(y)
如此一個神經元就完成了對輸入數據的非線性函數變換。
這裡需要強調下,步驟一的輸出一般稱為凈激活(Net Activation),第二步驟經過激活函數後得到的值為激活值。
3、Normalization的分類
至於深度學習中的Normalization,因為神經網路里主要有兩類實體:神經元或者連接神經元的邊,
所以按照規範化操作涉及對象的不同可以分為兩大類:
① 一類是對第L層每個神經元的 凈激活值 進行Normalization操作,
比如BatchNorm/ LayerNorm/ InstanceNorm/ GroupNorm等方法都屬於這一類;
② 另外一類是對神經網路中連接相鄰隱層神經元之間的邊上的權重進行規範化操作,比如Weight Norm就屬於這一類。
廣義上講,一般機器學習里看到的損失函數裡面加入的對參數的的L1/L2等正則項,本質上也屬於這第二類規範化操作。
L1正則的規範化目標是造成參數的稀疏化,就是爭取達到讓大量參數值取得0值的效果,
而L2正則的規範化目標是有效減小原始參數值的大小。
有了這些規範目標,通過具體的規範化手段來改變參數值,以達到避免模型過擬合的目的。
4、第一類 Normalization
下面先介紹第一類針對神經元的規範化操作方法,這是目前DNN做Normalization最主流的做法。
絕大多數網路目前都是將norm層放在激活函數之前。後續有研究提出的,放在激活函數之後效果更好,這裡還是看最原始的情況。

對於神經元的激活值來說,不論哪種Normalization方法,其規範化目標都是一樣的,
就是將其凈激活值規整為均值為0,方差為1的正態分布。即規範化函數統一都是如下形式:

第一步是將神經元的輸出 規整到均值為0,方差為1的正態分布範圍內;
其中 μ是均值,δ是標準差,它們都是通過 對特定範圍S內的神經元的輸出值 進行統計所得,
根據選取範圍S的不同,可以分為不同的normalize 方式;

第二步的主要目標是,讓每個神經元在訓練過程中學習到對應的兩個調節因子 γ 和 β,對規範到0均值,1方差的值進行微調。
因為經過第一步操作後,Normalization有可能降低神經網路的非線性表達能力,
添加這兩個可學習參數是為了保證模型的表達能力不因為規範化而下降
如果寫成一體的形式,則是如下形式:

4.0 根據集合S的不同的四種常見的 Normalization 方式

將輸入的影像shape記為[N, C, H, W],根據選定的集合S的不同,即進行歸整的神經元的選取方式的不同,有4種常見的Normalization方式如上,分別為 ,Batch Normalization(2015年)、Layer Normalization(2016年)、Instance Normalization(2017年)、Group Normalization(2018年)
4.1.1、 Batch Normalization
在batch方向上,對N H W做歸一化
Batch Normalization 於2015年由 Google 提出,開 Normalization 之先河。
其規範化針對單個神經元進行,利用網路訓練時一個 mini-batch 的數據來計算該神經元 x_i 的均值和方差,
因而稱為 Batch Normalization。

這個圖把四維[N, C, H, W]輸入數據以三維的方式畫出來了,即把空間維度 H,W融合成一個維度,看起來可能稍微有點不好理解,沒關係,我們可以通過深色格子的數量來分析。
我們可以看到,N那個方向上,深色格子是取滿了的,即對mini-batch的N個實例都考慮到了,而空間維度H,W(豎著的方向)也是全部取滿了的,即對輸入影像的H * W的所有像素點都考慮到了,唯獨通道方向C只取了1個格子,
這就說明通道方向上,是分開的,每次只考慮1個通道。
舉個例子,如果如果我們有8張大小為256*256的RGB彩色圖片,組合一個batch,得到[8, 3, 256, 256 ] 進行Batch Norm操作, 那麼具體來說就是:
統計8張圖片的 R 通道上的像素點做歸一化,即考慮範圍為8*1*256*256個像素點;
統計8張圖片的 G 通道上的像素點做歸一化,即考慮範圍為8*1*256*256個像素點;
統計8張圖片的 B 通道上的像素點做歸一化,即考慮範圍為8*1*256*256個像素點;

這個圖片可以看作正在對 8張圖片(實例)的 R 通道上的 所有像素點做歸一化
這就是所謂的對NHW做歸一化,即分開通道而統計影像(Batch方向上)來統計像素點。
BN 比較適用的場景是:每個 mini-batch 比較大,數據分布比較接近。
在進行訓練之前,要做好充分的 shuffle. 否則效果會差很多。
4.1.2、Batch Norm的四大罪狀:
局限1:如果Batch Size太小,則BN效果明顯下降。
實驗表明當BatchSize小於8的時候開始對分類效果有明顯負面影響。
局限2:對於有些像素級圖片生成任務來說,BN效果不佳;
對於圖片分類等任務,只要能夠找出關鍵特徵,就能正確分類,這算是一種粗粒度的任務,在這種情形下通常BN是有積極效果的。但是對於有些輸入輸出都是圖片的像素級別圖片生成任務,比如圖片風格轉換等應用場景,使用BN會帶來負面效果,
這很可能是因為在Mini-Batch內多張無關的圖片之間計算統計量,弱化了單張圖片本身特有的一些細節資訊。
局限3:RNN等動態網路使用BN效果不佳且使用起來不方便
對於RNN來說,儘管其結構看上去是個靜態網路,但在實際運行展開時是個動態網路結構,因為輸入的Sequence序列是不定長的,這源自同一個Mini-Batch中的訓練實例有長有短。對於類似RNN這種動態網路結構,BN使用起來不方便,因為要應用BN,那麼RNN的每個時間步需要維護各自的統計量,而Mini-Batch中的訓練實例長短不一,這意味著RNN不同時間步的隱層會看到不同數量的輸入數據,而這會給BN的正確使用帶來問題。假設Mini-Batch中只有個別特別長的例子,那麼對較深時間步深度的RNN網路隱層來說,其統計量不方便統計而且其統計有效性也非常值得懷疑。另外,如果在推理階段遇到長度特別長的例子,也許根本在訓練階段都無法獲得深層網路的統計量。綜上,在RNN這種動態網路中使用BN很不方便,而且很多改進版本的BN應用在RNN效果也一般。
局限4:訓練時和驗證/測試時統計量不一致
對於BN來說,採用Mini-Batch內實例來計算統計量,這在訓練時沒有問題,但是在模型訓練好之後,在線推理(online inference)的時候會有麻煩。因為在線推理或預測的時候,是單實例的,不存在Mini-Batch,所以就無法獲得BN計算所需的均值和方差,一般解決方法是採用訓練時刻記錄的各個Mini-Batch的統計量的數學期望,以此來推算全局的均值和方差,在線推理時採用這樣推導出的統計量。雖說實際使用並沒大問題,但是確實存在訓練和推理時刻統計量計算方法不一致的問題。
上面所列BN的四大罪狀,表面看是四個問題,其實深入思考,都指向了幕後同一個黑手,這個隱藏在暗處的黑手是誰呢?就是BN要求計算統計量的時候必須在同一個Mini-Batch內的實例之間進行統計,因此形成了Batch內實例之間的相互依賴和影響的關係。如何從根本上解決這些問題?一個自然的想法是:把對Batch的依賴去掉,轉換統計集合範圍。在統計均值方差的時候,不依賴Batch內數據,只用當前處理的單個訓練數據來獲得均值方差的統計量,這樣因為不再依賴Batch內其它訓練數據,那麼就不存在因為Batch約束導致的問題。在BN後的幾乎所有改進模型都是在這個指導思想下進行的。
Pytorch 實現(2d情況):https://pytorch.org/docs/stable/nn.html#batchnorm2d
torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
其中的參數 affine=True, 就是設置 對應的兩個調節因子 γ 和 β,
track_running_stats=True, 就是在訓練時 追蹤 並統計各個batch的統計量(pytorch稱之為:running_mean和running_var),如上面局限4談到的
momentum=0.1 也是用於統計 running_mean 和 running_var 的一個指數衰減量
4.2、Layer Normalization
在通道方向上,對CHW歸一化

我們可以看到,N那個方向上,深色格子是只取了1個,表示現在只考慮一個輸入影像(實例),而空間維度H,W(豎著的方向)也是全部取滿了的,即對輸入影像的H*W的所有像素點都考慮到了,通道方向C現在是取滿了的,這就說明通道方向上,是考慮了所有通道的。
仍然以我們的8張大小為256*256的RGB彩色圖片,組合一個batch舉例,得到[8, 3, 256, 256 ] 進行Layer Norm操作, 那麼具體來說就是:
統計第1張圖片的,R、G、B 3個通道上的像素點做歸一化,即考慮範圍為1*3*256*256個像素點;
統計第 i 張 圖片······
統計第8張圖片的,R、G、B 3個通道上的像素點做歸一化,即考慮範圍為1*3*256*256個像素點;

這張圖片可以看作是正在對第一張圖片的 R、G、B三個通道上的像素點做歸一化
這就是所謂的對CHW做歸一化,即分開影像(實例)而統計通道(Layer方向上)來統計像素點。
前文有述,BN在RNN中用起來很不方便,而Layer Normalization這種在同隱層內計算統計量,而不依賴batch size大小 的模式就比較符合RNN這種動態網路,目前在RNN中貌似也只有LayerNorm相對有效,但Layer Normalization目前看好像也只適合應用在RNN場景下,在CNN等環境下效果是不如BatchNorm或者GroupNorm等模型的。
Pytorch實現: https://pytorch.org/docs/stable/nn.html#layernorm,
torch.nn.LayerNorm(normalized_shape, eps=1e-05, elementwise_affine=True)
4.3、Instance Normalization
僅對HW做歸一化,

我們可以看到,N那個方向上,深色格子是只取了1個,表示現在只考慮一個輸入影像(實例),而空間維度H,W(豎著的方向)也是全部取滿了的,即對輸入影像的H*W的所有像素點都考慮到了,通道方向C現在是只取了1個的,這就說明通道方向上只是考慮了1個通道的。
仍然以我們的8張大小為256*256的RGB彩色圖片,組合一個batch舉例,得到[8, 3, 256, 256 ] 進行Layer Norm操作, 那麼具體來說就是:
統計第1張圖片的,R 通道上的像素點做歸一化,即考慮範圍為1*1*256*256個像素點;
統計第1張圖片的,G 通道上的像素點做歸一化,即考慮範圍為1*1*256*256個像素點;
統計第1張圖片的,B 通道上的像素點做歸一化,即考慮範圍為1*1*256*256個像素點;
後面依次統計第 i 張 圖片······

這張圖片可以看作是 在對第 i 張圖片(實例)的 B 通道上的 所有像素點做歸一化
這就是所謂的僅對HW做歸一化
也就是既不像BatchNorm那樣考慮一個batch內的多個實例,也不像Layer Norm那樣考慮layer方向上的多個通道,它現在只限制在單個實例 單個通道上操作!
那麼實際上,我們想一下卷積操作就會發現,這其實就是在對單個神經元的輸出做歸一化,因為單個神經元的卷積結果,就是 1個實例中的1個通道上的內容
影像風格化中,生成結果主要依賴於某個影像實例,所以對整個batch歸一化不適合影像風格化中,因而對HW做歸一化。可以加速模型收斂,並且保持每個影像實例之間的獨立。所以很多GAN網路中其實比較喜歡用InstanceNorm來進行操作。
而且往往這些網路 BatchSize的大小是設置成1的,也就是每次都只有1個實例進行前傳。那麼這樣可能會感覺到,如果把BatchNormalization中的BatchSize改為1,那豈不是就是InstanceNormlization了?
從數學運算上來看,二者應該是一樣的,因為BatchSize等於1時,此時考慮的集合S範圍內的神經元是一樣的。
但是可能在深度學習框架中的具體實現會有差別。
比如在測試的時候,我們通常都是輸入的單個樣例,也就是BatchSize在測試階段設置為1。
①如果訓練階段用的是BatchNorm,往往BatchSize都大於1,考慮的是一個batch內的實例的統計特性。所以在測試的時候,往往不計算測試集/驗證集的單一輸入實例的歸一化參數,而是使用訓練階段保存下來的歸一化參數:均值μ,標準差δ。
更進一步,我們在訓練階段使用BatchNorm的時候,每一個mini-Batch計算完歸一化參數之後,會使用指數加權平均 來進行累加,通常會有一個momentum參數,默認值為0.1,即當前mini-batch的統計值佔比0.1,加上歷史積累的mini-batch的統計值佔比0.9。所以最後訓練完成後保存下來的模型中的 均值μ和 標準差δ 是對所有mini-batch的一個加權平均統計值,可以看作是照顧到了所有的訓練集數據。
②如果訓練階段用的就是InstanceNorm,本身的BatchSize在訓練時就是1,即只考慮當前輸入實例的影響。那麼在測試時,也就需要即時計算 測試集/驗證集 的單一輸入實例的歸一化參數。並不使用訓練階段保存的歸一化參數,而且訓練階段也不需要保存歸一化參數,因為每個batch都是獨立的。
Pytorch實現(2d情況):https://pytorch.org/docs/stable/nn.html#instancenorm2d
torch.nn.InstanceNorm2d(num_features, eps=1e-05, momentum=0.1, affine=False, rack_running_stats=False)
可以看到,pytorch實現時,affine=False,即不設置 兩個調節因子 γ 和 β,
rack_running_stats=False, 也不追蹤和統計 各個批次的統計量
也就是說,並不是單純的把batchnorm2d的batchsize改成1就完全等價
4.4、Group Normalization
將channel分組,然後再做歸一化

是Facebook何凱明研究組2017年提出的。這是一種介於前面的Layer Norm 和Instance Norm 之間的Norm操作,我們可以看到,batch方向上仍然只取1個,H*W方向上取滿,通道方向上,C現在既不是取滿(Layer Norm的操作),也不是只取1個通道(Instance Norm的操作),而是取了介於二者之間的幾個通道。相當於把這幾個通道分成了一組!
上面舉彩色圖片的例子這裡稍微修改一下,假設我們在彩色圖片後面再加兩個通道,表示每個像素點的坐標,即現在每個像素點的值為(r, g, b, x, y),那麼這時影像就是5個通道的影像了,所謂group norm, 可以理解為:
對某一張圖片,我對其R,G,B 3個通道上的像素點做歸一化,共有1*3*256*256個像素點;
然後我再對剩下的 X,Y 2個通道上的像素點做歸一化,共1*2*256*256個像素點;
這就是所謂通道分組的概念,我這個例子中,我分組的依據是,R、G、B這3個通道是顏色資訊,它們之間關係更大一些; 而後兩個通道X,Y是表示位置資訊的,它們關係要大一些,所以我這麼分組。 這只是我這裡舉了個例子而已,為了說明通道分組的概念。

這張圖片也闡述了通道分組的意思。
Pytorch實現:https://pytorch.org/docs/stable/nn.html#groupnorm
torch.nn.GroupNorm(num_groups, num_channels, eps=1e-05, affine=True)
5、第二類Normalization
上面講的第一類,其實都是對神經元的輸出進行規範化,只是選取的神經元的範圍S不同,或者說選的經過卷積之後的特徵圖的數據的區域不同,其實這不同的區域就是對應著前面不同的神經元的輸出。
這裡講另一種方式:
Weight Normalization —— 參數規範化, 則另闢蹊徑,將規範化應用於線性變換函數的權重 w ,這就是 WN 名稱的來源。
我瀏覽過很多寫WN的文章,知乎上這篇文章我覺得是寫的比較好的:https://zhuanlan.zhihu.com/p/55102378,裡面的推導過程是比較詳細的。
這裡我就不重複了,而且我也覺得讓我重新推導寫出來也不會超過這篇文章,所以我這裡就簡單的說幾個結論性內容:
具體而言,WN 提出的方案是,將權重向量 w 分解為 向量方向 v 和向量模 g 兩部分。後使用SGD分別優化這兩個參數。

WN也是和樣本量無關的,所以可以應用在batchsize較小以及RNN等動態網路中;另外BN使用的基於mini-batch的歸一化統計量代替全局統計量,相當於在梯度計算中引入了雜訊。而WN則沒有這個問題,所以在生成模型,強化學習等雜訊敏感的環境中WN的效果也要優於BN。
WN沒有一如額外參數,這樣更節約顯示記憶體。同時WN的計算效率也要優於要計算歸一化統計量的BN。
Weight Normalization的優點:
更快的收斂速度;
更強的學習率魯棒性;
可以應用在RNN等動態網路中;
對雜訊更不敏感,更適用在GAN,RL等場景中