在深度學習中,使用歸一化層成為了很多網路的標配,最近,研究了不同的歸一化層,如BN,GN和FRN,接下來,介紹一下這三種歸一化演算法,
BN層
BN層是由谷歌提出的,其相關論文為《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》,即Inception v2的主要思想,大家也可以看回我以前的博客,關于這個BN層的介紹,
BN層的提出,主要解決的一個問題是Internal Covariate Shift,在BN層提出以前,是很難訓練一個深層次的網路的,其主要難點是每層的資料分布均會發生變化,使得神經元需要去學習新的分布,導致模型訓練緩慢、難以收斂,因此,作者借助了白化的思想,將每層資料都歸一化成均值為0、方差為1的分布,如公式(1)所示,即減去均值、除以方差,這樣就能是每層的資料分布不會發生過大變化,從而導致模型容易訓練,
$$\hat{x}^{(k)}=\frac{x^{(k)}-E[x^{(k)}]}{\sqrt{Var(x^{(k)})}} \tag{1}$$
但同時也引入了一個問題,我們將資料強行的歸一化,會導致原始的資料分布遭到破壞,特征的表達能力就會下降,所以,BN層的核心亮點是重構變換,引入兩個可學習的變數$\gamma $和$\beta $,分別表示縮放與偏差,如公式(2)所示,模型通過學習$\gamma $和$\beta $,來重構還原歸一化的分布,當$\gamma ^{(k)}=\sqrt{Var[x^{(k)}]}$和$\beta ^{(k)}=E[x^{(k)}]$時,就能完全還原原來的分布了,
$$y^{(k)}=\gamma ^{(k)}\hat {x}^{(k)}+\beta ^{(k)} \tag{2}$$
因此,BN層的演算法如下圖所示,首先計算該神經元輸入的均值$\mu _B $和方差$\sigma ^2_B $,再對資料進行標準化,得到$\hat{x}_i$,最后對進行重構還原,得到$y_i$,所以,BN層的輸出應該是$y_i$,而不是$\hat{x}_i$,

那么對于一個深度神經網路而言,具體又是如何操作的呢?在模型訓練中,我們一般都是使用一個batch size來對模型進行單次優化,假設某一BN層的輸入為$x_i$,其shape為$[B,C,H,W]$,分別表示batch、channels、特征圖的高和寬,一個神經元即對應一個通道,需要對$B\times H\times W$個值進行計算均值和方差,然后進行重構變換,在這一層中,需要計算$C$個通道,每個通道會生成一個$\gamma $,一個$\beta $,一個$\mu _B $和一個$\sigma ^2_B $,對于不同的batch,其$\mu _B $和一個$\sigma ^2_B $都是不一樣的,$\mu _B $和$\sigma ^2_B $對應的是當前batch的均值與方差,而$\gamma $和$\beta $對應的是該通道(神經元)的縮放和偏移,
而在測驗中,由于輸入只有一個樣本,如果用著一個樣本來進行估計均值與方差,會導致巨大的偏差,所以,測驗階段,$\gamma $和$\beta $是使用當前通道的縮放和偏移,是網路學習來的引數;而該神經元的均值與方差使用的是所有訓練樣本在該神經元上的均值與方差的無偏估計,
具體要如何操作呢?在訓練階段,會把所有均值和方差都保存下來,最后再計算一個無偏估計即可,對于Pytoch而言,同通過公式(3)來保存以往的均值和方差,其中,$\hat{x}_\text{new}$是新的均值或者方差,$momentum$是動量,與優化器的動量不一樣,這里默認是0.1,$\hat{x}$是上一次的估計量(均值或者方差),$x_t$是當前的估計量(均值或者方差),通過這樣的計算,將均值和方差保存下來用于測驗階段,但是,這個保存下來的均值和方差是用于測驗階段的,訓練時用的是當前batch的均值和方差,
$$\hat{x}_\text{new} = (1 - \text{momentum}) \times \hat{x} + \text{momentum} \times x_t \tag{3}$$
所以,一個BN層,會保存下來$4C$個引數,分別是$C$個$\gamma $,$C$個$\beta $,$C$個$\mu _B $和$C$個$\sigma ^2_B $,
BN層有很多優點,例如加速訓練速度、緩解梯度彌散等,但可以從上述分析看出,BN層與batch size密切關系,如果batch size過小,會受到過多干擾,在很多大型網路中,如語意分割,受到顯存的限制,batch size可能是1、2或者4,即比較小的batch size,此時,無法正確估計出當前batch的均值與方差,
當然,這個可以通過工程上的trick來進行解決,即訓練多幾次才進行引數更新,在pytorch中,可以訓練N個batch后,將N個引數進行相加,再進行更新;在caffe中,可以在solver中設定iter_size來使訓練N步后再進行引數更新,這樣做,就可以就相當于使用了$N\times batch$的樣本進行訓練,解決了batch size過小引起的問題,
GN層
BN演算法受到batch size的影響,因此,就有很多研究員想如何通過消除batch size的影響來實作歸一化,有很多優秀的方法,例如Layer Norm,Instance Norm和Group Norm,在這里,重點介紹一個Group Norm,
Group Normalization來自于2018年Facebook《Group Normalization》,其主要解決的一個問題就是,當batch size很小時,如何才能正確的歸一化,
無論BN、LN、IN還是GN,其歸一化都是執行公式(4):
$$\hat{x}_i=\frac{1}{\sigma _i}(x_i-\mu _i) \tag{4}$$
其中,$\mu$和$\sigma $表示均值和標準差:
$$\mu_i=\frac{1}{m}\sum _{k\in S_i}x_k,\ \sigma _i=\sqrt{\frac{1}{m}\sum _{k\in S_i}(x_k-\mu _i)^2+\epsilon } \tag{5}$$
其中,$\epsilon $是一個很小的常數;而$S_i$表示對哪些像素集合進行求均值和方差,不同的歸一化方式,造成$S_i$的不同,
下圖是不同歸一化方式的$S_i$取值方式,藍色表示選取哪些集合來計算均值和方差,BN層是沿著維度C的方向,計算$(N,H,W)$的均值和方差;LN層是沿著維度N的方向,計算$(C,H,W)$的均值和方差;IN層是驗證維度N和維度C的方向,計算$(H,W)$的均值和方差,

