文章出處: Michael Nielsen的《Neural Network and Deep Learning》,本節譯者:哈工大SCIR本科生 朱澤圻。
目錄
1、使用神經網路識別手寫數字
2、反向傳播演算法是如何工作的
3、改進神經網路的學習方法
- 改進神經網路的學習方式
- 交叉熵損失函式
- 使用交叉熵損失來分類MNIST數字集
- 交叉熵意味著什麼?它從哪裡來?
- Softmax
- 過擬合和正則化
- 正則化
- 為什麼正則化能夠降低過擬合?
- 其他正則化技術
- 引數初始化
- 重溫手寫數字識別:程式碼
- 如何選擇神經網路的超引數
- 其他技術
4、神經網路能夠計算任意函式的視覺證明
5、為什麼深度神經網路的訓練是困難的
6、深度學習
避免過擬合的方法之一是增加訓練資料數量。那麼,還有沒有別的方法能讓我們避免過擬合呢?一種可能的方法是減小網路的規模。然而,我們並不情願減小規模,因為大型網路比小型網路有更大的潛力。
幸好,哪怕使用固定的網路和固定的訓練資料,我們還有別的方法來避免過擬合。這就是所謂的正則化(regularization)技術。在這一節我將描述一種最常用的正則化技術——權重衰減(weight decay)或叫 L2 正則(L2 regularization)。L2 正則的思想是,在代價函式中加入一個額外的正則化項。這是正則化之後的交叉熵:
(85)
第一項是常規的交叉熵表示式。但我們加入了第二項,也就是網路中所有權值的平方和。它由引數 進行調整,其中 被稱為正則化引數(regularization parameter), 是我們訓練集的大小。我稍後會討論應該如何選擇 。另外請注意正則化項不包括偏移。我稍後也會提到這點。
當然,我們也可以對其它的代價函式進行正則化,例如平方代價。正則化的方法與上面類似:
(86)
在兩種情況中,我們都能把正則化的代價函式寫成:
(87)
其中 是原本的、沒有正則化的成本函式。
直觀來說,正則化的作用是讓網路偏好學習更小的權值,而在其它的方面保持不變。選擇較大的權值只有一種情況,那就是它們能顯著地改進代價函式的第一部分。換句話說,正則化可以視作一種能夠折中考慮小權值和最小化原來代價函式的方法。兩個要素的相對重要性由 的值決定:當 較小時,我們偏好最小化原本的代價函式,而 較大時我們偏好更小的權值。
貌似折中也可以!但事實是它的確能夠減少過擬合。我們將在下一部分闡述為何這樣的折中能夠減少過擬合。先讓我們通過一個例子展示正則化確實能夠減小過擬合。
為了構建這樣一個例子,我們首先要解決如何把隨機梯度下降學習演算法應用於正則化的神經網路中。我們尤其需要知道如何對網路中所有的權值和偏移計算偏導數 和。對等式(87)求偏導可得:
(88,89)
正如上一章所述,其中 和 可由反向傳播計算。於是我們發現計算正則化代價函式的梯度相當簡單:只要照常使用反向傳播,並把 加到所有權值項的偏導數中。偏移的偏導數保持不變,所以偏移的梯度下降學習的規則保持常規的不變:
(90)
而對於權值的學習規則變為:
(91) (92)
其它部分與常規的梯度下降學習規則完全一樣,不一樣的地方是我們以 調整權值 。這種調整有時也被稱作權重衰減(weight decay),因為它減小了權重。一眼看去權值將被不停地減小直到為 0。但實際上並不是這樣的,因為如果可以減小未正則化的成本函式的話,式中的另外一項可能會讓權值增加。
好的,這就是梯度下降實現的方法。那麼隨機梯度下降呢?和未正則化的隨機梯度下降一樣,我們首先在包含 個訓練樣例的 mini-batch 資料中進行平均以估計 的值。因此對於隨機梯度下降法而言正則化的學習方法就變成了(參考等式 (20)):
(93)
其中的求和是對 mini-batch 中的所有訓練樣例進行的, 是每個樣例對應的未正則化的代價。這與通常的隨機梯度下降方法一致,除了權重衰減變數 。最後,為了表述完整,我要說明對於偏移的正則化學習規則。毫無疑問,那就是與未正則化的情況(如等式 (21))完全一樣,
(94)
其中的求和是對 mini-batch 中的所有訓練樣例 進行的。
讓我們看看正則化如何改變了我們的神經網路的表現。我們將使用一個神經網路來進行驗證,其包含 個隱藏神經元,mini-batch 大小為 ,學習率為 ,並以交叉熵作為代價函式。然而,這次我們設定正則化引數 。注意在程式碼中,我們使用變數名 lmbda,因為 lambda 是 Python 的保留字,其含義與此無關。我也再次使用了 test_data 而非 validation_data。嚴格來說,我們應該使用 validation_data,詳細原因我們在此前已經解釋過。不過我決定用 test_data 因為它能讓結果與我們此前未正則化的結果進行更直觀的比較。對程式碼稍作改動你即可使用 validation_data,並且你將發現得到的結果很相似。
>>> 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[:1000](), 400, 10, 0.5,
… evaluation_data=test_data, lmbda = 0.1,
… monitor_evaluation_cost=True, monitor_evaluation_accuracy=True,
… monitor_training_cost=True, monitor_training_accuracy=True)
成本函式一直都在下降,幾乎與此前在未正則化的情形一樣[1]:
但這次它在 test_data 上的準確率在 400 次迭代中保持提升:
顯然,應用正則化抑制了過擬合。同時,準確率也顯著提升了:分類準確率峰值為 ,更高於未正則化例子中的峰值 。實際上,我們幾乎確定,繼續進行迭代可以得到更好的結果。從經驗來看,正則化讓我們的網路生成得更好,並有效地減弱了過擬合效應。
如果我們從僅有 張訓練圖片遷移到有著 張圖片的環境,結果又會怎麼樣呢?當然,我們已經看到過擬合對於 張圖片來說不再是個大問題了。那麼正則化能在這上面提供更多幫助嗎?讓我們把超引數保持跟以前的一樣: 次迭代,學習率為 ,mini-batch 數目為 。然而,我們需要調整正則化引數。原因是,訓練資料集的大小已經從 變成了 ,而這就改變了權重衰減因數 。如果我們繼續使用 那麼權重衰減將會大大減小,而正則化的效果也會相應減弱。我們調整 以進行補償。
好的,讓我們訓練我們的網路,並在此之前重新初始化權值:
>>> net.large_weight_initializer()>>> net.SGD(training_data, 30, 10, 0.5,
… evaluation_data=test_data, lmbda = 5.0,
… monitor_evaluation_accuracy=True, monitor_training_accuracy=True)
我們得到結果如圖:
這裡有很多好訊息。首先,我們在測試資料上的分類準確率提升了,從未正則化時的百分之 到百分之 。這是一個重大的提升。第二,我們能看到訓練資料的結果與測試資料的之間的間隙相比之前也大大縮小了,在一個百分點之下。雖然這仍然是一個明顯的間隙,但我們顯然已經在減弱過擬合上做出了大量的提升。
最後,讓我們看看當我們使用 個隱藏神經元並設定 時測試分類準確率。我將不會對這裡的過擬合進行詳細的分析,這只是純粹為了有趣,只為了看看我們使用新的技巧——交叉熵成本函式和L2 正則化——能讓我們得到多高的準確率。
>>> net = network2.Network([784, 100, 10](),\
… cost=network2.CrossEntropyCost)>>> net.large_weight_initializer()>>> net.SGD(training_data, 30, 10, 0.5, lmbda=5.0,\
… evaluation_data=validation_data,\
… monitor_evaluation_accuracy=True)
最終結果是,分類準確率在驗證資料上達到了 。相對於 個隱藏神經元的情形,這是一個飛躍。事實上,只要再訓練更多些,保持 和 ,增加到 次迭代,我們能夠突破百分之 的壁壘,在驗證資料上達到百分之 的準確率。對於這 152 行程式碼來說是不錯的結果了!
我已經描述了正則化作為一種減弱過擬合併提升分類準確率的方法。事實上,這並不是它唯一的好處。經驗表明,當在多次執行我們的 MNIST 網路,並使用不同的(隨機)權值初始化時,我發現未正則化的那些偶爾會被「卡住」,似乎陷入了代價函式的區域性最優中。結果就是每次執行可能產生相當不同的結果。相反,正則化的那些的每次執行可以提供更容易復現的結果。
為什麼會這樣呢?啟發式地來說,如果代價函式沒有正則化,那麼權重向量的長度傾向於增長,而其它的都不變。隨著時間推移,權重向量將會變得非常大。這可能導致權重向量被限制得或多或少指向同一個方向,因為當長度過長時,梯度下降只能帶來很小的變化。我相信這一現象令我們的學習演算法難於恰當地探索權重空間,因而難以給代價函式找到一個好的極小值。
[1]. 這張圖和下兩張圖的結果是由程式 overfitting.py (https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/fig/overfitting.py) 產生的。
本文來源於哈工大SCIR