文章出處: Michael Nielsen的《Neural Network and Deep Learning》,本節譯者:朱小虎 、張廣宇。
目錄
1、使用神經網路識別手寫數字
2、反向傳播演算法是如何工作的
3、改進神經網路的學習方法
- 改進神經網路的學習方式
- 交叉熵損失函式
- 使用交叉熵損失來分類MNIST數字集
- 交叉熵意味著什麼?它從哪裡來?
- Softmax
- 過擬合和正則化
- 正則化
- 為什麼正則化能夠降低過擬合?
- 其他正則化技術
- 權重初始化
- 重溫手寫數字識別:程式碼
- 如何選擇神經網路的超引數
- 其他技術
4、神經網路能夠計算任意函式的視覺證明
5、為什麼深度神經網路的訓練是困難的
6、深度學習
建立了神經網路後,我們需要進行權重和偏置的初始化。到現在,我們一直是根據在第一章中介紹的那樣進行初始化。提醒你一下,之前的方式就是根據獨立高斯隨機變數來選擇權重和偏置,其被歸一化為均值為 ,標準差 。這個方法工作的還不錯,但是非常特別,所以值得去重新探討它,看看是否能尋找一些更好的方式來設定初始的權重和偏置,這也許能幫助我們的網路學習得更快。
結果表明,我們可以比使用歸一化的高斯分佈做得更好。為什麼?假設我們使用一個有大量輸入神經元的網路,比如說 個。假設,我們已經使用歸一化的高斯分佈初始化了連線第一個隱藏層的權重。現在我將注意力集中在這一層的連線權重上,忽略網路其他部分:
為了簡化,假設我們使用訓練輸入 ,其中一半的輸入神經元值為 ,另一半為 。以下的論點更普遍適用,但你可以從這種特殊情況得到要點。讓我們考慮隱藏神經元輸入的帶權和 。其中 個項消去了,因為對應的輸入 為 。所以 是遍歷總共 個歸一化的高斯隨機變數的和,包含 個權重項和額外的 個偏置項。因此 本身是一個均值為 標準差為 的高斯分佈。 其實有一個非常寬的高斯分佈,完全不是非常尖的形狀:
尤其是,我們可以從這幅圖中看出 會變得非常的大,即 或者 。如果是這樣,隱藏神經元的輸出 就會接近 或者 。也就表示我們的隱藏神經元會飽和。所以當出現這樣的情況時,在權重中進行微小的調整僅僅會給隱藏神經元的啟用值帶來極其微弱的改變。而這種微弱的改變也會影響網路中剩下的神經元,然後會帶來相應的代價函式的改變。結果就是,這些權重在我們進行梯度下降演算法時會學習得非常緩慢[1]。
這其實和我們在本章前面討論的問題差不多,前面的情況是輸出神經元在錯誤的值上飽和導致學習的下降。我們之前通過代價函式的選擇解決了前面的問題。不幸的是,儘管那種方式在輸出神經元上有效,但對於隱藏神經元的飽和卻一點作用都沒有。
我已經討論了第一個隱藏層的權重輸入。當然,類似的論證也適用於後面的隱藏層:如果後面隱藏層的權重也是用歸一化的高斯分佈進行初始化,那麼啟用值將會非常接近 或者,學習速度也會相當緩慢。
還有可以幫助我們進行更好地初始化,能夠避免這種型別的飽和,最終避免學習速度的下降?假設我們有一個有 個輸入權重的神經元。我們會使用均值為 標準差為 的高斯隨機分佈初始化這些權重。也就是說,我們會向下擠壓高斯分佈,讓我們的神經元更不可能飽和。我們會繼續使用均值為 標準差為 的高斯分佈來對偏置進行初始化,後面會告訴你原因。有了這些設定,帶權和 仍然是一個均值為 , 不過有尖銳峰值的高斯分佈。假設,我們有 個值為 的輸入和 個值為 的輸入。那麼很容易證明 是服從均值為 標準差為 的高斯分佈。這要比以前有更尖銳的峰值,尖銳到為了用下圖更直觀地比較,我不得不對對縱座標進行壓縮:
這樣的一個神經元更不可能飽和,因此也不大可能遇到學習速度下降的問題。
練習
驗證 標準差為 。下面兩點可能會有幫助:(a)獨立隨機變數和的方差,是每個獨立隨機變數方差的和;(b)方差是標準差的平方。
我在上面提到,我們會繼續使用之前的方式對偏置進行初始化,就是使用均值為 標準差為 的高斯分佈來對偏置進行初始化。這其實是可行的,因為這樣並不會讓我們的神經網路更容易飽和。實際上,考慮到已經避免了飽和的問題,如何初始化偏置影響不大。有些人將所有的偏置初始化為 ,依賴梯度下降來學習合適的偏置。但是因為差別不是很大,我們後面還會按照前面的方式來進行初始化。
讓我們在 MNIST 數字分類任務上比較一下新舊兩種權重初始化方式。同樣,還是使用 個隱藏元,minibatch 的大小為 ,規範化引數 ,然後是交叉熵代價函式。我們將learningrate從 降到 ,因為這樣會讓結果在影像中表現得更加明顯。我們先使用舊的權重初始化方法訓練:
>>> import mnist_loader
>>> training_data, validation_data, test_data = \
… mnist_loader.load_data_wrapper()
>>> import network2
>>> net = network2.Network([784, 30, 10], cost=network2.CrossEntropyCost)
>>> net.large_weight_initializer()
>>> net.SGD(training_data, 30, 10, 0.1, lmbda = 5.0,
… evaluation_data=validation_data,
… monitor_evaluation_accuracy=True)
我們也使用新方法來進行權重的初始化。這實際上還要更簡單,因為network2 預設方式就是使用新的方法。這意味著我們可以丟掉上面的net.large_weight_initializer() 呼叫:
>>> net = network2.Network([784, 30, 10], cost=network2.CrossEntropyCost)
>>> net.SGD(training_data, 30, 10, 0.1, lmbda = 5.0,
… evaluation_data=validation_data,
… monitor_evaluation_accuracy=True)
將結果用圖展示出來[2],我們得到:
兩種情形下,我們最終都獲得了超過 96% 的準確率。最終的分類準確率幾乎完全一樣。但是新的初始化技術帶來了速度的提升。在經過一輪迭代後,第一種初始化方式的分類準確率在 87% 以下,而新的方法已經幾乎達到了 93%。看起來的情況就是我們新的關於權重初始化的方式將訓練帶到了一個新的境界,讓我們能夠更加快速地得到好的結果。同樣的情況在 個神經元的設定中也出現了:
在這個情況下,兩個曲線並沒有重合。然而,我做的實驗發現在一些額外的迭代次數之後準確率也是幾乎相同的。所以,基於這些實驗,看起來提升的權重初始化僅僅會加快訓練,不會改變網路的最終效能。然而,在第四章,我們會看到一些例子裡面使用 權重初始化的長期執行的結果要顯著更優。因此,不僅僅能夠帶來訓練速度的加快,有時候在最終效能上也有很大的提升。
的權重初始化方法幫助我們提升了神經網路學習的方式。其他的權重初始化技術同樣也被提出,很多都是基於這個基本的思想。我不會在這裡回顧其他的方法,因為 已經可以工作得很好了。如果你感興趣的話,我推薦你看看在2012 年的 Yoshua Bengio 的論文[3]的 14 和 15 頁,以及相關的參考文獻。
問題
將規範化和改進的權重初始化方法結合使用 L2 規範化有時候會自動給我們一些類似於新的初始化方法的東西。假設我們使用舊的初始化權重的方法。考慮一個啟發式的觀點:(1)假設 不太小,訓練的第一輪迭代將會幾乎被權重衰減統治;(2)如果 ,權重會在每輪迭代中按照因子 衰減;(3)假設 不太大,權重衰減會在權重降到 的時候保持住,其中 是網路中權重的個數。論證這些條件都已經在本節給出圖示的例子中滿足。
[1]我們在第二章詳細討論過這個問題,其中我們用反向傳播的方程來顯示輸入到飽和神經元的權重學習得緩慢。
[2]用來生成這幅以及下一幅圖形的程式是https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/fig/weight_initialization.py。
[3]http://arxiv.org/pdf/1206.5533v2.pdf Practical Recommendations for Gradient-Based Training of Deep Architectures,作者為Yoshua Bengio (2012)。
本文來源於哈工大SCIR