百度机器阅读理解比赛赛后总结
百度機器閱讀理解比賽賽后總結
<!-- 文章內容 --><div data-note-content="" class="show-content"><div class="show-content-free"><p>2018年4-5月間,筆者參加了百度舉辦的<a href="https://links.jianshu.com/go?to=http%3A%2F%2Fmrc2018.cipsc.org.cn%2F" target="_blank" rel="nofollow">機器閱讀理解競賽</a>,抱師兄大腿地從不知連機器學習的門入沒入的狀態到對自然語言以及閱讀理解有了一定理解。期間經歷了讀不懂論文、不會實現算法、對師兄談及的各種算法一無所知等等痛苦,最終堅持下來,算是有了一些收獲,就在這篇文章把參加比賽的整個過程以及解題、構建模型的思路梳理一下。</p>我和組隊的畢業師兄都是第一次參加閱讀理解的比賽,但他在自然語言方面有更多了解,先前也打過kaggle之類的比賽,比賽實際上以他打為主,我以輔助和學習的形式參加。
比賽最終以Rough-L第14名,BLEU第6名的結果結束,雖然有很多想法和改進沒有來得及實現,但畢竟是第一次參賽,相信之后會越來越好。
RanklistStep0:了解比賽,掌握數據形式
題目背景:
官方給出解釋:
對于給定問題q及其對應的文本形式的候選文檔集合D=d1, d2, ..., dn,要求參評閱讀理解系統自動對問題及候選文檔進行分析, 輸出能夠滿足問題的文本答案a。目標是a能夠正確、完整、簡潔地回答問題q。
個人詳細解釋:
語料庫包含很多問題
對于每個問題,語料庫中對應幾篇文檔和該問題的標準答案。
文檔來自百度搜索、百度知道的結果,文檔分標題和內容。文檔的標題和詢問的問題相似,而內容則是和問題答案相關的內容。
問題的標準答案參考給出的文檔由人工提取而成。(非完全抽取式,會有些許不同)。
我們要做的就是根據給出的幾篇文檔,回答問題的答案,根據我們給出的答案和他們給出的標準答案的相似度進行評分。
評分機制:
Rough-L:相同最大子串(考慮順序)
BLEU-4:預測答案和實際答案共同出現的詞數(無順序)
評分以Rough-L為主,Rough-L相同以BLEU-4排名
在對比賽形式和目標有了了解之后,下一步還要看官方給出的數據和代碼,包括訓練、驗證、測試集數據,預處理的代碼等。不過介于這是第一個比賽,經驗不足,這一步筆者是在往baseline里面加代碼的時候才做的,導致很大一段時間對數據細節不了解。
介于官方有給出了預處理之后的數據集,我們在這次比賽中直接使用了他們處理的數據集,沒有自行對原數據集進行處理。但是后來發現預處理中間其實大有可為,對最終表現也有些影響,不過那時已經接近比賽尾聲,我們只好作罷。
Step1: 閱讀論文,了解state-of-art models
頭兩個星期的預備階段用于看已有模型的論文和代碼,因為百度提供了兩個baseline系統:BIDAF和Match-LSTM,所以我們也主要看這兩個baseline的論文,再參考先前排行榜中排名靠前且開源的微軟r-net。通過這些已有的較為流行的模型,我對解決閱讀理解的流程和階段有了初步的認識。
閱讀理解模型基本分為編碼、聚合、匹配、抽取四個模塊:
Step2 模型選擇與改進
挑選Baseline System:
BIDAF與MLSTM區別:
BiDAF在Interaction 層中引入了雙向注意力機制
首先計算一個原文和問題的 Alignment matrix,
基于該矩陣計算 Query2Context 和 Context2Query 兩種注意力,
基于注意力計算 query-aware 的原文表示,
使用雙向 LSTM 進行語義信息的聚合。
另外,BIDAF Embed 層中混合了詞級 embedding 和字符級 embedding(在百度提供的baseline中沒有),詞級 embedding 使用預訓練的詞向量進行初始化,而字符級 embedding 使用 CNN 進一步編碼,兩種 embedding 共同經過 2 層 Highway Network 作為 Encode 層輸入。
通過實驗對比,我們最終選擇了效果更好的BIDAF作為baseline。
初期想法:
師兄從知識圖譜體系結構的角度提出了智能補充疑問代詞的思路,鑒于給出的問題有五分之二缺少疑問詞,僅僅給出名詞,如“xxx的價格”,他總結出三類問題所要問題:屬性、行為和狀態:
1. 屬性是不變或變得很緩慢的知識,如姓名、性別等
2. 行為,行為包括原因、過程、對象、時間、地點、結果,如遇到xxx怎么辦
3. 狀態,狀態是屬性和行為考慮時間維度后的產物,如天氣
但bidaf的Match層是類似于相似度計算,加上疑問代詞后反而降低了相似程度導致表現變差。同時,為了補充疑問代詞,我們將問題拆分為有無疑問代詞兩類,因此訓練集的規模減小,而補充代詞帶來的價值填補不了本身數據小還做了切分的損失,由此我們放棄了這個想法。
模型改造:
架構上:end-to-end 到 非 end-to-end
? 一個問題,文檔集中很可能會有多個答案,而它們彼此之間相互干擾,并且降低了神經網絡的學習效果,而針對這種情況,我們并沒有選擇在一個問題對應的整個文檔集的多篇文章中只抽取一個答案,而是每篇文章抽取一個答案,構成備選答案集,之后再從備選答案集中挑選最佳的作為我們的答案。在和其他隊伍交流的過程中,我們注意到他們截取的答案常常出現不完整的情況,而我們采用這種架構抽取的答案則幾乎不會出現。
? 對于單篇文章內答案的抽取:在一篇文章內同樣可能會有多個地方可能作為答案,在使用boundary模型預測始末位置時,一旦這篇文章模型認為的最優答案和文章內其它答案的區分度不高(概率差沒達到我們設定的闕值),那么我們就放棄在這篇文章中抽取答案。
? 由此,模型不再是end-to-end了,它的主要功能就是抽取備選答案集,而我們通過對比我們選出的答案和標準答案,據此更新參數,訓練模型從單篇文章抽取答案的能力。
實現上
在實現方面,我們做了兩點變化:
問題編碼作為上文流入文章編碼
第一點變化就是在編碼層將問題編碼作為文章上文流入文章編碼。在百度知道中,大多數時候人們的回答不會正式到將問題也加入到答案里,但是問題的一部分也應該包含在答案里,如:
Q:中國第一個乒乓球大滿貫是誰? A1:劉國梁。 A2:中國第一個乒乓球大滿貫是劉國梁。 A3:中國第一個乒乓球大滿貫。? 人們通常只會回答A1這樣的答案,雖然最正式的答案是A2。而把問題作為上文流入文章編碼,則相當于自動將A1變成A2,很大程度上強化了文章對問題的匹配程度。
加入self-matching層
如同r-net和上文中提到的,理論上聚合層已經聚合了足夠的上下文信息,但實際上它只能獲取有限的上下文,由此我們加入了r-net中的核心:self-matching層,用來在文章和問題匹配之后,強化文章內部的信息交互。而這里,也是我首次參與到代碼實現的部分。
雖然筆者之前接觸過tensorflow,但都是照著文檔,照著書打代碼,到了實際實現論文的算法時可就懵了,但是想來這么優秀的模型應當會有人去把它實現了吧,為了達到更好的效果同時也盡量減少重復造輪子,于是筆者在github上找到了幾個基于tensorflow實現的r-net,在照著論文把他們的代碼啃完之后,花了些功夫把其中的self-matching層結合進了我們的模型了,然而卻始終在reshape的調用上出錯,查找了各種解決方案后無果。
考慮到維度的升降問題是無法避免的,開源的使用reshape無法正常運行,而baseline能夠正常運行,它們的實現區別在哪里呢?想到這點,筆者又返回去看baseline的代碼并將它和開源代碼對比起來看,由此發現了區別:開源代碼中使用tf.variable顯式定義了各種需要訓練的參數,而在baseline中使用了layer的fully_connected讓tensorflow自行根據輸入的size設置參數的shape,而后自行完成乘、加的運算,就無需調用reshape函數手動調整維度,更不會遇到維度無法整除的問題了。
隨后,筆者照著baseline實現BIDAF那樣,根據r-net中self-matching的公式將self-matching實現了出來。不得不承認,哪怕把r-net的論文看了好幾遍,但在實現的時候才發現,自己還有好多的細節并沒有掌握,文章中可能只是在公式下面短短的一句話,卻是指向上一階段一系列公式的"指針",而忽略了這句話就會使得變量對應不上。
雖然這一系列過程很累也很惱人,但看到代碼最終成功運行并在服務器上跑起來,成就感還是相當足的。遺憾的是,這一層的加入對于模型的表現沒有太大的提升。
答案抽取1: EM算法
起初,我們使用EM算法,通過讓備選答案集彼此交互信息,選出共性最大的答案作為最佳答案,但發現效果并不好,并且沒有考慮到很多特征,由此僅作為一個額外的特征導入xgboost中。
EM算法作為無監督算法,目的在于在沒有標簽的情況下,讓備選答案集彼此間投票。基本思想是:首先將設置所有答案的可信度都一樣,出現在越多答案中的詞可信度越高(通過引入信息熵降低常用詞的價值),而這些詞會反過來增加某些答案的可信度,答案的可信度調整之后,在可信度高的答案的詞語可信度增加,由此雙方不斷加強,最終選出最佳答案。
這個算法在備選答案越多的情況下表現會越好,此次我們的備選答案最多有五個,雖然取得了不錯的效果但還需要更好的表現。此外,最佳答案通過這個算法選取僅考慮了答案之間的交互,省略了很多特征,如答案和問題的匹配程度、答案長度、和問題的編輯距離等等。
考慮到這是在五個答案中選擇一個最佳答案,把這視作一個五分類問題,起初筆者對視作五分類問題有疑惑,因為筆者認為答案和標號之間沒有聯系,可以隨意更換。但實際上,數據的來源是百度搜索和百度知道,搜索引擎通常會將最匹配問題的結果放在第一位,同樣的,備選答案之間也有順序,直接將第一個答案作為選出答案的分數比起隨機選擇或者把最后一個作為答案的分數高得多。
在對主流模型進行實驗挑選過后,我們最終選定了在kaggle中大放異彩,速度和準確率均高的xgboost。
答案抽取2:Xgboost
要使用xgboost訓練首先得構造訓練數據
答案的標簽生成方面,我們通過對比五個答案和標準答案的rough-l值高低,選出最高分答案的索引作為標簽。
特征選擇方面,除了先前提到的em分數、答案長度、問題長度、答案和問題的編輯距離外,我們還將神經網絡中經過各個層之后答案編碼向量同樣作為特征。
有了特征有了訓練數據,接下來就是調參了。而這對于模型最終的分數也有相當大的影響。
以下就是我們的成品模型了:
最終模型Step3 調參
改造好模型之后,參數調整這里同樣大有可為,而因為服務器性能有限,訓練前面的神經網絡一次就需要四天的時間,因此我們將重心放在了xgboost的參數調整上。
此時到了比賽結束前兩天,我也將幾乎所有的時間集中到了這里。先前在實現了self-matching之后,筆者花了一段時間了解了決策樹、隨機森林,從基本思想到公式推導,而后再了解xgboost這個相當優秀的實現,著實拓寬了眼界。
在翻閱了各種xgboost調參的教程后,對參數調整的順序和大致范圍有了基本的了解,為了不陷入手動調參的"悲慘境地",考慮到我們既然是學計算機、學軟件的,那大部分事情應當自動化讓計算機完成,于是搜索并發現了gridCV這一神函數,通過自動排列組合我們選定的參數,調用xgboost并返回分數和參數組合排名,我們只需要大致選定參數范圍,而后交給它去排列組合并返回結果,不過限于服務器性能,我們還是需要謹慎考慮選用的訓練集規模、各種參數的間隔、排列組合的個數等等因素,著實耗費了不少精力,不過也顯著將得分提了2-3個點。
未來改進點與賽后感想
改進:
感想
首次參加機器學習方面的比賽,雖然不對名次什么的抱有太大期望,不過在報名的八百多支隊伍,一百多份提交中排名14還是著實令人開心的(雖然大部分都是師兄的功勞)。
這次比賽給我帶來最大的收獲就是眼界的拓寬,而且讓我對自然語言處理中閱讀理解這個領域有了基本的了解,對于之后的學習也是相當有幫助的,之前再怎么學,也不過是照著書、照著教程打,沒有實際應用,因此也沒有真正掌握這些知識的實感。在參賽的過程中,從了解目標、了解模型、了解數據再到實地修改代碼、改造模型、調整參數,當這么一個完整的流程走下來之后,感覺成長了不少呢。
非常感謝極天信息給我這樣一個機會,以小白的狀態參加到比賽中,也感謝容福炬師兄在比賽過程中對我的指導。
源代碼
比賽中使用的神經網絡部分和xgboost調參部分的代碼可以在我的github倉庫中看到。
我的個人博客:Zedom1.top
總結
以上是生活随笔為你收集整理的百度机器阅读理解比赛赛后总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 论文解读:Attention is Al
- 下一篇: 论文浅尝 | 实体图的预览表格生成