QANet: Combining Local Convolution With Global Self-Attention For Reading Comprehension

博主標記版paper下載地址:zsweet github
關於paper,在進入正題之前先吐槽一下,論文中說的所有矩陣都是按照tensorflow源碼中的形勢,所以row和column的在讀論文時自己切換一下。。。

1.概述

過去幾年中最成功的模型通常採用了兩項關鍵要技術:

  • 處理順序輸入的循環模型
  • 應對長期交互的注意力要素。

Seo等人於2016年提出的的雙向注意力流(Bidirectional Attention Flow,BiDAF)模型將這兩項要素成功地結合在了一起,該模型在SQuAD數據集上取得了顯著的效果。這些模型的一個缺點是,它們的循環特性使得它們在訓練和推理方面的效率通常較低,特別是對於長文本而言。

QAnet模型設計的主要思想:卷積捕獲文本的局部結構,而自注意力則學習每對單詞之間的全局交互。附加語境疑問注意力(the additional context-query attention)是一個標準模塊,用於爲語境段落中的每個位置構造查詢感知的語境向量(query-aware context vector),這在隨後的建模層中得到使用。

CMU 和 Google Brain 新出的文章,SQuAD 目前的並列第一,兩大特點:

  • 模型方面創新的用 CNN+attention 來完成閱讀理解任務
    在編碼層放棄了 RNN,只採用 CNN 和 self-attention。CNN 捕捉文本的局部結構信息( local interactions),self-attention 捕捉全局關係( global interactions),在沒有犧牲準確率的情況下,加速了訓練(訓練速度提升了 3x-13x,預測速度提升 4x-9x)
  • 數據增強方面通過神經翻譯模型(把英語翻譯成外語(德語/法語)再翻譯回英語)的方式來擴充訓練語料,增加文本多樣性

現在越來越覺得CNN、capsule、transformer相關非NLP技術在NLP領域的強大,以後多嘗試在模型上使用這些結構!

2.模型結構

模型由五層結構組成:

  • input embedding layer
  • embedding encoder layer
  • context-query attention layer
  • model encoder layer
  • output layer

在這裏插入圖片描述

圖2-1.模型結構

2.1.Input embedding layer

