一、為什么選擇序列模型
序列模型可以用於很多領域,如語音識別,撰寫文章等等。總之很多優點。。。
二、數學符號
為了后面方便說明,先將會用到的數學符號進行介紹。
以下圖為例,假如我們需要定位一句話中人名出現的位置。
- 紅色框中的為輸入、輸出值。可以看到人名輸出用1表示,反之用0表示;
- 綠色框中的\(x^{<t>},y^{<t>}\)表示對應紅色框中的輸入輸出值的數學表示,注意從1開始。
- 灰色框中的\(T_x,T_y\)分別表示輸入輸出序列的長度,在該例中,\(T_x=9,T_y=9\)
- 黃色框中\(X^{(i)<t>}\)上的表示第i個輸入樣本的第t個輸入值,\(T_x^{(i)}\)則表示第i個輸入樣本的長度。輸出y也同理。

輸入值中每個單詞使用One-shot來表示。即首先會構建一個字典(Dictionary),假設該例中的字典維度是10000*1(如圖示)。第一個單詞"Harry"的數學表示形式即為[0,0,0,……,1 (在第4075位) ,0,……,0],其他單詞同理。
但是如果某一個單詞並沒有被包含在字典中怎么辦呢?此時我們可以添加一個新的標記,也就是一個叫做Unknown Word的偽造單詞,用 <UNK> 表示。具體的細節會在后面介紹。

三、循環神經網絡模型
1.為什么不用標准網絡
在介紹RNN之前,首先解釋一下為什么之前的標准網絡不再適用了。因為它有兩個缺點:
- 輸入和輸出的長度不盡相同
- 無法共享從其他位置學來的特征。例如上一節中的Harry這個詞是用\(x^{<1>}\)表示的,網絡從該位置學習了它是一個人名。但是我們希望無論Harry在哪個位置出現網絡都能識別出這是一個人名的一部分,而標准網絡無法做到這一點。

2.RNN結構
還是以識別人名為例,第一個單詞\(x^{<1>}\)輸入神經網絡得到輸出\(y^{<1>}\)

同理由\(x^{<2>}\)將得到\(y^{<2>}\),以此類推。但是這就是傳統網絡存在的問題,即單詞之間沒有聯系

為了將單詞之間關聯起來,所以將前一層的結果也作為下一層的輸入數據。如下圖示

整體的RNN結構有兩種表示形式,如下圖示
左邊是完整的表達形式,注意第一層的\(a^{<0>}\)一般設置為0向量。
右邊的示意圖是RNN的簡寫示意圖。

介紹完結構之后,我們還需要知道網絡中參數的表達方式及其含義。如下圖示,\(x^{<i>}\)到網絡的參數用\(W_{ax}\)表示,\(a^{<i>}\)到網絡的參數用\(W_{aa}\)表示,\(y^{<i>}\)到網絡的參數用\(W_{ya}\)表示,具體含義將在下面進行說明。
如下圖示,\(x^{<1>}\)通過網絡可以傳遞到\(y^{<3>}\),但是這存在一個問題,即每個輸出只與前面的輸入有關,而與后面的無關。這個問題會在后續內容中進行改進。

3.RNN前向傳播
如圖示,\(a^{<0>}=\vec{0}\)
激活函數:\(g_1\)一般為tanh函數或者是Relu函數,\(g_2\)一般是Sigmod函數。
- \(a^{<1>}=g_1(W_{aa}a^{<0>}+W_{ax}x^{<1>}+b_a)\)
- \(y^{<1>}=g_2(W_{ya}a^{<1>}+b_y)\)
- \(a^{<t>}=g_1(W_{aa}a^{<t-1>}+W_{ax}x^{<t>}+b_a)\)
- \(y^{<t>}=g_2(W_{ya}a^{<t>}+b_y)\)
注意參數的下標是有順序含義的,如\(W_{ax}\)下標的第一個參數表示要計算的量的類型,即要計算\(a\)矢量,第二個參數表示要進行乘法運算的數據類型,即需要與\(x\)矢量做運算。如 \(W_{ax} x^{t}\rightarrow{a}\)

4.簡化RNN公式
下面將對如下公式進行化簡:

- 1. 簡化\(a^{<t>}\)

注意,公式中使用了兩個矩陣進行化簡,分別是 \(W_a\)和\([a^{<t-1>},x^{<t>}]^T\)(使用轉置符號更易理解),下面分別進行說明:
- \(W_a = [ W_{aa}, W_{ax}]\),假設\(W_{aa}\)是(100,100)的矩陣,\(W_{ax}\)是(100,10000)的矩陣,那么\(W\)則是(100,10100)的矩陣。

- \([a^{<t-1>},x^{<t>}]^T\)是下圖示意。

故\(W_a [a^{<t-1>},x^{<t>}]^{T}\)矩陣計算如下圖示

- 2.簡化\(y^{<t>}\)

該節PPT內容:

四、通過時間的反向傳播
下面將會對反向傳播進行灰常灰常詳細的介紹,跟着下面一張一張的圖片走起來~
1.整體感受
- 首先再回顧一下RNN的整體結構

