問題生成調研
來自專欄 NLP Weekly40 人贊了文章
Part I:問題生成
Part II:對抗學習
Part III:多任務學習
前言:最近調研了一下問題生成,這是一個相對比較小眾的研究領域,但是應用場景挺多的,可用於數據增強、問診系統、輔導系統、童話提問等。網上分享的資料比較少,因此本文結合自己的一些實驗結果,介紹下這個領域。
Part I:問題生成
QG的任務形式,一般是給定文章和一個答案,生成一個對應的問題(然後問題和答案組成新QA對),或者是只給文章,生成更加open和多樣的問題。
QG屬於文本生成任務,可以用seq2seq那一套來做,更多的是結合問答(QA)任務一起做,使用對抗學習,對偶學習,也可以結合其它任務進行多任務學習。
先說下問題生成的評估指標,既然是文本生成任務,那當然可以用文本生成的指標(bleu,rouge),但這些指標只是評估相似度,顯然對於問題生成任務來說這些指標太過單薄,我們還需要採樣一些數據來做一些人工評估:
1)句子通順度(基本上可以達標)
2)語義合理性(比如「小明的老公是誰」這種問題就不合理)
3)答案與問題的匹配程度(要求該問題能用指定答案來回答,或者如果不加答案約束,至少要求這個問題可以被這篇文章來回答)
4)問題的多樣性(在這裡表現為,和reference問題是相同語義的,但是句子表達形式更多樣)這方面的研究比較少一點。
從這些指標可以看到,問題生成比單純的摘要生成更難一點,有答案的約束。
關於一些綜述論文:
Neural Question Generation from Text: A Preliminary Study
Learning to Ask: Neural Question Generation for Reading Comprehension by ACL-17
首先,我們先用文本生成的做法來試下水,pointer-generator,做摘要生成的:
Get To The Point: Summarization with Pointer-Generator Networks by acl-17
其實就是在seq2seq的基礎上加入copy機制和coverage機制,copy機制copy原文細節,以及解決oov問題,而coverage是解決重複生成的問題,都是文本生成中常見的問題。
copy機制
seq2seq在生成文本的時候常見的一個做法是,在decoder的每個step下,對encoder所有step加權算出一個context向量,將來自encoder的context和來自decoder的output拼接起來,去預測總詞表的概率分布,詞語都是從詞表中生成出來的。
那既然詞語來自詞表,那我們就只能生成詞表裡面的詞,原文中有些詞語可能是oov,比如一些人名地名或者別的細節,不存在於詞表中,就沒辦法生成這些詞。
因此,copy機制提出,我們可以復用encoder的加權概率,作為copy原文這個詞的概率,再結合詞表生成方式和原文copy方式,根據隱藏層和輸入詞向量來算一個p_gen,表示選擇從詞表生成該詞的概率,1-p_gen表示選擇從原文copy該詞的概率:
預測的時候,如果這個詞在原文中出現,用的就是來自總詞表的概率+來自原文的概率,如果這個詞在原文中沒有出現,第二項為0,就只用詞表的結果。
這個attention向量如果不復用也可以,可以重新生成一個attention向量。
在具體代碼實現上,首先我們統計出一個詞表vocab,然後每一篇文章都動態擴展自己的oov詞語到這個詞表中,每個文章最終用的詞表都不一樣。我們都用兩套詞id序列來表示原文,一套是原詞表id,另一套是在詞表的基礎上,把這篇文章的oov詞語擴展加到原詞表後面,對應的id也從oov改為擴展的id序號。encoder使用原詞表id來映射詞向量,decoder在copy的時候使用擴展詞表id,生成的時候還是使用原詞表,最終預測合併起來使用擴展詞表id。
既然可以copy原文了,我們可以減小詞典size,因為一些專有名詞可以從原文中進行copy,不需要加入到我們的詞典中,詞向量這部分的參數還是比較大的。甚至對於問題生成這個領域,我們可以統計高頻的問題字詞,這部分詞表應該比原詞表要小很多,另外的詞語就從原文中進行copy,encoder和decoder分別用兩套詞表。
另外有個問題是,deocder在預測的時候可以預測oov,但是在teach force的時候又沒有該oov詞語所對應的詞向量,還是只能用統一的oov詞向量,這樣感覺不太好。(或者詞向量也可以進行擴展學習?)
coverage機制
coverage機制在decoder每個step下,累加從前所有step中原文的attention向量,記為c,用來記錄從前的attention情況,把c加入計算該步對encoder的attention向量,記為a。coverage loss比較a和c,來懲罰那些重複關注的詞:
如果這個詞之前已經被關注過了,那麼所對應的c就比較大,如果這次還是關注這個詞,那麼a也會比較大,最後loss就會比較大,進行懲罰。而這個詞如果之前沒有被關注過,c比較小,我們可以關注這個詞,也可以不關注。
另外從公式中可以看出,一個詞只要在前面已經生成過了,那麼就要求後面不能再生成這個詞。其實這種方式可能不太合理,有時候一個詞可能會出現多次,比如,「小明的媽媽叫小明回家吃飯」,這句話中「小明」就出現了兩次。而重複生成的問題一般是連續重複生成的,比如,「小明回家家家家吃飯飯」,所以或許我們可以只用上一個step的a來進行懲罰,而不是累加前面所有step的a向量。
實驗發現,加入coverage機制並無明顯提升,可能是因為我前面的seq2seq本身就已經學得比較好,重複生成這種問題比較少,所以加coverage沒有明顯效果。
答案約束
如果直接使用pointer-generator模型,沒有對文章加上答案約束,即只輸入文章,輸出問題,局限在於,對一篇文章,模型只會提一個問題,因此我們要給文章加上答案約束,讓他學會對不同的答案進行提問。
最為簡單的思路是,在文章詞向量中加入答案one-hot特徵。然而實驗發現並沒有學到答案信息,我猜測可能是one-hot特徵維度比較小,詞向量維度比較大,這個特徵被淹沒在了茫茫詞向量中。
既然答案是包含在原文中的,那麼在對原文進行建模的時候,其實也對答案字詞進行了學習,所以我們可以直接在文章-encoder中抽取出答案所對應的embedding和lstm-output,再過一個bi-lstm得到答案語義向量。而原文中已經包含答案,我們不需要再對原文和答案進行交互,可以直接拿這個答案向量去初始化decoder的參數。
(關於coding:我最初是在opennmt的基礎上改代碼,其實opennmt這類框架是集成各種功能,方便大家跑demo使用,或者在上面擴展一些seq2seq功能,opennmt寫的很優秀,但同時也就封裝得略為嚴實,如果我們並不需要這麼多功能,各種類改起來還是挺麻煩的,所以最後我還是重新寫了個簡潔的架構)
Part II:對抗學習
普通版GAN
簡單的思路是,生成器就用seq2seq,輸入文章和答案,輸出問題,判別器就用個二分類器,輸入問題,輸出判斷這個問題是不是生成的。先用負對數似然函數來預訓練生成器(如果直接上判別器,就會很難收斂),然後交替訓練生成器和判別器,在訓練生成器的時候,修改生成問題的標籤為真,用判別器的reward來訓練生成器,試圖欺騙判別器;在訓練判別器的時候,用生成器所生成的問題,和原本真實的問題,來做二分類,提高自己的判斷能力。
而在生成答案的時候,每一個step選擇概率最大的詞,這裡的max操作會帶來梯度不連續的問題,所以一般要使用強化學習的方法去計算梯度。
而強化學習可能沒有那麼好訓練,所以有些研究想要把離散梯度改為連續梯度:
1)將生成器每個step所預測的概率向量,作為這個詞所對應的向量,直接作為判別器的輸入。其實是相當於one-hot向量。
2)將生成器每個step下的這個概率向量,和詞表中所有詞向量進行加權,得到一個平均的詞向量表示,作為這個step生成詞的向量,再作為判別器的輸入。
3)使用auto-encoder來對one-hot學習句向量
4)使用gumbel-softmax之類的仿sampling採樣方式
我採用的第二種方法。
多判別器版GAN
這是一個做圖片問題生成的論文,其實就是利用數據集屬性,增加了一個問題屬性分類器,一個判別器對問題的真假進行分類,另一個對問題的屬性進行分類。
A Reinforcement Learning Framework for Natural Question Generation using Bi-discriminators by colling-18
那我們可以對答案做個命名實體識別,作為問題的類別,然後判別器再判斷提問的類型是不是屬於該類別。因為有一些case,比如,生成的問題是「姚明的出生地在哪裡」,看上去很通順也沒什麼語義問題,但其實答案應該是「葉莉」,因為gtruth問題是「姚明的妻子是誰」,所以增加這個問題類型分類器,可以約束提問某一種類型的問題。假設我們已經可以解決問題類型不匹配這種case了,但是還有另外一些case,比如,生成的問題是「姚明的爸爸是誰」,gtruth答案還是「葉莉」,雖然提問的角度也是人名,但是和真實答案並不匹配。
所以更好的方法是用QA模型來判斷生成的問題能不能用原答案回答。在加答案約束的條件下,能被該答案回答的問題才是個好問題,而在不加答案約束的條件下,只要是能被回答的問題就是個好問題。
QA版GAN
這裡QG作為生成器,QA作為判別器,給QG提供reward來更新參數。
Semi-Supervised QA with Generative Domain-Adaptive Nets
這個論文給判別器的輸入增加了一個欄位來標記該問題是生成的還是真實的,d_true表示為真,d_false表示為假:
這個論文主要解決標註數據少的問題,在訓練QA判別器的時候,用到兩部分數據:
1)使用原始QA數據(少量),給QA判別器輸入文章、問題和d_true標記,輸出答案,用生成的答案和gtruth答案來算cross entropy作為loss
2)使用增強QA數據(大量),固定QG生成器,給QG生成器輸入未標記問題的文章和答案來生成問題,然後給QA判別器輸入文章、問題和d_gen標記,同樣用cross entropy來算loss
在訓練QG生成器的時候,先生成問題,然後修改問題標記為d_true,固定判別器參數,然後用判別器+強化學習來更新生成器參數。
其實QG跟QA正好是對偶任務,也用相同的數據集,因此有很多研究是將兩者結合起來,除了對抗訓練,還有一些別的做法:
1)duel-learning,對偶學習,同時訓練QA和QG,兩個任務沒有主次之分,分別在自己原本的loss基礎上再加一個對偶項,一起計算梯度和更新參數。
Question Answering and Question Generation as Dual Tasks
這篇論文把QA當成排序任務,所以模型每次是輸入多個QA對正負例。
2)joint-learning
[1706.01450] A Joint Model for Question Answering and Question Generation
這個論文把QA和QG都作為生成任務,用同一個模型進行聯合學習,通過一個mode來控制生成問題還是生成答案,實驗結果是QG有所提升,但是QA學得不好。
我覺得有兩點問題,首先在encoder中,文章對問題和答案的交互要求可能不一樣,然後在decoder中,生成問題和生成答案也不一樣,生成問題的時候是針對總詞表來生成,但是答案卻是直接出現在文章中,其實可以用文檔詞表。QA和QG可以共享部分參數,但是有些地方還是分開設計會更好一點。
3)self-learning
Self-Training for Jointly Learning to Ask and Answer Questions by naacl-18
4)transfer-learning
[1706.09789] Two-Stage Synthesis Networks for Transfer Learning in Machine Comprehension
另外這位同學做了一些整理:論文梳理:問題生成(QG)與答案生成(QA)的結合
Part III:多任務學習
除了QA任務外,QG還花式結合了一些別的任務。
1)sentence ranking + QG
這個論文先用分類器從文章中選一個跟問題相關的句子,QG再用該句子去生成問題。
Identifying Where to Focus in Reading Comprehension for Neural Question Generation by emnlp-17
句子選擇器:分別對句子進行encode得到句向量,再將這些句向量經過雙向LSTM,再經過全連接層-softmax進行分類,這裡使用答案所在的句子作為gtruth。
問題生成:訓練的時候,使用正確的句子生成對應的問題,測試的時候就直接使用句子選擇器選擇出來的句子,生成問題。
但有個問題是,QG只使用一個句子去產生問題,可能會缺失全文信息,其實可以使用句子選擇器中的句向量,拼接到QG的輸入中。
2)QG + 文本生成
這個屬於多任務學習,用問題生成和蘊含生成去輔助摘要生成任務:
Soft Layer-Specific Multi-Task Summarization with Entailment and Question Generation by ACL-18
Motivation是這麼寫的:問題生成學會對重要的地方提問,用於檢測重要信息,蘊含生成做去重改寫,檢測不重要的信息。(大概或許可能是圓故事吧.....)
這三個都是生成任務,使用同一種baseline模型:2層encoder-decoder + copy + coverage,分別進行預訓練。這裡用到2層encoder-decoder是有原因的,一來只用1層學習能力不夠,二來是為共享做鋪墊,大家共享第2層encoder參數,attention參數,和第1層decoder參數,而第2層encoder和第2層decoder用於保留各種任務的參數獨特性。
另外,在多任務學習中,參數是hard共享模式(即要求共享的參數完全一致),這個論文提了一種soft共享方式,不需要完全共享參數,要求輔助任務共享的參數接近主任務參數即可,顯得更加靈活一點。
END 還是要腳踏實地進行落地
推薦閱讀:
※Attention的梳理、隨想與嘗試
※DeepMind提出空間語言集成模型SLIM
※自然語言處理(NLP)基礎教程1:接觸PyTorch
※AAAI2018會議中的應答生成
※tensorflow用高級api實現文本分類初嘗試
TAG:自然語言處理 |