1. 程式人生 > >QA(二):利用Attention機制,帶著問題閱讀

QA(二):利用Attention機制,帶著問題閱讀

摘要

本文介紹一種結合 math-LSTM 和Pointer Net利用end-end的來解決QA問題的方式

模型

最主要的還是 match-LSTM:有兩個句子,一個是前提,另外一個是假設,match-LSTM序列化的經過假設的每一個詞,然後預測前提是否繼承自假設。

簡單的說:帶著問題去閱讀原文,然後用得到的資訊去回答問題

  1. 先利用LSTM閱讀一遍passage,得到輸出的encoding 序列
  2. 然後帶著question的資訊,重新將passage的每個詞輸入LSTM,再次得到passage的encoding資訊。但是這次的輸入不僅僅只有passage的資訊,還包含這個詞和question的關聯資訊,它和qustion的關聯資訊的計算方式就是我們在seq2seq模型裡面最常用的attention機制。
  3. 然後將資訊輸入answer模組,生成答案

下面介紹詳細的模型

1. 預處理層LSTM Preprocessing層

首先對文字和問題分別單獨用LSTM進行單向的encoder

Hp=LSTM(P)Hq=LSTM(Q)
HpR[l,p],HqR[l,q]
l 是LSTMcell的隱藏層大小,p和q分別是文字passage 和 問題question的長度
程式碼很簡單,兩個序列分別經過LSTM序列模型,就得到encoder向量。
lstm_cell_question = tf.nn.rnn_cell_impl.BasicLSTMCell(l, state_is_tuple=True
) encoded_question, q_rep = tf.nn.dynamic_rnn(lstm_cell_question, question,masks_question,dtype=tf.float32) lstm_cell_passage = tf.nn.rnn_cell_impl.BasicLSTMCell(l, state_is_tuple=True) encoded_passage, p_rep = tf.nn.dynamic_rnn(lstm_cell_passage, passage,masks_passage, dtype=tf.float32)

2. Match-LSTM 層

帶著qustion來閱讀passage,利用的是利用了 Bahdanau Attention機制機制,具體可以見該論文。

但是為了詳細描述,在這裡還是詳細的描述一遍:

整體的思路可以看作我們在decoder passage,我們聚焦的是qustion向量:
hri=LSTM(zi,hri1)

由attention機制我們可以知道,這裡的zi是融合passage的input和對qustion的attention資訊:

zi=[hpif(Hq)]

Hp是prcess層利用LSTM將passage預處理後得到的,
第i個詞的向量為hpiRl,我們在hpi之後加一個qustion相關的資訊,

令:f(Hq)=Hqαi

其中αi是文字passage裡面的第i個詞,首先計算第i個詞和question裡面每一個詞的相關性權重

αi就是attention的alignment model:

Gi=tanh(WqHq+(Wphpi+Wrhri1+bp)eQ)αi=softmax(wtGi+beQ)
# tensorflow 裡面有現成的BahdanauAttention類
match_lstm = BahdanauAttention(l, q)

這樣我們就得到了αi

這樣我們可以完整的迭代這個序列模型:

hri=LSTM(zi,hri1)

同理我們將passage倒敘,可以得到倒敘的LSTM模型

hri^=LSTM(zi^,hri1^)

我們令forward和backward得到的轉檯矩陣分別為Hr,Hr^, 我們把兩個矩陣直接連線起來得到最終的狀態矩陣

Hr=[HrHr^]
HrR[2l,p]
# LSTM Cell
cell = BasicLSTMCell(l, state_is_tuple=True)
lstm_attender = AttentionWrapper(cell, match_lstm)
reverse_encoded_passage = _reverse(encoded_passage)

# bi-dir LSTM
output_attender_fw, _ = tf.nn.dynamic_rnn(lstm_attender, encoded_passage, dtype=tf.float32, scope="rnn")
output_attender_bw, _ = tf.nn.dynamic_rnn(lstm_attender, reverse_encoded_passage, dtype=tf.float32, scope="rnn")

output_attender_bw = _reverse(output_attender_bw)

# concat
output_attender = tf.concat([output_attender_fw, output_attender_bw], axis=-1)

3. Answer Pointer

Answer Pointer的思想是從Pointer Net得到的,
它將Hr作為輸入,生成答案有兩種方式:
1. sequence,自動生成答案序列, 序列裡面的詞是從passage裡面選取出來的
2. boundary,答案從passage裡面擷取,模型生成的是開始和結束下標

Sequence

假設我們的答案序列為:
a=(a1,a2,...)
其中ai為選擇出來答案的詞在原文passage裡面的下標位置,