r-net:machine reading comprehension with self-matching networks

我覺得這篇文章的文筆真的有點不敢恭維,首先向量矩陣的維度不說清楚還能腦補,但是這邊前後不同層之間用一樣的變量名是什麼意思啊(這麼說出來會不會被MSRA鄙視,以後的簡歷都過不了了,ORZ),本文中儘量避免這種情況。嗯嗯,文章還是不錯的^@^
標記版文章下載地址:zsweet github
原始文章下載地址:
Gated Self-Matching Networks for Reading Comprehension and Question Answering
R-NET: MACHINE READING COMPREHENSION WITH SELF-MATCHING NETWORKS

這裏先總結下幾個特點:

  • 同時使用了char-embedding和word-embedding,不同的是char-embedding是通過將char放入雙向gru之後,最終的是通過gru的最終狀態來得到的。
  • 在attention之後添加gate,主要用在Question-Passage Matching和Passage Self-Matching之後。
  • 對文章本身進行self-attention。

1.模型概述

其實我覺得整體結構就是math-lstm和transformer模型的融合,然後再加了一點的小trick.

模型整體可以分爲如下幾個模塊:

  • embedding層
  • RNN網絡分別對question和passage單獨編碼 (本文中將前兩部分放在一個部分介紹)
  • 基於門限的注意力循環神經網絡(gated-attention based recurrent network)匹配question和passage,獲取問題的相關段落表示(question-aware passage representation)
  • 基於自匹配注意力機制的循環神經網絡(self-matching attention network),將passage和它自己匹配,從而實現整個段落的高效編碼
  • 基於指針網絡(pointer-network)定位答案所在位置

模型結構如下:
在這裏插入圖片描述
在這裏插入圖片描述

2.passage和question編碼層

輸入問題Q=wtQt=1mQ={w_t^Q}_{t=1}^m和段落P=wtPt=1nP={w_t^P}_{t=1}^n,分別進行word-level編碼和character-level編碼,得到向量eecc。這裏character-level編碼主要是爲了應對OOV的影響,以往OOV詞向量直接就是0,這裏可以緩和OOV的影響。之後,利用兩個雙向RNN網絡分別對question和passage再編碼。而之前多數都是用的CNN卷積和highway。另外,作者在這裏選用了GRU單元,而不是LSTM,原因在於GRU計算量更小。
utQ=BiGRU(ut1Q,[etQ,ctQ])\mathbf u_t^Q = \rm{BiGRU }(u_{t-1}^Q, [e_t^Q, c_t^Q])

utP=BiGRU(ut1P,[etP,ctP])\mathbf u_t^P = \rm{BiGRU }(u_{t-1}^P, [e_t^P, c_t^P])

其中:et,cte_t, c_t分別表示詞向量和字向量,編碼後的passage爲[u1Q,u2Q...umQ][u_1^Q,u_2^Q...u_m^Q],query爲[u1P,u2P...unP][u_1^P,u_2^P...u_n^P]

3.Gated Attention-based RNN

首先對query做attention:
sjt=vTtanh(WuQujQ+WuPutP+WvPvt1P),j=1, ,ms_j^t = v^T \tanh (W_u^Q\mathbf u_j^Q + W_u^P \mathbf u_t^P + W_v^P \mathbf v_{t-1}^P), \quad j = 1, \cdots, m
αjt=softmax(sjt)\alpha_{j}^t = \rm{softmax}(s_j^t)

ct=i=1mαituiQ\mathbf c_t = \sum_{i=1}^m \alpha_i^t \mathbf u_i^Q
上述的attention可記爲ct=attn(uQ,[utP,vt1P])\mathbf c_t = \rm{attn}(\mathbf u^Q, [\mathbf u_t^P, \mathbf v_{t-1}^P])​。

上面的attention與match-lstm一樣,但是這裏又增加了一個gate:
gt=sigmoid(Wg[utP,ct])g_t = sigmoid(W_g[\mathbf u_t^P,\mathbf c_t])
[utP,ct]=gt[utP,ct][\mathbf u_t^P, \mathbf c_t]^* = g_t \odot [\mathbf u_t^P, \mathbf c_t]

然後再像match-lstm一樣放入RNN:
vtP=BiGRU(vt1P,[utP,ct])\mathbf v_t^P = \rm{BiGRU}(\mathbf v_{t-1}^P, [\mathbf u_t^P, \mathbf c_t]^*)
每個vtP\mathbf v_t^P動態地合併了來自整個Q的匹配信息。

可以看到,這一步驟和match-lstm的唯一區別就是增加了這個gtg_t來控制passage和attention之後的query的輸出量。

Gate RNN的門機制:

  • 與GRU和LSTM不同
  • 門機制是基於當前PtP_t和它的對應的QQ的注意力向量ctc_t(包含當前pt和Q的關係)
  • 模擬了閱讀理解中,只有P的一部分才與問題相關的特點

其實這個gate我覺得是很像那個highway的,在transformer裏面用的是residual,但是這裏和下面的self-attention之後換成了僞highway,甚至我覺得這個地方換成residual也未必不好,但是我沒嘗試過。

4.Self-Matching Attention

爲了充分利用Passage的上下文信息。增加對passage的self-attention :
sjt=vTtanh(WvPvjP+WvPˉvtP),j=1, ,ns_j^t = v^T \tanh (W_v^P \mathbf v_j^P + W_v^{\bar P} \mathbf v_t^P), \quad j = 1, \cdots, n

βjt=softmax(sjt)\beta_{j}^t = \rm{softmax}(s_j^t)