當將特征歸一化完后,通常都會進行“變換重構”:
$$y_i=\gamma \hat{x}_i+\beta \tag{6}$$
其中,$\gamma $和$\beta $是可學習的變數,
對于GN層,在某一層中,將一個樣本的C個特征通道分成G組(默認情況下,$G=32$),每組中包含$\left \lfloor \frac{C}{G} \right \rfloor$個特征通道,我們將使用每個樣本下的每個分組來計算均值和方差,即計算$\frac{C}{G}\times H\times W$個值得均值和方差,在這里,$G$值是超參,$\left \lfloor \cdot \right \rfloor$是地板除法(向下取整),以上圖中最右邊的GN圖例為例,batch size為6,每個樣本中有$C=6$個特征通道,我們將其分成兩組$G=2$,此時每組具有$C/G=3$個通道,即藍色部分,對藍色部分計算均值和方差,
在同一組中,每個特征值使用當前組計算出來的均值$\mu $和方差$\sigma $,同樣,GN也需要變換重構,對于公式(6),GN會計算每個通道(不是每個組)的可學習變數$\gamma $和$\beta $,論文中給出了Tensorflow的代碼,和BN層很類似,

可以看出,如果$G=1$的話,即使用所有特征通道,等于變成了LN;若$G=C$的話,即只使用一個通道,等于變成了IN,與LN對比,GN約束性小了,可以更加靈活的學習到不同分組之間的不同分布,能有效提高模型的表達能力;與IN相比,GN利用了通道之間的關系,

從實驗結果來看,當batch size為32時,驗證集上,BN的效果略好于GN層,兩者差異不是特別大,但當batch size變小時,使用BN層的模型的性能迅速下降,而GN層不怎么受batch size的影響,表現穩定,比BN效果好很多,
另外值得注意一點是,論文中作者對實驗細節的表述特別棒,論文中提及到一點,目標檢測或者語意分割時,頭結構使用GN比使用BN的效果更好,因為在目標檢測中,ROI區域是從相同的圖片采樣得到的,它們不滿足獨立同分布,而非獨立同分布會榷訓BN層的均值和方差分布,所以導致在頭結構中使用BN層效果更差,
為什么GN層會有這樣的效果呢?最主要的原因是,用于表示物體特征的通道并非完全獨立的,可能會存在多個通道表示同一個特征的情況,所以在這一組特征通道中,這些特征值具有同分布的性質,對這一組內的特征進行group normalization,是一種比較合理的方法,(但這里不明確的是,表示統一特征之間的通道被分配到多個不同的組,這種情況該如何解決,)
最后,介紹一下GN層在pytorch中的用法,如下所示,其中, num_groups 表示需要分成多少組, num_channel 表示輸入通道數, eps 表示一個很小的常數, affine 表示是否需要進行變換重構,
import torch import torch.nn as nn nn.GroupNorm(num_groups=32, num_channel=64, eps=1e-5, affine=True)
綜上所述,GN層解決了batch size較小時引起的問題,通過將通道分成G組,以此來計算均值和方差,實作對一個樣本的歸一化,
FRN層
FRN層是谷歌在2019年的《Filter Response Normalization Layer: Eliminating Batch Dependence in the Training of Deep Neural Networks》中提出的,雖然GN解決了小batch size時的問題,但在正常的batch size時,其精度依然比不上BN層,如下圖所示,因此,有什么辦法能解決歸一化既不依賴于batch,又能使精度高于BN呢?FRN就是為了解決這個問題,

