〖TensorFlow2.0筆記25〗循環神經網絡RNN原理講解以及實戰!

循環神經網絡RNN原理講解以及實戰!

一. 引言

  • 卷積神經網絡利用數據的局部相關性權值共享的思想大大減少了網絡的參數量,非常適合於圖片這種具有空間(Spatial)局部相關性的數據,已經被成功地應用到計算機視覺領域的一系列任務上。自然界的信號除了具有空間維度之外,還有一個時間(Temporal)維度。具有時間維度的信號非常常見,比如我們正在閱讀的文本、說話時發出的語音信號、隨着時間變化的股市參數等。這類數據並不一定具有局部相關性,同時數據在時間維度上的長度也是可變的,卷積神經網絡並不擅長處理此類數據。

二. 序列的表示

2.1. 序列(Sequence)

  • 首先我們來介紹對於具有時間先後順序的數據的表示方法。具有先後順序的數據一般叫作序列(Sequence)
  • 對於一個非數值類型的信號如何轉換成數值信號,比如常見的文本信號,怎樣把這樣的String類型轉換成數值類型。

我們把文字編碼爲數值的過程叫作Word Embedding。One-hot 的編碼方式實現Word Embedding 簡單直觀,編碼過程不需要學習和訓練。但是One-hot 編碼的向量是高維度而且極其稀疏的,大量的位置爲0,計算效率較低,同時也不利於神經網絡的訓練。從語義角度來講,One-hot 編碼還有一個嚴重的問題,它忽略了單詞先天具有的語義相關性。舉個例子,對於單詞“like”、“dislike”、“Rome”、“Paris”來說,“like”和 dislike”在語義角度就強相關,它們都表示喜歡的程度;“Rome”和“Paris”同樣也是強相關,他們都表示歐洲的兩個地點。對於一組這樣的單詞來說,如果採用One-hot 編碼,得到的向量之間沒有相關性,不能很好地體現原有文字的語義相關度,因此One-hot 編碼具有明顯的缺陷。

  • 什麼是 word embedding:通俗的翻譯可以認爲是單詞嵌入,就是把 X\mathbf X 所屬空間的單詞映射爲到 Y\mathbf Y 空間的多維向量,那麼該多維向量相當於嵌入到 Y\mathbf Y 所屬空間中,一個蘿蔔一個坑。之乎大神:什麼是 word embedding?

2.2. Tensorflow2.0中的Embedding層

  • 在神經網絡中,單詞的表示向量可以直接通過訓練的方式得到,我們把單詞的表示層叫作Embedding 層。Embedding 層負責把單詞編碼爲某個詞向量 v\boldsymbol{v},它接受的是採用數字編碼的單詞編號 ii,如2 表示“I”,3 表示“me”等,系統總單詞數量記爲 NvocabN_{vocab},輸出長度爲 nn 的向量 v\boldsymbol{v}v=fθ(iNvocab ,n)(1)\boldsymbol{v}=f_{\theta}\left(i | N_{\text {vocab }}, n\right)\tag{1}
  • Embedding 層實現起來非常簡單,構建一個shape 爲[Nvocab ,n]\left[N_{\text {vocab }}, n\right]的查詢表對象table,對於任意的單詞編號 ii,只需要查詢到對應位置上的向量並返回即可:v=table[i](2)\boldsymbol{v}=table[i]\tag{2}
  • Embedding 層是可訓練的,它可放置在神經網絡之前,完成單詞到向量的轉換,得到的表示向量可以繼續通過神經網絡完成後續任務,並計算誤差,採用梯度下降算法來實現端到端(end-to-end)的訓練。
  • 在 TensorFlow 中,可以通過layers.Embedding(NvocabN_{vocab},nn)來定義一個Word Embedding層,其中 NvocabN_{vocab} 參數指定詞彙數量nn 爲指定單詞向量的長度。例如:
x = tf.range(10) # 生成10 個單詞的數字編碼
x = tf.random.shuffle(x) # 打散
# 創建共10 個單詞,每個單詞用長度爲4 的向量表示的層
net = layers.Embedding(10, 4)
out = net(x) # 獲取詞向量
  • 上述代碼創建了10個單詞的Embedding 層,每個單詞用長度爲4的向量表示,可以傳入數字編碼爲0~9的輸入,得到這4 個單詞的詞向量,這些詞向量隨機初始化的,尚未經過網絡訓練,例如:
