本文爲筆者學習CS224N所做筆記,所包含內容不限於課程課件和講義,還包括筆者對機器學習、神經網絡的一些理解。所寫內容難免有難以理解的地方,甚至可能有錯誤。如您在閱讀中有疑惑或者建議,還望留言指正。筆者不勝感激!
在本章中,將着重討論以下內容:
- 如何更新神經網絡參數?
- 以何種形式保存更新結構?
- 搭建和訓練神經網絡的技巧.
梯度和導數
上一章提到,應該最小化損失函數。損失函數的參數是神經網絡參數,由於梯度的方向是函數上升最快的方向,故若想最小化損失函數,應該按負梯度方向更新參數,即梯度下降。而爲了求解損失函數對參數的梯度,就涉及到了微分的問題。
梯度計算
對於上一章提出的簡單的神經網絡分類器,有如下的形式:
現在計算,根據鏈式法則,有
此處均爲矩陣或者向量的形式,涉及到矩陣求導,較爲繁瑣。爲了簡單清楚的闡述其原理,我們求對於中某個特定元素的求導規則,即計算。同時,我們神經網絡用圖的方式更加詳細的表示出來。
再做一個簡化,令鏈式法則展開的前兩項爲,關注,即
我們考慮對於一個矩陣權重的微分,
KaTeX parse error: No such environment: align* at position 8:
\begin{̲a̲l̲i̲g̲n̲*̲}̲
\frac{z_i}{\pa…
故對於一個權重值,,其中與輸入有關,叫做局部梯度信號,而和誤差有關,叫做誤差信號。
對於,最終的維度爲,其中爲隱層神經元數量,上圖中爲2,爲輸入層神經元數量,上圖爲(也可以直接根據矩陣求導求得)。
滑動窗口輸入的梯度計算
上一小節圖片中的模型考慮到的是輸入爲一個詞向量的情況,而對於滑動窗口模型而言,輸入爲多個詞向量。可以將每個詞的詞向量分開考慮,這樣做的原因是考慮到可以對已經訓練好的詞向量做fine-tune(微調),則有
且.在fine tune過程中,對神經網絡參數訓練的同時,也會調整詞向量。
在對詞向量做fine-tune之前也要考慮一些問題,例如我們要使用單個詞彙訓練電影評論情感分類模型,在訓練集中出現了"TV"和"telly",但是沒有出現"television",在測試集中只出現了"television",卻沒有出現"TV"和"telly";換言之,訓練集和測試集的樣本分佈不均衡。如果在這種情況下依舊對詞向量進行fine tune,會導致詞的分類錯誤。如下面兩幅圖所示。
如果使用已經訓練好的詞向量,需要判斷下游任務數據情況,來決定是否fine tune。若數據量很大,可以試着採用fine tune,如果數據集很小,則不要使用fine tune,否則容易出現上圖的情況。
計算圖和反向傳播
在我們使用深度學習框架搭建神經網絡的時候,深度學習框架在檢查模型無誤後(指類型匹配,維度匹配等),幫我們建立計算圖,以便更新神經網絡參數。每當一個batch的數據送入神經網絡(一個batch的數據往往是多個矩陣或者多個張量),會先沿着計算圖前向傳播,目的是求出最終的結果,即模型輸出。之後,再計算梯度,沿着計算圖反向傳播,更新參數。不同的batch按照此操作,反覆執行,使得神經網絡的參數能夠更好的擬合數據。
下面就介紹一下,計算圖是如何結合上一節提到的梯度,來更新神經網絡的參數的。
計算圖
我們將剛纔的神經網絡以計算圖的形式繪製出來
圖中的結點表示操作,而邊表示運算結果和運算結果的傳遞方向。從輸入到最終結果的傳遞過程稱爲前向傳播。在前向傳播之後,我們可以得到最後的運算結果。在這之後,我們需要根據最後的前一節提到的梯度,更新神經網絡中的各個參數值。
反向傳播
前向傳播之後,沿着計算圖中邊的反方向,逐次計算梯度,並傳播,同時更新參數。
首先會先計算,之後依次計算, 。值得一提的是,各個函數的偏微分已經在建立計算圖的時候,由深度學習框架的自動微分機計算好了,在我們向模型feed數據之後,就可以快速得到偏微分的數值。
傳播方向總是從上游(靠近預測結果)向下遊(靠近輸入)傳遞。如下圖所示,表示了一個節點的計算圖。
可以看到,下游偏微分,這裏使用了到了鏈式法則,其中是來自上游計算的梯度,而是來自本地(本節點)的梯度。不難得出,下游梯度=上游梯度×本地梯度。這也可以說明,反向傳播應該從模型輸出結果一端計算到模型輸入一端。(此處的上游和下游與NLP預訓練任務的上游和下游不同)
如果一個計算圖中的節點的輸入有多個,只需要對不同的輸入分別計算,與單個並無差異(如下圖),
這裏有一個具體的例子。
需要注意的是,要對max函數進行分類討論,來確定其偏導數。而輸入節點y有兩條邊,反向傳播需要求和。
通常來說,一個計算圖是一個有向無環圖,在前向傳播時按照拓撲序處理每個節點(拓撲序可以參見算法拓撲排序),而在反向傳播時按照逆拓撲序處理節點。其時間複雜度是相同的。現在有了深度學習框架的加持,不需要手動計算偏微分,不需要手動求導,而在神經網絡的早期,還需要使用這樣的方法來計算導數()。由於需要對每個參數使用式子計算,故計算時間很長,速度很慢。現在多爲向量化和矩陣化的參數計算,可以大大提高運行效率和計算速度。
技巧
正則化
由於深度神經網絡很強大,會導致模型對於訓練集擬合的太好,對於新樣本的泛化能力下降,出現過擬合的情況。此時,可以選擇在損失函數後加上正則化項,來避免這種情況。
(紫色框中爲正則化項)
問題來了,爲什麼正則化可以減輕過擬合呢?我分享兩種淺顯的理解方式,也歡迎各位分享自己見解(知乎問答:機器學習中使用正則化來防止過擬合是什麼原理?)。
- 以曲線擬合任務爲例,過擬合可以看作是模型學習出的曲線太好了,儘管經過了每一個點,但是不平滑,很扭曲。神經網絡的強大之處在於其的參數空間很大,在損失函數中加入正則項,限制了其參數空間,學得的曲線不能像原來那樣“隨意伸展”,降低了過擬合的風險。
- 還以曲線擬合爲例,過擬合曲線在樣本點的導數都很大(因爲很扭曲),有時導數大的原因是係數很大,添加正則化項之後,限制了係數,曲線也不能像原來那樣扭曲了,降低過擬合的風險。
向量化和矩陣化
在實現神經網絡的時,儘量使用向量和矩陣運算,避免使用循環。一是因爲深度學習框架對向量和矩陣運算有優化,二是因爲在訓練時使用的硬件(GPU和TPU)從結構上可以快速處理矩陣運算。
參數初始化
一般可以選擇隨機初始化爲小數,正態分佈初始化或者Xavier初始化。
優化器
可以選擇SGD(隨機梯度下降),現在可以一般都採用Adam優化器,經常廣泛用於各個模型優化(Adam優化器介紹)。
學習速率
如果使用的是SGD(隨機梯度下降),一般需要逐漸降低學習速率,使模型較好的收斂,如,其中爲初始的學習速率,,爲一個設定的常數,爲epoch(epoch指的是訓練數據訓練多少遍,如50個epoch就表示將訓練集反覆送如模型50遍,這樣的做的目的是確保模型擬合數據並且收斂)。
如果使用的是Adam等高級優化器,則不需要手動調整,只需要設定一個初始學習速率,優化器會根據計算的二階矩自動調整學習速率。
對於學習速率初值的選擇,沒有固定答案,需要根據模型和經驗選擇。當初始學習速率過大的時候,會出現梯度爆炸現象(即訓練過程中提示有值變爲NaN或者Inf)。當初始學習速率過小,會導致學習速度緩慢,模型效果提升緩慢等結果。可以先嚐試一個值,再根據結果做調整。