一、什么是Batch Normalization(批標準化)?
因為我們正常的訓練神經網路,為了提高速度,當然也因為很多時候資料量很龐大沒法一次性全部讀入,我們會把資料分批次讀入模型訓練,批標準化就是針對每批資料訓練后,對網路每層神經元的輸出做標準化處理(將很離散的資料映射到0-1之間),這只是一個很簡單的操作,但是我為啥要單獨拎出來說呢,因為這個批標準化對模型的影響實在太大太大,
上周我正開開心心的搭建一個CNN模型跑影像識別,模型沒問題,資料正常讀取,然后…模型發散了!!!是的,不是過擬合或欠擬合,就是發散了!訓練集一直不收斂,一直發散,我知道這是因為模型設計的不合理導致的,于是我反復查看神經網路層數,每層的神經元個數,卷積層,池化層,全連接層,但是都沒有找到問題,于是我換了另外一個資料集,正常擬合了,,,,那是我這個資料集的問題嗎???是資料集內容太少了嗎?也不是啊,上萬的資料量,是產生了梯度爆炸嗎?也不是啊,keras里面設計會產生的初始化權重會自動規避這個問題,那是啥原因呢???
后來注意到沒有加入批標準化對每層的輸出做處理,莫非是這里的問題?于是在全連接層中加了批標準化處理,結果,,,順利的擬合了,,,,模型最后輸出也沒有問題,What???為啥會是沒有批標準化處理就導致這樣的問題,
二、Batch Normalization(批標準化)對模型的影響是什么?
回憶一下,在模型讀入資料的時候,我們會將資料進行標準化處理(所有資料映射到0-1),這樣對模型的影響是什么呢?比如我們的模型中第一個神經元權重是0.5,如果原始資料是100,那么第一個神經元輸出是0.5 x 100 = 50,將原始資料標準化為0.1,那么此時輸出為0.5 x 0.1 = 0.05,50和0.05有啥區別呢?說個很直接的例子,如果我們的激活函式是sigmoid,函式方程點擊這里查看常見的激活函式(Sigmoid,tanh雙曲正切,ReLU修正線性單元,Leaky ReLU函式),那么50會很容易導致sigmoid的函式方程式爆炸,因為e的-50次方的原因,會讓sigmoid整體輸出的結果非常趨近于0(python實作的時候就已經是輸出0了,,,,,),這也很好的解釋了我為啥一開始numpy實作神經網路時產生的很多資料爆炸的問題,而如果是0.05就不會這樣,會輸出一個非常可觀的數值,當然我們的神經網路隱層現在常采用的是ReLU激活函式,不會出現sigmoid所謂的數值爆炸情況,但是也恰好因為ReLU沒有映射能力,會導致前面的資料量不斷堆積到后面,后面的數值也會非常龐大,最后模型的輸出還是使用到sigmoid進行映射輸出,也會產生數值爆炸,所以最好的方式就是對每層神經元的輸出做一個批標準化處理,因為每層讀入的數值很大對模型的優化訓練也不是好事,下降慢耗時長,而且也容易導致其他隱藏的因為資料量過大的問題,
三、keras加載使用Batch Normalization(批標準化)
keras加載使用BatchNormalization很簡單,看下面代碼,
from keras.layers import BatchNormalization
model.add(Dense(2, input_dim=10,#輸入資料唯獨10,輸出唯獨為2
activation='relu'#激活函式采用ReLU
)),
BatchNormalization()#添加批標準化處理
Dense(1,activation='sigmoid')#輸出
根據上面的分析,如果隱層使用的ReLU激活函式,沒有加BatchNormalization,那么最好輸出層,也就是sigmoid輸出層前面的一層神經元的輸出最好加上,比如導致sigmoid的數值爆炸,對了如果是多分類,激活函式使用的是softmax,也要加上BatchNormalization,因為softmax和sigmoid本質一樣是利用e的指數函式進行數值映射,也會容易產生數值爆炸,
希望我的分享對你的學習有所幫助,如果有問題請及時指出,謝謝~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/294110.html
標籤:AI
上一篇:機器學習入門日記