<tf.Tensor: id=96, shape=(10, 4), dtype=float32, numpy=
array([[-0.00998075, -0.04006485, 0.03493755, 0.03328368],
       [-0.04139598, -0.02630153, -0.01353856, 0.02804044],
  • 我們可以直接查看Embedding 層內部的查詢表table:
In [1]: net.embeddings
Out[1]:
<tf.Variable 'embedding_4/embeddings:0' shape=(10, 4) dtype=float32, numpy=
array([[ 0.04112223, 0.01824595, -0.01841902, 0.00482471],
[-0.00428962, -0.03172196, -0.04929272, 0.04603403],
  • 並查看net.embeddings 張量的可優化屬性爲True,即可以通過梯度下降算法優化。
In [2]: net.embeddings.trainable
Out[2]:True

2.3. 預訓練的詞向量

  • Embedding 層的查詢表是隨機初始化的,需要從零開始訓練。實際上,我們可以使用預訓練的Word Embedding 模型來得到單詞的表示方法,基於預訓練模型的詞向量相當於遷移了整個語義空間的知識,往往能得到更好的性能。
  • 目前應用的比較廣泛的預訓練模型有 Word2Vec 和 GloVe 等。它們已經在海量語料庫訓練得到了較好的詞向量表示方法,並可以直接導出學習到的詞向量表,方便遷移到其它任務。比如 GloVe 模型GloVe.6B.50d,詞彙量爲40 萬,每個單詞使用長度爲50 的向量表示,用戶只需要下載對應的模型文件即可,“glove6b50dtxt.zip”模型文件約69MB。
  • 那麼如何使用這些預訓練的詞向量模型來幫助提升NLP 任務的性能?非常簡單,對於Embedding 層,不再採用隨機初始化的方式,而是利用我們已經預訓練好的模型參數去初始化 Embedding 層的查詢表。 例如:
# 從預訓練模型中加載詞向量表
embed_glove = load_embed('glove.6B.50d.txt')
# 直接利用預訓練的詞向量表初始化Embedding 層
net.set_weights([embed_glove])
  • 經過預訓練的詞向量模型初始化的Embedding 層可以設置爲不參與訓練:net.trainable= False,那麼預訓練的詞向量就直接應用到此特定任務上;如果希望能夠學到區別於預訓練詞向量模型不同的表示方法,那麼可以把Embedding 層包含進反向傳播算法中去,利用梯度下降來微調單詞表示方法。

三. 循環神經網絡

  • 現在我們來考慮如何處理序列信號,以文本序列爲例,考慮一個句子 :“I hate this boring movie”。
  • 通過Embedding 層,可以將它轉換爲shape 爲 [b,s,n][b,s,n] 的張量,bb 爲句子數量,ss 爲句子長度,nn 爲詞向量長度。上述句子可以表示爲shape 爲 [1,5,10][1,5,10]的張量,其中5代表句子單詞長度,10 表示詞向量長度。

3.1. 全連接層可行嗎

  • 2大缺陷:
  • 1、網絡參數量是相當可觀的,內存佔用和計算代價較高,同時由於每個序列的長度 ss 並不相同,網絡結構是動態變化的。
  • 2、每個全連接層子網絡 Wi\boldsymbol{W_i}bi\boldsymbol{b_i} 只能感受當前詞向量的輸入,並不能感知之前和之後的語境信息,導致句子整體語義的缺失,每個子網絡只能根據自己的輸入來提取高層特徵。

3.2. 權值共享解決問題1

  • 在介紹卷積神經網絡時,我們就比較過,卷積神經網絡之所以在處理局部相關數據時優於全連接網絡,是因爲它充分利用了權值共享的思想,大大減少了網絡的參數量,使得網絡訓練起來更加高效。那麼,我們在處理序列信號的問題上,能否借鑑權值共享的思想呢?

  • 我們嘗試將這 ss 個網絡層參數共享,這樣其實相當於使用一個全連接網絡來提取所有單詞的特徵信息,如下圖所示:

  • 通過權值共享後,參數量大大減少,網絡訓練變得更加穩定高效。但是,這種網絡結構並沒有考慮序列之間的先後順序,將詞向量打亂次序仍然能獲得相同的輸出,無法獲取有效的全局語義信息。

3.3. 內存機制解決問題2

  • 如何賦予網絡提取整體語義特徵的能力呢?或者說,如何讓網絡能夠按序提取詞向量的語義信息,並累積成整個句子的全局語義信息呢?我們想到了內存(Memory)機制。如果網絡能夠提供一個單獨的內存變量,每次提取詞向量的特徵並刷新內存變量,直至最後一個輸入完成,此時的內存變量即存儲了所有序列的語義特徵,並且由於輸入序列之間的先後順序,使得內存變量內容與序列順序緊密相連。如下圖未添加偏置:
  • 我們將上述Memory 機制實現爲一個狀態張量 ,如圖上圖所示,除了原來的 Wxh\boldsymbol{W}_{xh} 參數共享外,這裏額外增加了一個和 Whh\boldsymbol{W}_{hh} 參數,每個時間戳 tt上狀態張量刷新機制爲:ht=σ(Wxhxt+Whhht1+b)(3)\boldsymbol{h}_{t}=\sigma\left(\boldsymbol{W}_{x h} \boldsymbol{x}_{t}+\boldsymbol{W}_{h h} \boldsymbol{h}_{t-1}+\boldsymbol{b}\right)\tag{3}
  • 其中狀態張量 h0\boldsymbol{h}_{0} 初始的內存狀態,可以初始化爲全0,經過𝑠個詞向量的輸入後得到網絡最終的狀態張量 hs\boldsymbol{h}_{s}hs\boldsymbol{h}_{s}較好地代表了句子的全局語義信息,基於 hs\boldsymbol{h}_{s} 通過某個全連接層分類器即可完成情感分類任務。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章