深度學習 weight initialization


轉自: https://www.leiphone.com/news/201703/3qMp45aQtbxTdzmK.htmla

https://blog.csdn.net/shuzfan/article/details/51338178  [原理推導]

 

背景

深度學習模型訓練的過程本質是對weight(即參數 W)進行更新,這需要每個參數有相應的初始值。有人可能會說:“參數初始化有什么難點?直接將所有weight初始化為0或者初始化為隨機數!”對一些簡單的機器學習模型,或當optimization function是convex function時,這些簡單的方法確實有效。

然而對於深度學習而言,非線性函數被瘋狂疊加,產生如本文題圖所示的non-convex function,如何選擇參數初始值便成為一個值得探討的問題——其本質是初始參數的選擇應使得objective function便於被優化。事實上,在學術界這也是一個被actively研究的領域。

TLDR里已經涵蓋了本文的核心要點,下面在正文中,我們來深入了解一下前因后果。

初始化為0的可行性?

答案是不可行。 這是一道送分題 哈哈!為什么將所有W初始化為0是錯誤的呢?是因為如果所有的參數都是0,那么所有神經元的輸出都將是相同的,那在back propagation的時候同一層內所有神經元的行為也是相同的 --- gradient相同,weight update也相同。這顯然是一個不可接受的結果。

可行的幾種初始化方式

pre-training

pre-training是早期訓練神經網絡的有效初始化方法,一個便於理解的例子是先使用greedy layerwise auto-encoder做unsupervised pre-training,然后再做fine-tuning。具體過程可以參見UFLDL的一個tutorial,因為這不是本文重點,就在這里簡略的說一下:

  • pre-training階段,將神經網絡中的每一層取出,構造一個auto-encoder做訓練,使得輸入層和輸出層保持一致。在這一過程中,參數得以更新,形成初始值

  • fine-tuning階段,將pre-train過的每一層放回神經網絡,利用pre-train階段得到的參數初始值和訓練數據對模型進行整體調整。在這一過程中,參數進一步被更新,形成最終模型。

隨着數據量的增加以及activation function (參見我的另一篇文章) 的發展,pre-training的概念已經漸漸發生變化。目前,從零開始訓練神經網絡時我們也很少采用auto-encoder進行pre-training,而是直奔主題做模型訓練。不想從零開始訓練神經網絡時,我們往往選擇一個已經訓練好的在任務A上的模型(稱為pre-trained model),將其放在任務B上做模型調整(稱為fine-tuning)。

random initialization

隨機初始化是很多人目前經常使用的方法,然而這是有弊端的,一旦隨機分布選擇不當,就會導致網絡優化陷入困境。下面舉幾個例子。

核心代碼見下方,完整代碼請參見我的Github

谷歌工程師:聊一聊深度學習的weight initialization

這里我們創建了一個10層的神經網絡,非線性變換為tanh,每一層的參數都是隨機正態分布,均值為0,標准差為0.01。下圖給出了每一層輸出值分布的直方圖。

谷歌工程師:聊一聊深度學習的weight initialization

隨着層數的增加,我們看到輸出值迅速向0靠攏,在后幾層中,幾乎所有的輸出值 x 都很接近0!回憶優化神經網絡的back propagation算法,根據鏈式法則,gradient等於當前函數的gradient乘以后一層的gradient,這意味着輸出值 x 是計算gradient中的乘法因子,直接導致gradient很小,使得參數難以被更新!

讓我們將初始值調大一些:

谷歌工程師:聊一聊深度學習的weight initialization

均值仍然為0,標准差現在變為1,下圖是每一層輸出值分布的直方圖:

谷歌工程師:聊一聊深度學習的weight initialization

幾乎所有的值集中在-1或1附近,神經元saturated了!注意到tanh在-1和1附近的gradient都接近0,這同樣導致了gradient太小,參數難以被更新。

Xavier initialization

原理:https://www.jianshu.com/p/4e53d3c604f6   自編碼器參數初始化方法-Xavier initialization

Xavier initialization可以解決上面的問題!其初始化方式也並不復雜。Xavier初始化的基本思想是保持輸入和輸出的方差一致,這樣就避免了所有輸出值都趨向於0。注意,為了問題的簡便,Xavier初始化的推導過程是基於線性函數的,但是它在一些非線性神經元中也很有效。讓我們試一下:

谷歌工程師:聊一聊深度學習的weight initialization

谷歌工程師:聊一聊深度學習的weight initialization

Woohoo!輸出值在很多層之后依然保持着良好的分布,這很有利於我們優化神經網絡!之前談到Xavier initialization是在線性函數上推導得出,這說明它對非線性函數並不具有普適性,所以這個例子僅僅說明它對tanh很有效,那么對於目前最常用的ReLU神經元呢(關於不同非線性神經元的比較請參考這里)?繼續做一下實驗:

谷歌工程師:聊一聊深度學習的weight initialization

谷歌工程師:聊一聊深度學習的weight initialization

前面看起來還不錯,后面的趨勢卻是越來越接近0。幸運的是,He initialization可以用來解決ReLU初始化的問題。

He initialization

He initialization的思想是:在ReLU網絡中,假定每一層有一半的神經元被激活,另一半為0,所以,要保持variance不變,只需要在Xavier的基礎上再除以2:

谷歌工程師:聊一聊深度學習的weight initialization

谷歌工程師:聊一聊深度學習的weight initialization

看起來效果非常好,推薦在ReLU網絡中使用!

Batch Normalization Layer

Batch Normalization是一種巧妙而粗暴的方法來削弱bad initialization的影響,其基本思想是:If you want it, just make it!

我們想要的是在非線性activation之前,輸出值應該有比較好的分布(例如高斯分布),以便於back propagation時計算gradient,更新weight。Batch Normalization將輸出值強行做一次Gaussian Normalization和線性變換:

谷歌工程師:聊一聊深度學習的weight initialization

Batch Normalization中所有的操作都是平滑可導,這使得back propagation可以有效運行並學到相應的參數γ,β。需要注意的一點是Batch Normalization在training和testing時行為有所差別。Training時μβ和σβ由當前batch計算得出;在Testing時μβ和σβ應使用Training時保存的均值或類似的經過處理的值,而不是由當前batch計算。

隨機初始化,無Batch Normalization:

谷歌工程師:聊一聊深度學習的weight initialization

谷歌工程師:聊一聊深度學習的weight initialization

隨機初始化,有Batch Normalization:

谷歌工程師:聊一聊深度學習的weight initialization

谷歌工程師:聊一聊深度學習的weight initialization

很容易看到,Batch Normalization的效果非常好,推薦使用!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM