【前言】:公眾號【機器學習煉丹術】的AI初學者交流群已經建立啦,公眾號後臺回覆【
加群
】可以加入。群裡都是些一起學習的朋友大家學習路上,結個伴。
文章共3371字,預計閱讀時間9min
文章目錄:
1 BN的優點
2 BN的缺點
2。1 受限於Batch size
2。2 訓練集與測試集的分佈
3 Group Normalzation
4 PyTorch實現GN
總的來說,GN是對BN的改進,是IN和LN的均衡。
1 BN的優點
這裡簡單的介紹一下BN,在之前的文章中已經詳細的介紹了BN演算法和過程。
BN於2015年由 Google 提出,Google在ICML論文中描述的非常清晰,即在每次SGD時,透過mini-batch來對相應的activation做規範化操作,使得結果(輸出訊號各個維度)的均值為0,方差為1。最後的“scale and shift”操作則是為了訓練所需而“刻意”加入的BN能夠有可能還原最初的輸入,從而保證資料中有用資訊的留存。
【BN的好處】
BN使得網路中每層輸入資料的分佈相對穩定,加速模型學習速度;
BN使得模型對網路中的引數不那麼敏感,簡化調參過程,使得網路學習更加穩定;
BN允許網路使用飽和性啟用函式(例如sigmoid,tanh等),緩解梯度消失問題;
BN具有一定的正則化效果。
2 BN的缺點
2.1 受限於Batch size
BN 沿著 batch 維度進行歸一化,其受限於 Batch Size,
當 Batch Size
很
小時,BN 會得到不準確的統計估計,會導致模型誤差明顯增加
【一般每塊 GPU 上 Batch Size =32 最合適。】
但對於目標檢測,語義分割,影片場景等,輸入影象尺寸比較大,而限於GPU顯示卡的視訊記憶體限制,導致無法設定較大的 Batch Size,如 經典的Faster-RCNN、Mask R-CNN 網路中,
由於影象的解析度較大,Batch Size 只能是 1 或 2.
2.2 訓練集與測試集的分佈
BN處理訓練集的時候,採用的均值和方差是整個訓練集的計算出來的均值和方差
(這一部分沒有看懂的話,可能需要去看一下BN演算法的詳解)
所以測試和訓練的資料分佈如果存在差異,那麼就會導致訓練和測試之間存在不一致現象(Inconsistency)。
3 Group Normalzation
Group Normalization(GN)是由2018年3月份何愷明團隊提出,GN優化了BN在比較小的mini-batch情況下表現不太好的劣勢。
Group Normalization(GN) 則是提出的一種 BN 的替代方法,其是首先將 Channels 劃分為多個 groups,再計算每個 group 內的均值和方法,以進行歸一化。
GB的計算與Batch Size無關,因此對於高精度圖片小BatchSize的情況也是非常穩定的,
下圖是比較BN和GN在Batch Size越來越小的變化中,模型錯誤率變化的對比圖:
因此在實驗的時候,可以
在
嘗試使用GN來代替BN哦~
其實不難發現,GN和LN是存在一定的關係的。
上圖中有四種Normalization的方法。就先從最簡單的Instance Normalization開始分析:
IN:僅僅對每一個圖片的每一個通道最歸一化。也就是說,對【H,W】維度做歸一化。假設一個特徵圖有10個通道,那麼就會得到10個均值和10個方差;要是一個batch有5個樣本,每個樣本有10個通道,那麼IN總共會計算出50個均值方差;
LN:對一個特徵圖的所有通道做歸一化。5個10通道的特徵圖,LN會給出5個均值方差;
GN:這個是介於LN和IN之間的一種方法。假設Group分成2個,那麼10個通道就會被分成5和5兩組。然後5個10通道特徵圖會計算出10個均值方差。
BN:這個就是對Batch維度進行計算。所以假設5個100通道的特徵圖的話,就會計算出100個均值方差。5個batch中每一個通道就會計算出來一個均值方差。
在GN的論文中,給出了GN推薦的group Number:
第一個表格展示GN的group Number不斷減小,退化成LN的過程。其實,分組32個group效果最好;
第二個表格展示GN的每一組的channel數目不斷減小,退化成IN的過程。
每一組16個channel的效果最好
,
我個人在專案中也會有優先嚐試16個通道為一組的這種引數設定。
4 PyTorch實現GN
import numpy as npimport torchimport torch。nn as nnclass GroupNorm(nn。Module): def __init__(self, num_features, num_groups=32, eps=1e-5): super(GroupNorm, self)。__init__() self。weight = nn。Parameter(torch。ones(1,num_features,1,1)) self。bias = nn。Parameter(torch。zeros(1,num_features,1,1)) self。num_groups = num_groups self。eps = eps def forward(self, x): N,C,H,W = x。size() G = self。num_groups assert C % G == 0 x = x。view(N,G,-1) mean = x。mean(-1, keepdim=True) var = x。var(-1, keepdim=True) x = (x-mean) / (var+self。eps)。sqrt() x = x。view(N,C,H,W)
當然,你要是想問PyTorch是否已經集成了GN?那必然的。下面的程式碼比較了PyTorch整合的GN和我們手算的GN的結果。
import torchimport torch。nn as nnx=torch。randn([2,10,3,3])+1# Torch整合的方法m=torch。nn。GroupNorm(num_channels=10,num_groups=2)# 先計算前面五個通道的均值firstDimenMean = torch。Tensor。mean(x[0,0:5])# 先計算前面五個通道的方差firstDimenVar= torch。Tensor。var(x[0,0:5],False)# 減去均值乘方差y2 = ((x[0][0][0][1] - firstDimenMean)/(torch。pow(firstDimenVar+m。eps,0。5) )) * m。weight[0] + m。bias[0]print(y2)y1=m(x)print(m。weight)print(m。bias)print(y1[0,0,0,1])
輸出結果:
tensor(0。4595, grad_fn=
- END -