BN和conv pooling一樣是一個含有參數的層,其解決的問題是樣本間在隱含層的特徵數據分佈不均,提升訓練效率。
基本算法如下,首先對每一層的數據,都會計算其均值和方差,再將特徵數據分佈歸一化到均值為1,標準差為0。僅僅是這樣操作後會有一個硬傷:原本一些數據分佈可能都是大於0的,現在你歸一化到均值為1,一般情況下,神經元在ReLu都不會被激活!
因而BN層又構造了一個的線性變換,且
、
兩個參數都是可學習的,讓神經網絡自己憑經驗選擇,對於某一類數據在特定層,需要將數據變換到什麼參數下的分佈
其優點有:
- 讓SGD變得簡單而高效,可以使用更高的學習率也不必過於小心參數初始化(BN同時解決了梯度消失/爆炸??限制了權重,避免爆炸,把激活值拉到一個合理區間,避免消失?)
- BN提高了泛化性能。AlexNet中的LRN、dropout可以退出歷史舞台了,也可以選擇更小的L2正則約束參數
關於BN層的使用,有兩種方式,一是在conv/FC之前使用,二是在conv/FC之後,在ReLu激活之前使用BN層,作者論證了後者更合理,而且由於BN的歸一化作用,神經網絡中的bias沒啥影響了:
隨便找了個代碼,確實BN是夾在conv和ReLu之間:
if batch_norm:
layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)]