FRN層由兩部分組成,Filtere Response Normalization (FRN)和Thresholded Linear Unit (TLU),

假設輸入x的shape為$(B,C,H,W)$,分別表示batch size、通道數,特征圖的高寬,首先,先對每一個樣本的每一個通道單獨進行歸一化,即使用$N=H\times W$個特征值來求取平均平方和$\nu ^2$,然后對這$N=H\times W$個特征值進行公式(7)的計算:
$$\hat{x}_i=\frac{x_i}{\nu ^2+\epsilon } \tag{7}$$
其中,$\epsilon $是一個很小的正常數,防止除以零,這樣的操作注意,有利于消除又中間操作引起的尺寸變化問題[2],這里并不是傳統意義上的歸一化,它沒有減去均值,除以的也不是方差,然后對于每個通道,同樣進行變換重構,
由于在FRN操作中沒有減去均值,會導致“歸一化”后的特征值不是關于零對稱,會以任意的方式偏移零值,如果使用ReLU作為激活函式的話,會引起誤差,產生很多零值,性能下降,所以需要對ReLU進行增強,即TLU,引入一個可學習的閾值$\tau $:
$$z_{TLU}=max(y,\tau )=max(y-\tau ,0)+\tau =ReLU(y-\tau )+\tau \tag{8}$$
從上面來看,FRN層引入了$\gamma $、$\beta $和$\tau $三個可學習的引數,分別學習變換重構的尺度、偏移和閾值,他們都具有$C$個值,對應每一個通道,
一般情況下,特征圖的大小$N=H\times N$都比較大,但也有$N=1$的情況(全連接或者特征圖為$1 \times 1$),在$N=1$的情況下,對于公式(7),若$\epsilon $很小,則會變成一個sign函式,梯度值變得很小,不利于優化;若$\epsilon $相對較大,則曲線會平滑一點,容易優化,如下圖所示,因此,$\epsilon $的取值對于$N=1$的情況有重要影響,

在$N=1$的情況下,將$\epsilon $變成一個可學習的引數(初始化為$10^{-4}$);而對于$N\neq 1$時,將$\epsilon $固定成$10^{-6}$,為了保證可學習引數$\epsilon >0$,對其進行一定限制,$\epsilon =10^{-6}+\left | \epsilon _l \right |$,
在Tensorflow中,FRN層的代碼如下,

另外,在實驗上,存在幾個可以關注的細節:
- 由于FRN層沒有均值中心化,所以會有一些模型對初始學習率的選擇十分敏感,特別是那些使用了多個最大池化層的網路,為了緩解這個問題,作者建議使用warm-up來對學習率進行調整,
- 一般而言,FC層后一般都不會接歸一化層,這是因為均值和方差計算的數量太少,難以正確估計,但如果FC層后接FRN層,性能不會下降,反而會有上升,
- 作者對BN+TLU或者GN+TLU或者FRN+ReLU等系列都做過實驗對比,還是發現FRN+TLU的搭配是 最好的,
總結
BN層是現在大部分網路的標配,但其若batch size較小時,性能會表現較差;GN層就是為了解決batch size較小時,依然能使網路具有較好的性能,但是在大batch size時,性能依然比不上BN層;FRN層同時解決了mini-batch size的問題,同時又保證性能比BN層好,
參考文獻:
- 全面解讀Group Normalization,對比BN,LN,IN
- 超越BN和GN!谷歌提出新的歸一化層:FRN
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/43593.html
標籤:其他