dt=i=1nβitviP\mathbf d_t = \sum_{i=1}^n \beta_i^t \mathbf v_i^P
上述的attention可記爲dt=att(vP,vtP)\mathbf d_t = att(v^P,v_t^P))
同樣在這裏添加gate:
gt=sigmoid(Wg[vtP,dt])g'_t = sigmoid(W_g[\mathbf v_t^P,\mathbf d_t])
[vtP,dt]=gt[vtP,dt][\mathbf v_t^P, \mathbf d_t]^* = g'_t \odot [\mathbf v_t^P, \mathbf d_t]

同樣放入RNN計算:
htP=BiGRU(ht1P,[vtP,dt])\mathbf h_t^P = \rm{BiGRU}(\mathbf h_{t-1}^P, [\mathbf v_t^P, \mathbf d_t]^*)
Self-Matching根據當前p單詞,從整個Passage中提取信息。最終得到Passage的表達HPH^P

我奇怪的是這裏在計算sjts_j^t的時候爲什麼沒有使用RNN中t-1時刻的輸出ht1Ph_{t-1}^P?難道效果不好?

5.output layer

類似於match-lstm中的最後輸出層Ptr-net:
計算tt時刻的attention-pooling passage (注意力ct\mathbf c_t
sjt=vTtanh(WhPhjP+Whaht1a)s_j^t = \mathbf v^T \tanh(W_h^P\mathbf h_j^P + W_h^a \mathbf h_{t-1}^a)

γit=softmax(sjt)\gamma _i^t = \rm{softmax}(s_j^t)

ft=i=1nγithiP\mathbf f_t = \sum_{i=1}^n \gamma_i^t \mathbf h_i^P

pt=argmaxi(γit)p^t = \arg \max_{i}(\gamma_i^t)
上述的attention可記爲ft=att(hP,ht1)\mathbf f_t = att(h^P,h_{t-1})

RNN前向計算
hta=GRU(ht1a,ft)\mathbf h_t^a = \rm{GRU} (\mathbf h_{t-1}^a, \mathbf f_t)
基於注意力權值去選擇位置。

上面的這是match-lstm中的Ptr,在R-net中是增加了RNN中的初始狀態初始化,
初始hidden state是Question的attention-pooling vector:
h0Q=rQ\mathbf h_{0}^Q = \mathbf r^Q
基於Q的編碼和一組參數VrQV_r^Q,利用注意力機制計算rQ\mathbf r^Q

sj=vTtanh(WuQujQ+WvQVrQ),j=1, ,ms_j = \mathbf v^T \tanh(W_u^Q \mathbf u_j^Q + W_v^Q V_r^Q), \quad j = 1, \cdots, m

δi=softmax(si)\delta_i = \rm{softmax}(s_i)

rQ=i=1mδiuiQ\mathbf r^Q = \sum_{i=1}^m\delta_i \mathbf u_i^Q
上述的attention可記爲rQ=attn(uQ,VrQ)\mathbf r^Q = \rm{attn}(\mathbf u^Q, \mathbf V_r^Q)

同樣這裏有點奇怪的是,按說這裏的VrQV_r^Q是一個向量的,並且WvQVrQW_v^Q V_r^Q也是個向量,這不就相當於一個bias向量嗎?爲什麼寫的這麼麻煩?

之後從網上看到這個:
這裏肯定會有很多人困惑這個V_r^Q是怎麼來的,文中並沒有介紹,其實它是RNN的首狀態,大部分RNN的第一個輸入都是這麼處理的。看代碼還會發現它就是一個通過tf.contrib.layers.xavier_initializer()初始化的參數,那爲什麼不把這個乘法寫成一個參數呢,因爲兩個都是可學習的參數完全可以合併,我覺得是因爲要和attention的輸入保持一致(attention函數有兩個輸入)。

所以按照match-lstm中boundary方案,每次ft=att(hP,ht1)\mathbf f_t = att(h^P,h_{t-1})產生的權重就可以作爲start-probability和end-probability了

目標函數:
n=1Nlogp(anPn,Qn)- \sum_{n=1}^N \log p(\mathbf a_n \mid P_n, Q_n)
本文用的是邊界模型,所以不用預測完整的序列,只預測開始和結束位置就可以了。
p(aHr)=p(asHr)p(aeas,Hr)p(\mathbf a \mid H^r) = p(a_s \mid H^r) \cdot p(a_e \mid a_s, H^r)

6.源碼和參數

模型細節

  • 訓練集80%,驗證集10%,測試10%
  • 分詞用的斯坦福的CoreNLP中的tokenizer
  • 預訓練好的Glove Vectors。訓練中保持不變。
  • 單層的雙向GRU,末尾隱狀態作爲該單詞的字符向量
  • BiRNN編碼Question和Passage中使用3層的雙向GRU
  • Hidden Size大小,所有都是75
  • 每層之間的DropOut比例是0.2
  • 優化器使用AdaDelta。初始學習率爲1,衰減率β=0.95,ϵ=1e−6

源碼:

  • r-net
    該源碼與原文比較貼合,readme和issue中沒有提到過結果怎麼樣

  • zsweet github
    這份源碼提供了score,但是代碼中沒有完全按照r-net,因爲擬合RNN實在太慢了,所以我研究的也是這份代碼,區別就在attention上面,用的是transformer裏面的那種attention,速度還是可以的。

原文中還提了很多的嘗試,其中有個sentence rank的,之前我也在Dureader裏面嘗試過,嘗試的是passage rank,效果也不好,其他的嘗試可以參考文章,別人踩過的坑還是不要再踩一次了,當然這只是針對SQuAD

參考鏈接

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