寫作目的
BatchNorm作業中一直在用,之前也看了好幾遍paper,一直沒有理解透徹,最近OpenMMLab發布了BN的pytorch原始碼解讀,跟著其理了一遍BN的實作,有了新的理解,特此記錄,
BatchNorm初衷
緩解造成深度神經網路訓練難的一個問題—— internal covariate shift(在訓練程序中,由于前面層的引數改變導致每層的輸入分布在不斷改變),
BatchNorm原理
BatchNorm in Training

上述公式為原Paper中給出的公式,這里有幾個比較困惑的問題:
(1)為什么歸一化之后又要加gamma和beta,破壞歸一化分布?
該問題在原論文(Sec3)中能找到答案,直接歸一化會丟失一些學習到的特征,為了保證插入的模塊能完成恒等變換,能將歸一化后的分布恢復為原始學習到的分布,加入了引數gamma和beta,在極端情況gamma等于方差,beta等于均值的時候BN能恢復原始的輸入,
個人理解,這里在保留原始特征和歸一化之間做了一個折中,使得BN輸出的特征既能盡可能保持之前網路學習到的特征,同時也能盡可能歸一化特征分布,
(2) 為什么均值和方差在除了channel之外的其他維度上求,
對應于卷積計算程序,輸入的channel是多大,其對應的feature map就有多深,即每個channel對應于一個二維的核(cs231n),同理每個channel對應一個mean和variance統計值,也對應一個gamma和一個bata,
BatchNorm in Inference

上述公式為原paper中給出的公式,有一個比較困惑的問題:
(1)為什么inference時的公式和training時的公式看上去不一樣?
將該式子變換為gamma和beta的公式,如下所示:

現在看上去就和訓練時候是一樣了,但是由于測驗時候均值、方差以及引數gamma和beta都不用計算,所以寫成了原paper中所示的形式,省去了除法計算,
BatchNorm計算
參考OpenMMLab對PyTorch中BatchNorm實作的解讀,手動計算BatchNorm,程序如下所示,
首先明確一下BatchNorm的輸入是什么——在卷積層之后的BatchNorm輸入是卷積層的output,即一個shape為NCHW的tensor,假設其輸入為以下N=2,C=3,H=2,W=2的隨機tensor,
>>> inputs = torch.randn(2, 3, 2, 2)
>>> inputs
tensor([[[[-0.8030, 0.2264],
[-0.8409, -0.9273]],
[[-0.5455, -0.7653],
[ 0.3283, -0.1631]],
[[-0.1568, 1.5355],
[ 1.7826, 0.8605]]],
[[[-1.9135, 1.2265],
[ 1.5482, -0.1545]],
[[ 2.3411, 1.5531],
[ 0.9359, 1.1492]],
[[-0.2346, -0.7456],
[ 0.0338, -0.8034]]]])
即第一個樣本的卷積層output為:
[[[-0.8030, 0.2264],
[-0.8409, -0.9273]],
[[-0.5455, -0.7653],
[ 0.3283, -0.1631]],
[[-0.1568, 1.5355],
[ 1.7826, 0.8605]]]
第二個樣本的卷積層output為:
[[[-1.9135, 1.2265],
[ 1.5482, -0.1545]],
[[ 2.3411, 1.5531],
[ 0.9359, 1.1492]],
[[-0.2346, -0.7456],
[ 0.0338, -0.8034]]]
(1)在N的維度上求均值,得到兩個樣本的平均特征,shape為CHW,結果如下所示:
tensor([[[-1.3582, 0.7265],
[ 0.3537, -0.5409]],
[[ 0.8978, 0.3939],
[ 0.6321, 0.4930]],
[[-0.1957, 0.3950],
[ 0.9082, 0.0286]]])
此處即對應位置的兩個數相加除以2,如左上角-1.3582 = (-0.8030-1.9135)/2
(2)對于該平均特征,在H的維度上求均值,shape為C*W,結果如下所示:
tensor([[-0.5023, 0.0928],
[ 0.7650, 0.4435],
[ 0.3562, 0.2118]])
此處即對沒一列求平均,例如左上角-0.5023 = (-1.3582+0.3537)/2
(3)在W的維度上繼續求平均,得到最終的inputs_mean,為一個C維的tensor,結果如下所示:
inputs_mean = tensor([-0.2048, 0.6042, 0.2840])
此處即對每一行求平均,例如第一個數 -0.2048= (-0.5023 + 0.0928)/2
(4)按照上述三步同樣的方法求得方差,如下所示:
inputs_var = tensor([1.1893, 1.0233, 0.8641])#unbiased=False,有偏
(5)根據求出的均值和方差對輸入進行歸一化:
inputs = inputs - inputs_mean[None, ..., None, None]
inputs = inputs / torch.sqrt(inputs_var[None, ..., None, None] + eps)
(6)對歸一化后的結果乘以gamma并加上beta:
inputs = inputs * bn_weight[..., None, None] + bn_bias[..., None, None]
(7)更新均值running_mean 和方差running_var,用于推理,
running_mean = running_mean * (1 - momentum) + momentum * inputs_mean
running_var = running_var * (1 - momentum) + momentum * inputs_var * n / (n - 1)
BatchNorm的優點
結合以上分析,進一步理解BatchNorm的優點:
(1)允許使用更大的學習率,使得訓練更快,
原因:BatchNorm能阻止大學習率使得引數發生大的變化后,輸出落入非線性函式的飽和區域;另外大的學習率相當于放大了引數,這樣會增加反傳的梯度,造成梯度爆炸,在采用了BatchNorm之后,反向傳播將不會受到引數縮放的影響,(sec3.3)
(2)有正則化的效果,一些情況下可以去除drop out,
原因:采用BatchNorm的時候,網路會同時看到一個batch樣本的統計量(均值、方差),而不是一個樣本,達到了正則化的效果,一個batch樣本采樣約隨機,正則化效果越好,
(3)使用sigmoid等非線性層時的梯度不容易消失,
原因:BatchNomr能將非線性層輸入分布更多的拉到0附近(非線性層梯度較大的區間),
加速BN網路訓練的方法
在原論文(sec4.2.1)中,作者提出了一些讓BN作業得更好得技巧,如下所示:
(1)增加學習率,
(2)移除Dropout,
(3)減少權重的L2正則化,比如除以5,
(4)加快學習率衰減的step,
(5)更徹底的Shuffle訓練樣本,
(6)減小 photometric distortions(光度畸變),
(7)移除 Local Response Normalization,
BN合并到卷積層
在模型部署時,往往需要把BN合并到卷積層,已加快推理,合并BN的公式推導如下:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/259848.html
標籤:AI
上一篇:《DLS》第二章筆記:感知機