Input embedding layer和BIDAF一模一樣
具體順序是:

  • 英文字母隨機初始化每個字母的char-embedding(當然對中文的char-embedding最好是pretrain的),並對query和context進行lookup
  • 對query和context的char-embedding過CNN,提取每個字之間的特徵;
  • 對query和context的pretrain的word-embedding進行lookup
  • word-embedding和char-embedding進行concatenation
  • 對concat的向量過兩層highway,提取並保留原來的特徵。(關於highway可參考博客highway netword

word embedding+character embedding,word embedding從預先訓練好的詞向量中讀取,每個詞向量維度爲p1p_1假設詞w對應的詞向量爲xwx_w
character embedding隨機初始化,維度爲p2p_2,將每個詞的長度padding or truncating到kk,則詞w也可以表示成一個p2kp_2*k的矩陣,經過卷積和max-pooling後得到一個p2p_2維的character-level的詞向量,記爲xcx_c
  將xwx_w​和xcx_c​拼接,得到詞w對應詞向量[xw;xc]Rp1+p2[x_w;x_c]\in{R^{p_1+p_2}}​,最後將拼接的詞向量通過一個兩層的highway network,其輸出即爲embedding層的輸出。訓練過程中,word embedding固定,character embedding隨模型一起訓練。

2.2 Embedding Encoder Layer

重點是這一層上的改變,由一個stacked model encoder block而成(這部分只用了1個stacked model encoder block且裏面只有一個encoder block,每個encoder block裏面4個卷積層,每個卷積層的filter number是128、高度是7),每個 block 的結構是:[convolution-layer x # + self-attention-layer + feed-forward-layer]

單個block結構自底向上依次包含位置編碼(position encoding)卷積(conv)層self attention層前饋網絡(fnn)層,具體參考圖下圖:
在這裏插入圖片描述

圖2-2-1.Encoder block
每個基本操作(conv/self-attention/ffn)都放在殘差塊(residual block)裏,具體各層參數參考原論文。原論文對這裏卷積層和self-attention層的作用解釋是:卷積能夠捕獲上下文局部結構,而self-attention則可以捕捉文本之間全局的互作用

這裏出去CNN之外,幾乎照搬的是transformer,關於transformer可以查看我之前的文章:paper:Attention Is All You Need(模型篇) ,那接下來說下這裏的CNN部分,卷積用的 separable convolutions 而不是傳統的 convolution,因爲更加 memory efficient,泛化能力也更強。核心思想是將一個完整的卷積運算分解爲 Depthwise ConvolutionPointwise Convolution 兩步進行,兩幅圖簡單過一下概念:

  • 先做 depthwise conv, 卷積在二維平面進行,filter 數量等於上一次的 depth/channel,相當於對輸入的每個 channel 獨立進行卷積運算,然後就結束了,這裏沒有 ReLU
    假設輸入是646464*64的3通道圖片,使用3313*3*1大小的卷積核,filter 數量等於上一層的depth,對輸入的每個 channel 獨立進行卷積運算,得到與上層depth相同個數的feature map。對應到圖裏即3個filter分別對3個channel進行卷積,得到3個feature map。如下圖:
    在這裏插入圖片描述
圖2-2-2.depthwise conv
- 然後是pointwise convolution,和常規卷積運算類似,卷積核的尺寸爲 1×1×M,M等於上一層的depth。它會將上一步的feature map在深度方向上進行加權組合,生成新的feature map,有幾個filter就有幾個feature map。如圖3所示,輸入depth爲3,卷積核大小爲$1*1*3$,使用4個filter,最終生成4個feature map。

在這裏插入圖片描述

圖2-2-2.pointwise convolution

動畫見https://www.slideshare.net/DongWonShin4/depthwise-separable-convolution

編者按:
如果看過capsule的童鞋,應該還記得capsule是cnn的一個升級,所以在這裏我也在想,如果把這裏面的cnn替換成capsule會不會有奇效。之後有時間嘗試

2.3.Context-Query Attention Layer

幾乎所有 machine reading comprehension 模型都會有,而這裏依舊用了 context-to-query 以及 query-to-context 兩個方向的 attention:

  • 先計算相關性矩陣,
  • 再歸一化計算 attention 分數,
  • 最後與原始矩陣相乘得到修正的向量矩陣。

這裏的attention步驟和BIDAF也有點像,context-to-query完全相同,但是在query-to-context的時候稍有不同。

根據上一層得到的context和query的encoder表示來計算context-to-query attention和query-to-context attention矩陣。分別用C和Q來表示編碼後的context和query,CRndC \in R^{n*d}QRmdQ \in R^{m*d}。則步驟如下:

  • 首先計算context和query單詞之間的相似度,結果矩陣記爲S,SRn×mS\in{R^{n×m}}。其中相似度計算公式爲:f(q,c)=W0[q,c,qc]f(q,c)=W_0[q,c,q⊙c]
    其中:q、c分別爲單個單詞的中間表示,W0W_0是一個可訓練的參數。
  • 用softmax對S的行、列分別做歸一化得到Sˉ\bar{S}Sˉˉ\bar{\bar{S}},則 context-to-query attention矩陣A=SˉQTRnd\bar{S}·Q^T \in {R^{n*d}},query-to-context attention矩陣B=SˉSˉˉTCTRnd\bar{S}·\bar{\bar{S}}^T·C^T \in {R^{n*d}}(參考DCN模型)。

2.4.Model Encoder Layer

和 BiDAF 差不多,不過這裏依舊用 CNN 而不是 RNN。這一層的每個位置的輸入是 [c, a, c⊙a, c⊙b],a, b 是 attention 矩陣 A,B 的行,參數和embedding encoder layer大致相同,但是cnn 層數不一樣,這裏是每個 block 2 層卷積,一共7個block,並且一共用了3個這樣的組合stack,並且這三個stack共享參數
更易懂地說,這裏的Model Encoder Layer包含三個stacked model encoder blocks,每個stack model encoder blocks包含7個block,每個block的結構如圖2-1,而每個block內部包含2個cnn卷積(也就是[convolution-layer x # + self-attention-layer + feed-forward-layer]裏面的#=2)。

2.5 Output layer

分別預測每個位置是answer span的起始點和結束點的概率,分別記爲p1p^1p2p^2,計算公式如下:
p1=softmax(W1[M0;M1])p^1=softmax(W_1[M_0;M_1])
p2=softmax(W2[M0;M2])p^2=softmax(W_2[M_0;M_2])

其中W1W_1W2W_2是兩個可訓練變量,M0M_0M1M_1M2M_2依次對應結構圖中三個model encoder block的輸出(自底向上)。
目標函數:
L(θ)=1NiN[log(pyi11)+log(pyi22)]L(θ)=-\frac{1}{N}{\sum_i^N[log(p_{y_i^1}^1)+log(p_{y_i^2}^2)]}
其中yi1y_i^1yi2y_i^2分別爲第i個樣本的groudtruth的起始位置和結束位置。
對測試集進行預測時,span(s, e)的選取規則是:ps1p_s^1pe2p_e^2最大且ses\leq e

3.數據增強

看圖說話,對段落中每個句子先用 English-to-French 模型的 beam decoder 得到 k 個法語翻譯,然後對每一條翻譯,都再經過一個 reversed translation model 的 beam decoder,這最後就得到了 k^2 個改寫的句子(paraphrases),然後從這 k^2 個句子中隨機選一個

具體到 SQuAD 任務就是(d,q,a)>(d,q,a)(d,q,a) -> (d', q, a'),問題不變,對文檔 d 翻譯改寫,由於改寫後原始答案 a 現在可能已經不在改寫後的段落 dd' 裏了,所以需要從改寫後的段落 dd' 裏抽取新的答案 aa',採用的方法是計算 s’ 裏每個單詞和原始答案裏 start/end words 之間的 character-level 2-gram score,分數最高的單詞就被選擇爲新答案 aa' 的 start/end word

實驗結論是英文語料:法語語料:德語語料是 3:1:1 的比例時效果最好,EM 提升了 1.5,F1 提升了 1.1

4.源碼及訓練

We employ two types of standard regularizations. First, we use L2 weight decay on all the trainable variables, with parameter λ = 3 × 10−7. We additionally use dropout on word, character embeddings and between layers, where the word and character dropout rates are 0.1 and 0.05 respectively, and the dropout rate between every two layers is 0.1. We also adopt the stochastic depth method (layer dropout) (Huang et al., 2016) within each embedding or model encoder layer,where sublayer l has survival probability pl=1lL(1pL)p_l = 1− \frac{l}{L} (1−p_L) where L is the last layer and pLp_L = 0.9. The hidden size and the convolution filter number are all 128, the batch size is 32, training steps are 150K for original data, 250K for “data augmentation × 2”, and 340K for “data augmentation × 3”. The numbers of convolution layers in the embedding and modeling encoder are 4 and 2, kernel sizes are 7 and 5, and the block numbers for the encoders are 1 and 7,respectively.
We use the ADAM optimizer (Kingma & Ba, 2014) with β1=0.8β1 = 0.8; β2=0.999β2 = 0.999; ϵ=107\epsilon = 10−7. We use a learning rate warm-up scheme with an inverse exponential increase from 0.0 to 0.001 in the first 1000 steps, and then maintain a constant learning rate for the remainder of training. Exponential moving average is applied on all trainable variables with a decay rate 0.9999.
Finally, we implement our model in Python using Tensorflow (Abadi et al., 2016) and carry out our experiments on an NVIDIA p100 GPU.

Tensorflow實現:https://github.com/NLPLearn/QANet
Pytorch實現:https://github.com/hengruo/QANet-pytorch

這裏提供AI challenger參賽隊友D總的code:aic_qa

參考文獻

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