Seq2Seq+前缀树:检索任务新范式(以KgCLUE为例)
?PaperWeekly 原創 ·?作者 |蘇劍林
單位 |追一科技
研究方向 |NLP、神經網絡
兩年前,在《萬能的seq2seq:基于seq2seq的閱讀理解問答》和《“非自回歸”也不差:基于MLM的閱讀理解問答》中,我們在嘗試過分別利用“Seq2Seq+前綴樹”和“MLM+前綴樹”的方式做抽取式閱讀理解任務,并獲得了不錯的結果。而在去年的 ICLR 2021上,Facebook 的論文《Autoregressive Entity Retrieval》同樣利用“Seq2Seq+前綴樹”的組合,在實體鏈接和文檔檢索上做到了效果與效率的“雙贏”。?
事實上,“Seq2Seq+前綴樹”的組合理論上可以用到任意檢索型任務中,堪稱是檢索任務的“新范式”。本文將再次回顧“Seq2Seq+前綴樹”的思路,并用它來實現最近推出的 KgCLUE 知識圖譜問答榜單的一個 baseline。
檢索任務
說到檢索任務,想必大家都不陌生,除了常規的相似問檢索外,NLP中還有很多任務都可以視為檢索,比如抽取式閱讀理解、實體鏈接甚至基于知識圖譜的問答,等等。
以相似問檢索為例,常規的檢索系統的流程為:
1. 訓練句子編碼模型,這通常包含復雜的負樣本構建流程,負樣本質量直接影響到最終效果;
2. 將每個句子編碼為向量,存到諸如Faiss的向量檢索庫中,這一步通常需要消耗相當大的空間;
3. 將查詢句子編碼為向量,然后進行檢索,返回 Topk 結果及其相似度。
如果現在告訴你,有一個做檢索的新方案,可以不用花心思挑選負樣本,也不用消耗極大內存的向量檢索庫,最終效果和速度也不差于舊方案,那你會不會迫不及待想要嘗試一下?沒錯,這就是本文的主角“Seq2Seq+前綴樹”了。
Seq2Seq
首先,讓我們拋開各種繁瑣的細枝末節,想一想檢索任務究竟在做什么。對于相似問檢索來說,我們輸入一個問句,希望輸出數據庫中與之最相近的句子;對于實體鏈接來說,我們輸入一個包含該實體的句子,希望輸出知識庫中能正確詮釋該實體的實體名或者編號;等等。
拋開某些約束規則不說,可以發現這些任務本質上都可以抽象為:輸入一個句子,輸出另一個句子。
這不正是 Seq2Seq 最擅長的工作了嘛!所以用 Seq2Seq 做不是一件很自然的事情?當然,有讀者會說我要輸出的是數據庫里邊已有的一個句子呀,Seq2Seq 要是“溢出”(解碼出了數據庫不存在的句子)了怎么辦?這時該前綴樹上場了,我們可以利用前綴樹約束解碼過程,保證生成的結果在數據庫中,這一點我們等會細說。
沒有了“溢出”的顧慮,我們將會發現 Seq2Seq 的做法真的是集諸多優點于一身,比如:
1. 訓練 Seq2Seq 模型只需要輸入和目標,這也就是說我們只需要正樣本,免除了構建負樣本的煩惱,或者說它是將所有其他句子都當成負樣本了;
2. Seq2Seq 是直接解碼出目標句子,省去了句向量的儲存和檢索,也就免除了 Faiss 等工具的使用了;
3. Seq2Seq 包含了目標句子與輸入句子之間 Token 級別的交互,理論上比基于內積的向量檢索能做到更精細的對比,從而有更好的檢索效果。
前綴解碼
現在我們來細說一下利用前綴樹來約束解碼的過程,看一下它是如何保證輸出結果在數據庫中的。我們假設數據庫有如下幾句話:
那么我們將用如下的前綴樹來存儲這些句子:
▲ 前綴樹示意圖:本質上是序列的一種壓縮表示
其實就是從左往右地把相同位置的相同 token 聚合起來,樹上的每一條完整路徑(以?[BOS]?開頭、[EOS]?結尾)都代表數據庫中的一個句子。之所以叫“前綴樹”,是因為利用這種樹狀結構,我們可以很快地查找到以某個前綴開頭的字/句有哪些。比如從上圖中我們可以看到,第一個字只可能是“明”或“今”,“明”后面只能接“月”、“天”或“年”,“明天”后面只能接“會”或“下”,等等。
有了前綴樹,我們約束 Seq2Seq 解碼就不困難了,比如第一個字只能是“明”或“今”,那么在預測第一個字的時候,我們可以把模型預測其他字的概率都置零,這樣模型只可能從這兩個字中二選一;如果已經確定了第一個字,比如“明”,那么我們在預測第二個字的時候,同樣可以將“月”、“天”或“年”以外的字的概率都置零,這樣模型只可能從這三個字中選一個,結果必然是“明月”、“明天”、“明年”之一;依此類推,通過將不在前綴樹上的候選 token 置零,保證解碼過程只走前綴樹的分支,而且必須走到最后,這樣解碼出來的結果必然是數據庫中已有的句子。
相比常規的向量檢索方案,“Seq2Seq+前綴樹”的方案用前綴樹代替了要儲存的檢索向量,而前綴樹本質上是原始句子的一種“壓縮表示”,所以不難想象前綴樹所需要的儲存空間要比稠密的檢索向量要少得多。在 Python 中,實現前綴樹比較簡單的方案就是利用字典結構來實現嵌套,具體例子可以參考后面的 KgCLUE 的代碼。
KgCLUE
實踐是檢驗真理的唯一標準,現在我們就利用“Seq2Seq+前綴樹”的方案實現一個 KgCLUE 的 baseline,以檢驗它的有效性。
4.1 任務簡介
KgCLUE 是 CLUE 組織最近推出的一個中文知識圖譜問答的評測任務,數據比較規范,適合科研實驗測試。具體來說,它以約 2000 萬個三元組為知識庫,每個三元組是 (S, P, O) 的格式(Subject-Predicate-Object),如下圖:
▲?KgCLUE知識庫截圖
然后它還提供了一批標注語料供訓練,每個樣本是簡單的問題加答案的形式,其實問題本質上都可以抽象為“S 的 P 是什么”,而答案則是對應的三原則 (S,P,O),如下圖:
▲?KgCLUE標注語料截圖
原則上來說,只要確定了 (S,P),就可以從知識庫里邊抽取出對應的 O,所以我們主要的任務,就是要從問題中解析出正確的 S 和 P 出來。?
4.2 一般思路
完成這個任務比較樸素的方法是分兩步進行:第一步訓練一個標注模型負責從問題中抽取 S,然后從知識庫中找出該 S 對應的所有三元組,將 S 分別每一個 P 組合起來,逐一與問題算相似度,所以第二步也就是一個相似度模型。?
但要注意的是,知識庫里邊可能存在很多同名實體,比如“牛郎織女”,可能指神話故事,也可能指一本書或者一首歌等,為了對它們進行區分,知識庫里邊還有一個“義項(Meaning)”的概念,用來注明該名詞的具體指代,在 KgCLUE 的知識庫中,義項是通過括號的方式補充在 Subject 后面,比如“牛郎織女(中國著名民間故事)”、“牛郎織女(2015 年東方出版社出版的圖書)”等,但如果直接從問題抽取的話,通常只能抽取到義項以外的部分,即“牛郎織女”,所以我們實際處理時,通常會將它們分隔開,即將每條知識視為一個四元組 (S, M, P, O) 而不是三元組。?
根據給定問題來確定 Subject 究竟屬于哪個 Meaning,這就是“實體鏈接”問題,是知識圖譜問答的必要步驟。但如果局限在當前的 KgCLUE 任務中,由于語料本身不大,對于分兩步的模型來說,我們可以認為實體鏈接這一步整合到了相似度模型中,而不單獨進行實體鏈接任務。?
4.3 本文方案
如果用“Seq2Seq+前綴樹”來做的話,那么模型訓練方面將會變得非常簡單。
具體來說,我們就只需要一個 Seq2Seq 模型,然后將問題當作 Seq2Seq 的輸入,將 (S,P,M) 用 [SEP] 連接起來作為目標,進行正常的 Seq2Seq 訓練就行了。這里的一個技巧是按照 (S,P,M) 的順序進行拼接,要比按照 (S,M,P) 的順序的最終效果要好很多(8~10 個百分點),這是因為問題來預測 S,P 要比預測 M 都更容易,我們要先把容易預測的預測出來,以減少候選答案的數量。
▲?本文baseline模型示意圖
在參考代碼中,我們所用的 Seq2Seq 模型是《SimBERTv2來了!融合檢索和生成的RoFormer-Sim模型》、《用開源的人工標注數據來增強RoFormer-Sim》中介紹的 RoFormer-Sim-FT 模型,它是利用 UniLM 模型預訓練過的相似問生成模型,經過對比,用 RoFormer-Sim-FT 相比直接用 RoFormer,效果至少提升 2 個百分點。這也說明相似問生成是該方案的一種有效的預訓練方式。?
4.4 錯例分析
解碼的時候,我們先把所有的 (S,P,M) 建立成前綴樹,然后按照前綴樹進行解碼,就保證了解碼結果必然落到知識庫的某個三元組中,從而能夠合理地輸出結果。詳細的前綴解碼步驟前面已經介紹過了,這里就不再細說。?
然而,觀察 bad case 的時候,發現模型有可能會出現一些非常“簡單”的 bad case,比如“海浦東香格里拉大酒店離火車站有多遠?”,正確的 (S,P) 應該是“(上海浦東香格里拉大酒店, 火車站距離)”,但模型卻生成了“(上海浦東香格里拉大酒店, 酒店星級)”;有時候問“XXX 討厭什么”,結果模型卻生成了“(XXX, 喜歡)”;有時候問“XXX 主要講什么課程”,正確的答案應該是“(XXX, 主講課程)”,結果模型卻生成了“(XXX, 主要成就)”。也就是說,模型似乎會在一些字面上看起來非常簡單的問題上犯錯(生成錯誤的 P)。?
經過思考,筆者認為這種 bad case 本質上是 Seq2Seq 本身的固有缺點所導致的,主要包含兩方面:1)訓練時的 Exposure Bias 問題;2)解碼時 Beam Search 的貪心問題。
首先,由于 Seq2Seq 在訓練時是已知上一真實標簽的,這會弱化訓練難度,導致模型的“全局觀”不夠;其次,解碼哪怕用了 Beam Search,本質上也是貪心的,很難做到綜合后幾個 token 來預測當前 token。比如剛才的“XXX 主要講什么課程”一例,模型生成 P 的時候,首先就很貪心地生成“主要”兩個字,然后按照前綴樹的約束,“主要”后面只能接“成就”了(因為“主講課程”前兩個字是“主講”),所以就出來了“主要成就”。?
理論上,應用一些緩解 Seq2Seq 的 Exposure Bias 問題的策略,比如《Seq2Seq中Exposure Bias現象的淺析與對策》、《TeaForN:讓Teacher Forcing更有“遠見”一些》等,應該是對此問題有幫助的。這些方法比較多,復雜度也有所不一樣,就留給讀者自行嘗試了。?
4.5 “前瞻”策略
這里筆者提出另一個能夠緩解此問題的“前瞻”策略。?
在“Seq2Seq+前綴樹”方案中,我們的 Seq2Seq 不是真的要去生成任意文本,而是在前綴樹的約束下做本質上是檢索的操作,所以生成了 S 之后,我們可以知道后續容許的 P,并且一般來說后續容許的 P 不會太多,所以我們可以直接逐一枚舉容許的 P,通過 P 對問題的覆蓋程度,來調整當前 token 的預測結果。
具體的步驟是,假設當前問題 Q 已經解碼出 S,以及 P 的前 t-1 個字符 ,現在要預測 P 的第 t 個字 ,那么我們根據 檢索出所有可能的 ,每個 可以表示為 的格式;然后我們用一個覆蓋度函數,這里直接用最長公共子序列長度 ,來算出每個候選的 P 所能帶來的覆蓋度增益:
該增益視為將 預測為 的“潛在收益”,如果多個 對應同一個字,那么就取最大者。
這樣,對于 的所有候選值 k,我們都計算出來了一個“潛在收益”,我們可以調整 Seq2Seq 的預測概率,來強化一下 的 token。筆者用的強化規則為:
也就是如果潛在收益是 ,那么對應的概率就開 次方,然后重新歸一化,由于概率是小于 1 的,所以開方起到了放大的作用。該策略帶來的收益,大概是 4 個百分點的提升。其他強化規則也可以嘗試,這部分主觀性比較強,就不一一列舉了。
4.6 效果分析?
本文的代碼分享在:?
https://github.com/bojone/KgCLUE-bert4keras?
最終效果是:
目前排行榜上排名第二:
▲?當前KgCLUE榜單截圖
調試歷程大概是:
1. 開始用 RoFormer+UniLM 按照 (S,M,P) 順序預測,驗證集 EM 大約是 70 多;
2. 然后改為 (S,P,M) 的順序之后,驗證集能做到 82 了;
3. 接著預訓練模型換用 RoFormer-Sim-FT 后,提升到 84~85;
4. 最后加上“前瞻”策略,就做到當前的 89 了。
一些缺點
至此,我們已經比較詳細地介紹了“Seq2Seq+前綴樹”方案,并且以 KgCLUE 為例分享了一個 baseline 給大家。總的來說,“Seq2Seq+前綴樹”有它的明顯優點,并且能在檢索任務上取得有競爭力的效果,但其中依然有一些問題值得思考。?
最典型的問題,就是 Seq2Seq 本身的固有問題,這我們在前面已經提過了。雖然“前瞻”策略已經能給我們帶來不錯的提升,但相應的問題依然沒有完全解決,如何更自然地解決該問題,或者設計更自然的解碼規則,依然是值得思考,沒有標準答案。此外,前面提到的解決 Exposure Bias 問題的通用策略,筆者也還沒有嘗試,不確定具體效果如何。?
還有一個問題,就是“Seq2Seq+前綴樹”的方案,是靠模型把結果“生成”的,而一旦遇到生僻字被識別為 [UNK],那么大概率就會失敗了,尤其是如果 S 的第一個字就是 [UNK],那么幾乎都會失敗,所以如何更好地解決 [UNK] 問題,是一個值得研究的問題。當然,也可以嘗試傳統的 Copy 機制,這就看個人的審美了。?
最后,“Seq2Seq+前綴樹”或許可以在評測指標上取得不錯的效果,但它對于工程來說,有一個不大有好的特點,就是修正 bad case 會變得比較困難,因為傳統方法修正 bad case,你只需要不斷加樣本就行了,而“Seq2Seq+前綴樹”則需要你修改解碼過程,這通常困難得多。
文章總結
本文介紹了檢索模型的一種新方案——“Seq2Seq+前綴樹”,并以 KgCLUE 為例給出了一個具體的 baseline。“Seq2Seq+前綴樹”的方案有著訓練簡單、空間占用少等優點,也有一些不足之處,總的來說算得上是一種簡明的有競爭力的方案。
特別鳴謝
感謝 TCCI 天橋腦科學研究院對于 PaperWeekly 的支持。TCCI 關注大腦探知、大腦功能和大腦健康。
更多閱讀
#投 稿?通 道#
?讓你的文字被更多人看到?
如何才能讓更多的優質內容以更短路徑到達讀者群體,縮短讀者尋找優質內容的成本呢?答案就是:你不認識的人。
總有一些你不認識的人,知道你想知道的東西。PaperWeekly 或許可以成為一座橋梁,促使不同背景、不同方向的學者和學術靈感相互碰撞,迸發出更多的可能性。?
PaperWeekly 鼓勵高校實驗室或個人,在我們的平臺上分享各類優質內容,可以是最新論文解讀,也可以是學術熱點剖析、科研心得或競賽經驗講解等。我們的目的只有一個,讓知識真正流動起來。
📝?稿件基本要求:
? 文章確系個人原創作品,未曾在公開渠道發表,如為其他平臺已發表或待發表的文章,請明確標注?
? 稿件建議以?markdown?格式撰寫,文中配圖以附件形式發送,要求圖片清晰,無版權問題
? PaperWeekly 尊重原作者署名權,并將為每篇被采納的原創首發稿件,提供業內具有競爭力稿酬,具體依據文章閱讀量和文章質量階梯制結算
📬?投稿通道:
? 投稿郵箱:hr@paperweekly.site?
? 來稿請備注即時聯系方式(微信),以便我們在稿件選用的第一時間聯系作者
? 您也可以直接添加小編微信(pwbot02)快速投稿,備注:姓名-投稿
△長按添加PaperWeekly小編
🔍
現在,在「知乎」也能找到我們了
進入知乎首頁搜索「PaperWeekly」
點擊「關注」訂閱我們的專欄吧
·
總結
以上是生活随笔為你收集整理的Seq2Seq+前缀树:检索任务新范式(以KgCLUE为例)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智商重要,还是情商重要?
- 下一篇: 青春期吃什么有助于长高,长腿鹿长高效果好