CS224n 深度自然語言處理(四) Note - Backpropagation and computation graphs

本文爲筆者學習CS224N所做筆記,所包含內容不限於課程課件和講義,還包括筆者對機器學習、神經網絡的一些理解。所寫內容難免有難以理解的地方,甚至可能有錯誤。如您在閱讀中有疑惑或者建議,還望留言指正。筆者不勝感激!

在本章中,將着重討論以下內容:

  1. 如何更新神經網絡參數?
  2. 以何種形式保存更新結構?
  3. 搭建和訓練神經網絡的技巧.

梯度和導數

上一章提到,應該最小化損失函數。損失函數的參數是神經網絡參數,由於梯度的方向是函數上升最快的方向,故若想最小化損失函數,應該按負梯度方向更新參數,即梯度下降。而爲了求解損失函數對參數的梯度,就涉及到了微分的問題。

梯度計算

對於上一章提出的簡單的神經網絡分類器,有如下的形式:

在這裏插入圖片描述

現在計算sW\frac{\partial s}{\partial W},根據鏈式法則,有
sW=shhzzW \frac{\partial s}{\partial W}=\frac{\partial s}{\partial h}·\frac{\partial h}{\partial z}·\frac{\partial z}{\partial W}
此處s,W,h,zs,W,h,z均爲矩陣或者向量的形式,涉及到矩陣求導,較爲繁瑣。爲了簡單清楚的闡述其原理,我們求對於WW中某個特定元素的求導規則,即計算sWij\frac{\partial s}{\partial W_{ij}}。同時,我們神經網絡用圖的方式更加詳細的表示出來。

在這裏插入圖片描述

再做一個簡化,令sW\frac{\partial s}{\partial W}鏈式法則展開的前兩項爲δ\delta,關注zW\frac{\partial z}{\partial W},即
sW=δzW=δWWx+b \frac{\partial s}{\partial W}=\delta\frac{\partial z}{\partial W}=\delta \frac{\partial}{\partial W}Wx+b
我們考慮ziz_i對於一個矩陣權重WijW_{ij}的微分,
KaTeX parse error: No such environment: align* at position 8: \begin{̲a̲l̲i̲g̲n̲*̲}̲ \frac{z_i}{\pa…
故對於一個權重值WijW_{ij}sWij=δixj\frac{\partial s}{\partial W_{ij}}=\delta_{i}x_j,其中xjx_j與輸入有關,叫做局部梯度信號,而δi\delta_i和誤差有關,叫做誤差信號。

對於sW=δTxT\frac{\partial s}{\partial W}=\delta^T x^T,最終的維度爲n×mn\times m,其中nn爲隱層神經元數量,上圖中爲2,mm爲輸入層神經元數量,上圖爲33(也可以直接根據矩陣求導求得)。

滑動窗口輸入的梯度計算

上一小節圖片中的模型考慮到的是輸入爲一個詞向量的情況,而對於滑動窗口模型而言,輸入爲多個詞向量。可以將每個詞的詞向量分開考慮,這樣做的原因是考慮到可以對已經訓練好的詞向量做fine-tune(微調),則有
δwindow=[xmuseumsxinxParisxarexamazing] \delta_{window}= \begin{aligned} \left[ \begin{matrix} \nabla x_{museums} \\ \nabla x_{in} \\ \nabla x_{Paris} \\ \nabla x_{are} \\ \nabla x_{amazing} \end{matrix} \right] \end{aligned}
xJ=WTδ=δxwindow\nabla_{x}J =W^T\delta = \delta·x_{window}.在fine tune過程中,對神經網絡參數訓練的同時,也會調整詞向量。

在對詞向量做fine-tune之前也要考慮一些問題,例如我們要使用單個詞彙訓練電影評論情感分類模型,在訓練集中出現了"TV"和"telly",但是沒有出現"television",在測試集中只出現了"television",卻沒有出現"TV"和"telly";換言之,訓練集和測試集的樣本分佈不均衡。如果在這種情況下依舊對詞向量進行fine tune,會導致詞的分類錯誤。如下面兩幅圖所示。

在這裏插入圖片描述
在這裏插入圖片描述
如果使用已經訓練好的詞向量,需要判斷下游任務數據情況,來決定是否fine tune。若數據量很大,可以試着採用fine tune,如果數據集很小,則不要使用fine tune,否則容易出現上圖的情況。

計算圖和反向傳播

在我們使用深度學習框架搭建神經網絡的時候,深度學習框架在檢查模型無誤後(指類型匹配,維度匹配等),幫我們建立計算圖,以便更新神經網絡參數。每當一個batch的數據送入神經網絡(一個batch的數據往往是多個矩陣或者多個張量),會先沿着計算圖前向傳播,目的是求出最終的結果,即模型輸出。之後,再計算梯度,沿着計算圖反向傳播,更新參數。不同的batch按照此操作,反覆執行,使得神經網絡的參數能夠更好的擬合數據。

下面就介紹一下,計算圖是如何結合上一節提到的梯度,來更新神經網絡的參數的。

計算圖

我們將剛纔的神經網絡以計算圖的形式繪製出來
s=uThh=f(z)z=Wx+bx(input) s=u^Th \\ h=f(z) \\ z=Wx+b \\ x(input)
在這裏插入圖片描述

圖中的結點表示操作,而邊表示運算結果和運算結果的傳遞方向。從輸入xx到最終結果ss的傳遞過程稱爲前向傳播。在前向傳播之後,我們可以得到最後的運算結果ss。在這之後,我們需要根據最後的前一節提到的梯度,更新神經網絡中的各個參數值。

反向傳播

前向傳播之後,沿着計算圖中邊的反方向,逐次計算梯度,並傳播,同時更新參數。

在這裏插入圖片描述

首先會先計算su\frac{\partial s}{\partial u},之後依次計算sh\frac{\partial s}{\partial h}, sz,sb\frac{\partial s}{\partial z}, \frac{\partial s}{\partial b}。值得一提的是,各個函數的偏微分已經在建立計算圖的時候,由深度學習框架的自動微分機計算好了,在我們向模型feed數據之後,就可以快速得到偏微分的數值。

傳播方向總是從上游(靠近預測結果)向下遊(靠近輸入)傳遞。如下圖所示,表示了一個節點ff的計算圖。

在這裏插入圖片描述

可以看到,下游偏微分sz=shsz\frac{\partial s}{\partial z}=\frac{\partial s}{\partial h} · \frac{\partial s}{\partial z},這裏使用了到了鏈式法則,其中sh\frac{\partial s}{ \partial h}是來自上游計算的梯度,而hz\frac{\partial h}{\partial z}是來自本地(本節點)的梯度。不難得出,下游梯度=上游梯度×本地梯度。這也可以說明,反向傳播應該從模型輸出結果一端計算到模型輸入一端。(此處的上游和下游與NLP預訓練任務的上游和下游不同)

如果一個計算圖中的節點的輸入有多個,只需要對不同的輸入分別計算,與單個並無差異(如下圖),

在這裏插入圖片描述

這裏有一個具體的例子。

在這裏插入圖片描述

需要注意的是,要對max函數進行分類討論,來確定其偏導數。而輸入節點y有兩條邊,反向傳播需要求和。

通常來說,一個計算圖是一個有向無環圖,在前向傳播時按照拓撲序處理每個節點(拓撲序可以參見算法拓撲排序),而在反向傳播時按照拓撲序處理節點。其時間複雜度是相同的。現在有了深度學習框架的加持,不需要手動計算偏微分,不需要手動求導,而在神經網絡的早期,還需要使用f(x)=f(x+h)f(xh)2hf'(x)=\frac{f(x+h)-f(x-h)}{2h}這樣的方法來計算導數(x=1e4x=1e-4)。由於需要對每個參數使用式子計算,故計算時間很長,速度很慢。現在多爲向量化和矩陣化的參數計算,可以大大提高運行效率和計算速度。

技巧

正則化

由於深度神經網絡很強大,會導致模型對於訓練集擬合的太好,對於新樣本的泛化能力下降,出現過擬合的情況。此時,可以選擇在損失函數後加上正則化項,來避免這種情況。

在這裏插入圖片描述

(紫色框中爲正則化項)

問題來了,爲什麼正則化可以減輕過擬合呢?我分享兩種淺顯的理解方式,也歡迎各位分享自己見解(知乎問答:機器學習中使用正則化來防止過擬合是什麼原理?)。

  1. 以曲線擬合任務爲例,過擬合可以看作是模型學習出的曲線太好了,儘管經過了每一個點,但是不平滑,很扭曲。神經網絡的強大之處在於其的參數空間很大,在損失函數中加入正則項,限制了其參數空間,學得的曲線不能像原來那樣“隨意伸展”,降低了過擬合的風險。
  2. 還以曲線擬合爲例,過擬合曲線在樣本點的導數都很大(因爲很扭曲),有時導數大的原因是係數很大,添加正則化項之後,限制了係數,曲線也不能像原來那樣扭曲了,降低過擬合的風險。

向量化和矩陣化

在實現神經網絡的時,儘量使用向量和矩陣運算,避免使用循環。一是因爲深度學習框架對向量和矩陣運算有優化,二是因爲在訓練時使用的硬件(GPU和TPU)從結構上可以快速處理矩陣運算。

參數初始化

一般可以選擇隨機初始化爲小數,正態分佈初始化或者Xavier初始化。

優化器

可以選擇SGD(隨機梯度下降),現在可以一般都採用Adam優化器,經常廣泛用於各個模型優化(Adam優化器介紹)。

學習速率

如果使用的是SGD(隨機梯度下降),一般需要逐漸降低學習速率,使模型較好的收斂,如lr=lr0ektlr=lr_0e^{-kt},其中r0r_0爲初始的學習速率,,kk爲一個設定的常數,tt爲epoch(epoch指的是訓練數據訓練多少遍,如50個epoch就表示將訓練集反覆送如模型50遍,這樣的做的目的是確保模型擬合數據並且收斂)。

如果使用的是Adam等高級優化器,則不需要手動調整,只需要設定一個初始學習速率,優化器會根據計算的二階矩自動調整學習速率。

對於學習速率初值的選擇,沒有固定答案,需要根據模型和經驗選擇。當初始學習速率過大的時候,會出現梯度爆炸現象(即訓練過程中提示有值變爲NaN或者Inf)。當初始學習速率過小,會導致學習速度緩慢,模型效果提升緩慢等結果。可以先嚐試一個值,再根據結果做調整。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章