- 要進行反向傳播,首先需要前向傳播,傳播方向如藍色箭頭所示,其次再按照紅色箭頭進行反向傳播。

2.前向傳播
- 首先給出所有輸入數據,即從\(x^{<1>}\)到\(x^{<T_x>}\),\(T_x\)表示輸入數據的數量。

- 初始化參數\(W_a,b_a\),將輸入數據輸入網絡得到對應的\(a^{<t>}\)

- 再通過與初始化參數\(W_y,b_y\)得到\(y^{<t>}\)

3.損失函數定義
要進行反向傳播,必須得有損失函數嘛,所以我們將損失函數定義如下:
- 每個節點的損失函數
\(L^{<t>}(\hat{y}^{<t>},y^{<t>})=y^{<t>}log(y^{<t>})-(1-y^{<t>})log(1-\hat{y}^{<t>})\)
- 整個網絡的損失函數
\(L(\hat{y}^{<t>},y^{<t>)}) = \sum_{t=1}^{T_y}L^{<t>}(\hat{y}^{<t>},y^{<t>})\)

4.反向傳播
計算出損失值后再通過梯度下降進行反向傳播

5.整個流程圖

五、不同類型的循環神經網絡
本節主要介紹了其他更多類型的RNN結構,下圖參考大數據文摘

六、語言模型和序列生成
1.什么是語言模型
凡事開頭舉個栗子,一切都好說:
假設一個語音識別系統聽一句話得到了如下兩種選擇,作為正常人肯定會選擇第二種。但是機器才如何做判斷呢?

此時就需要通過語言模型來預測每句話的概率:

2.如何使用RNN構建語言模型
- 首先我們需要一個很大的語料庫(Corpus)
- 將每個單詞字符化(Tokenize,即使用One-shot編碼)得到詞典,,假設有10000個單詞
- 還需要添加兩個特殊的單詞
-
: end of sentence. 終止符,表示句子結束.
-
: UNknown, 之前的筆記已介紹過.
-
3.構建語言模型示例
假設要對這句話進行建模:Cats average 15 hours of sleep a day. <EOS>
- 1.初始化
這一步比較特殊,即\(x^{<1>}\)和\(a^{<0>}\)都需要初始化為\(\vec{0}\)。
此時\(\hat{y}^{<1>}\)將會對第一個字可能出現的每一個可能進行概率的判斷,即\(\hat{y}^{<1>}=[p(a),…,p(cats),…]\)。
當然在最開始的時候沒有任何的依據,可能得到的是完全不相干的字,因為只是根據初始的值和激活函數做出的取樣。

- 2.將真實值作為輸入值
之所以將真實值作為輸入值很好理解,如果我們一直傳錯誤的值,將永遠也無法得到字與字之間的關系。
如下圖示,將\(y^{<1>}\)所表示的真實值Cats作為輸入,即\(x^{<2>}=y^{<1>}\)得到\(\hat{y}^{<2>}\)。
此時的\(\hat{y}^{<2>}=[p(a|cats),…,p(average|cats),…]\)。
同理有\(\hat{y}^{<3>}=[p(a|cats\, average),…,p(average|cats\,average),…]\)
另外輸入值滿足: \(x^{<t>}=y^{<t-1>}\)

- 3.計算出損失值
下圖給出了構建模型的過程以及損失值計算公式。

七、對新序列采樣
當我們訓練得到了一個模型之后,如果我們想知道這個模型學到了些什么,一個非正式的方法就是對新序列進行采樣。具體方法如下:
在每一步輸出\(\hat{y}\)時,通常使用 softmax 作為激活函數,然后根據輸出的分布,隨機選擇一個值,也就是對應的一個字或者英文單詞。
然后將這個值作為下一個單元的x輸入進去(即\(x^{<t>}=\hat{y}^{<t-1>}\)), 直到我們輸出了終結符,或者輸出長度超過了提前的預設值n才停止采樣。.
上述步驟具體如圖示:

下圖給出了采樣之后得到的效果:
左邊是對訓練得到新聞信息模型進行采樣得到的內容;
右邊是莎士比亞模型采樣得到的內容。


八、帶有神經網絡的梯度消失
1.RNN的梯度消失、爆炸問題
梯度值在RNN中也可能因為反向傳播的層次太多導致過小或者過大。
- 當梯度值過小的時候,神經網絡將無法有效地調整自己的權重矩陣導致訓練效果不佳,稱之為“梯度消失問題”(gradient vanishing problem);
- 過大時可能直接影響到程序的運作因為程序已經無法存儲那么大的值,直接返回 NaN ,稱之為“梯度爆炸問題”(gradient exploding problem)。
當梯度值過大的時候有一個比較簡便的解決方法,每次將返回的梯度值進行檢查,如果超出了預定的范圍,則手動設置為范圍的邊界值。
if (gradient > max) {
gradient = max
}
但梯度值過小的解決方案要稍微復雜一點,比如下面兩句話:
“The cat,which already ate apple,yogurt,banana,..., was full.”
“The cats,which already ate apple,yogurt,banana,..., were full.”
重點標出的 cat(s)和be動詞(was,were) 是有很重要的關聯的,但是中間隔了一個which引導的定語從句,對於前面所介紹的基礎的RNN網絡很難學習到這個信息,尤其是當出現梯度消失時,而且這種情況很容易發生。
我們知道一旦神經網絡層次很多時,反向傳播很難影響前面層次的參數。所以為了解決梯度消失問題,提出了GRU單元,下面一節具體介紹。
九、GRU單元
GRU(Gated Recurrent Unit)是一種用來解決梯度值過小的方法,首先來看下在一個時刻下的RNN單元,激活函數為 tanh
1.首先回顧一下普通RNN單元的結構示意圖
如圖示,輸入數據為\(a^{<t-1>}\)和\(x^{<t>}\),與參數\(W_a\)進行線性運算后再使用tanh函數轉化得到\(a^{<t>}\). 當然再使用softmax函數處理可以得到預測值。

2.GRU結構
- 記憶細胞
在GRU中會用到 “記憶細胞(Memory cell)” 這個概念,我們用變量\(c\)表示。這個記憶細胞提供了記憶功能,例如它能夠幫助記住 cat對應was,cats對應were。
而在t時刻,記憶細胞所包含的值其實就是激活函數值,即\(c^{<t>}=a^{<t>}\)。
注意:在這里兩個變量的值雖然一樣,但是含義不同。另外在下節將介紹的LSTM中,二者值的大小有可能是不一樣的,所以有必要使用這兩種變量進行區分。
為了更新記憶細胞的值,我們引入\(\tilde{c}\)來作為候選值從而來更新\(c^{<t>}\),其公式為:
- 更新門(update gate)
更新門是GRU的核心概念,它的作用是用於判斷是否需要進行更新。
更新門用\(\Gamma_u\)表示,其公式為:

如上圖示,\(\Gamma_u\)值的大小大多分布在0或者1,所以可以將其值的大小粗略的視為0或者1。這就是為什么我們就可以將其理解為一扇門,如果\(\Gamma_u=1\),就表示此時需要更新值,反之不用。
- t時刻記憶細胞
有了更新門公式后,我們則可以給出t時刻記憶細胞的值的計算公式了:
注意:上面公式中的 * 表示元素之間進行乘法運算,而其他公式是矩陣運算。
公式很好理解,如果\(\Gamma_u=1\),那么t時刻記憶細胞的值就等於候選值\(\tilde{c}\),反之等於前一時刻記憶細胞的值。
下圖給出了該公式很直觀的解釋:
在讀到“cat”的時候 ,其他時候一直為0,知道要輸出“was”的時刻我們仍然知道“cat”的存在,也就知道它為單數了。

- GRU結構示意圖

3.完整版GRU
上述是簡化了的GRU,在完整版中還存在另一個符號 ,這個符號的意義是控制\(\tilde{c}\)和\(c^{<t-1>}\)之間的聯系強弱,完整版公式如下:

注意,完整公式中多出了一個\(\Gamma_r\),這個符號的作用是控制\(\tilde{c}^{<t>}\)與\(c^{<t>}\)之間聯系的強弱。
十、長短期記憶
介紹完GRU后,再介紹LSTM會更加容易理解。下圖是二者公式對比:
GRU只有兩個門,而LSTM有三個門,分別是更新門\(\Gamma_u\),遺忘門\(\Gamma_f\),輸出門\(\Gamma_o\)


雖然LSTM比GRU更復雜,但是它比GRU更早提出哦。另外一般而言LSTM的表現要更好,但是計算量更大,畢竟多了一個門嘛。而GRU實際上是對LSTM的簡化,它的表現也不錯,能夠更好地擴展到深層網絡。所以二者各有優勢。
下圖是LSTM的結構示意圖:

十一、雙向遞歸神經網絡
前面介紹的都是單向的RNN結構,在處理某些問題上得到的效果不盡人意
如下面兩句話,我們要從中標出人名:
He said, "Teddy Roosevelt was a great President".
He said, "Teddy bears are on sale".
第一句中的Teddy Roosevelt是人名,但第二句中的Teddy bears是泰迪熊,同樣都是單詞Teddy對應的輸出在第一句中應該是1,第二句中應該是0。
像這樣的例子如果想讓我們的序列模型明白就需要借助不同的結構比如 - 雙向遞歸神經網絡(Bidirectional RNN)。該神經網絡首先從正面理解一遍這句話,再從反方向理解一遍。
雙向遞歸神經網絡結構如下:

下圖摘自大數據文摘整理

十二、深層循環神經網絡
深層,顧名思義就是層次增加。如下圖是深層循環神經網絡的示意圖
橫向表示時間展開,縱向則是層次展開。

注意激活值的表達形式有所改變,以\(a^{[1]<0>}\)為例進行解釋:
- [1]表示第一層
- <0>表示第一個激活值
另外各個激活值的計算公式也略有不同,以\(a^{[2]<3>}\)為例,其計算公式如下: