小哥哥,檢索式chatbot瞭解一下?

夕小瑶發表於2018-09-25

小夕從7月份開始收到第一場面試邀請,到9月初基本結束了校招(面夠了面夠了T_T),深深的意識到今年的對話系統/chatbot方向是真的超級火呀。從微軟主打情感計算的小冰,到百度主打智慧家庭(與車聯網?)的DuerOS和UNIT,到滲透在阿里許多產品的全能型智慧客服小蜜,以及騰訊的小微和搜狗的汪仔,更不必說那些大佬坐鎮的獨角獸公司了,小夕深感以對話為主戰場的NLP之風在工業界愈演愈烈,嚇得小夕趕緊碼了這篇文章。

注:本文同步到小夕的知乎專欄,可能存在的校正與更新見https://zhuanlan.zhihu.com/p/44539292

1. 掃盲

對話的概念很大,從輸入形式上分為文字和語音,本文當然只考慮文字。從對話目的上分為任務型對話與非任務型/閒聊型對話。顧名思義,任務型對話就是為了解決任務而進行的對話,比如你讓Siri幫你定鬧鐘、發簡訊等,而閒聊型對話當然就是human-to-human的正常聊天啦。本文就不討論任務型對話了,有興趣的同學可以戳這裡掃掃盲,本文聚焦在非任務型對話的多輪對話問題上。

要完成對話的建模,目前主要分為檢索式、生成式以及檢索與生成融合的方式。顧名思義,檢索式就是透過檢索與匹配的方式從已有的大量candidate responses中找出最合適的那個作為response;生成式則是事先透過訓練來把對話知識塞進模型中,推理的時候首先模型的encoder部分去讀歷史對話,然後模型中的decoder/語言模型部分直接生成相應的回覆;檢索與生成相結合的方法則玩法很多了,比如用生成模型來做檢索模型的reranker,用生成模型來作改寫,用生成模型生成的response來作為檢索模型的一條response等。限於篇幅,本文只講純檢索式的,其他的以後再說(maybe不會太久╮( ̄▽ ̄"")╭)。

2. 檢索式模型的套路

檢索式對話的一般套路是首先構建一個由大量query-response pair構成的知識庫(比如從豆瓣、貼吧等地方抽取),然後將對話中最後一次的回覆作為query,透過經典的資訊檢索方式(倒排索引+TFIDF/BM25)作q-q匹配來召回若干相關的candidate responses。注意,這一步實在太粗糙了,完全沒有考慮語義,所以直接使用檢索分數來挑選最優response顯然是太過簡單粗暴不靠譜。所以我們還需要使用考慮語義的深度文字匹配模型來將歷史對話與這些檢索出來的candidate responses進行matching/reranking,從而挑選出一個更加合適的response。

那麼怎麼進行文字的深度匹配呢?

一個很簡單的做法是直接把複述識別/自然語言推理/檢索式問答這些相關領域的文字匹配模型直接拿來用,但是顯然這樣僅僅建模的是單輪對話,於是聊天機器人就變成了只有7秒記憶的金魚╮(╯▽╰)╭,因此,建模多輪對話是非常有必要的。

不過了解一下文字匹配模型是很有幫助的。這方面今年COLING有一篇文章[6]總結的不錯,把基於表示與基於互動的SOTA匹配模型都給詳細總結對比了。

基礎比較差的同學可以看這篇文章,從2013年的DSSM[9]開始入手,慢慢補。篇幅所限,加上這方面研究相對很充分了,小夕就不展開講啦。所以話說回來,將多輪對話與候選回覆進行匹配的正確方式是什麼呢?

3. 論文串燒

一切還要從兩年前的秋天說起,曾經,有一個少年。。。

算了算了,還是正經點吧,要不然沒法寫了╮( ̄▽ ̄"")╭總之,小夕從眾多魚龍混雜的檢索式多輪對話的論文裡精選出如下4篇進行串燒(按時間順序,從經典到state-of-art),包括:

  • EMNLP2016 百度自然語言處理部的xiangyang大佬的Multi-view[1]

  • ACL2017 MSRA吳俁大佬的SMN[2]

  • COLING2018 上交的DUA[3]

  • ACL2018 百度自然語言處理部xiangyang大佬和lilu女神的DAM[4]

不過不要怕,小夕的論文分享總是淺顯易懂還帶點萌( ̄∇ ̄)

必須要提的經典:Multi-view model

想一下,怎麼才能從單輪q-r的匹配擴充套件到多輪呢?一個最最最簡單的想法就是直接把多輪對話首尾連線變成一個長長的單輪╮( ̄▽ ̄"")╭比如這種:
小哥哥,檢索式chatbot瞭解一下?如上圖,首先將各輪的對話連線起來(這裡在連線處插入一個"__SOS__"的token),然後這裡用RNN系網路取最後時刻隱態的方法分別得到query和response的向量表示,進而將這倆向量透過
小哥哥,檢索式chatbot瞭解一下?得到匹配分值(M為網路引數),進而透過小哥哥,檢索式chatbot瞭解一下?得到匹配機率(p為引數)。當然,其實這裡本質上就是一個基於表示的文字匹配模型,所以完全可以用更復雜的表示方法和匹配函式(如SSE模型[8])來完成這個過程。

聰明的童鞋肯定可以想到,顯然這種將長長的word embedding sequence直接塞進網路得到整個多輪對話的表示(context embedding)的做法未免太看得起神經網路對文字的表示能力了,因此作者提出,不僅要在這個word-level上進行匹配,而且還要在一個更高的level上進行匹配,這個level稱為utterance-level(即把對話中的每條文字(utterance)看作word)。
小哥哥,檢索式chatbot瞭解一下?如上圖的綠色->黃色->紅色的部分,首先得到對話的每條文字(utterance)的向量表示(這裡用的14年Kim提出的那個經典CNN),這樣歷史的多輪對話就變成了一個utterance embedding sequence。之後再透過一層Gated RNN(GRU、LSTM等)把無用的utterances中的噪聲濾掉,進而取最後一個時刻的隱狀態得到整個多輪對話(context)的context embedding啦。

拿到context embedding後,就可以跟之前word-level中的做法一樣,得到對話與candidate response的匹配機率啦。最後,將word-level得到的匹配機率與utterance-level得到的匹配機率加起來就是最終的結果。

實驗結果如下:
小哥哥,檢索式chatbot瞭解一下?可以看到utterance-level確實是明顯比word-level work的,而且整合一下提升效果更顯著。因此從這篇論文後的大部分論文也follow了這種對每條utterance分別進行處理(表示或互動),而後對utterance embedding sequence用Gated RNN進行過濾和得到context embedding的思路。

而到了2017年,文字匹配的研究明顯變得更加成(花)熟(哨),各種花式attention帶來了匹配效果的大幅度提升,這也標誌著檢索式多輪對話這方面的玩法也將變得豐(麻)富(煩)。

一次大大的進化:SMN model

如果說Multi-view模型在檢索式多輪對話領域開了個好頭,那麼SMN則是將這個大框架往前推進了一大步。雖然表面上看Multi-view模型與SMN模型相去甚遠,但是熟悉文字匹配的小夥伴應該有注意到,16年左右,基於互動的匹配模型開始代替基於表示的匹配模型成為主流[6],因此在Multi-view中內嵌的匹配模型是基於表示的,而到了17年的這個SMN模型則使用了前沿的基於互動的匹配方法。另外除了改變文字匹配的“派系”之外,SMN還有一個比較亮的操作是在做文字匹配的時候考慮了文字的不同粒度 (granularity) 之間的匹配,這個操作也成為了後續一些paper的follow的點。

對文字匹配比較熟悉的同學應該在AAAI2016看過這麼一篇paper:

Text Matching as Image Recognition (參考文獻[5])小哥哥,檢索式chatbot瞭解一下?如圖,基本思想就是,使用傳統的attention來計算出兩個文字的word-level對齊矩陣/相似度矩陣後,將該矩陣看成一個影像,然後使用影像分類模型(如CNN)來得到更高level的相似度特徵表示(比如phrase level, segment level等),進而最終得到全域性的相似度匹配特徵。這也是最早的幾個互動式文字匹配模型之一。

SMN這篇paper就是採用了這個思想。給定一個candidate response,在生成word-level的每個utterance的向量表示的時候,首先計算出歷史上每個utterance跟該response的對齊矩陣,然後對每個對齊矩陣,均使用上面這種影像分類的思想生成high-level表徵文字對相似度的特徵向量作為該utterance的向量表示(utterance embedding)。

之後就是使用前面Multi-view中的做法,從這個utterance embedding sequence中得到整個對話的context embedding,最後將該context embedding和之前的word-level下得到的context embedding與response的向量去計算相似度了。

不過作者這裡在計算對齊矩陣和得到context embedding的時候,用了更復雜一些的方法。如圖
小哥哥,檢索式chatbot瞭解一下?在計算對齊矩陣的時候,作者不僅用了原始的word embedding,而且同時用了RNN系模型對文字encoding之後的隱狀態(即編碼過上下文資訊的word embedding,可以看作phrase-level的"word embedding"了),這樣就生成了兩份對齊矩陣,然後這樣將兩份對齊矩陣作為兩個channel丟進“影像分類模型”,從而保證了即使影像分類模型很淺,也能抽取出比較high-level的特徵,得到高質量的utterance embedding。

另外,作者這裡在得到最終的context embedding的時候,除了使用RNN最後一個隱狀態的傳統做法(記為小哥哥,檢索式chatbot瞭解一下?)外,作者還額外實驗了對頂層各個time step的隱狀態進行加權求和(權重可訓練)的方式(小哥哥,檢索式chatbot瞭解一下?)以及更復雜的整合utterance自身表示的資訊並使用self-attention的方式(小哥哥,檢索式chatbot瞭解一下?),實驗結果表明,總的來看小哥哥,檢索式chatbot瞭解一下?的方式稍好一些(不過考慮到額外引入的計算和儲存開銷,一般不值得這樣做)。有興趣的同學可以去看原paper,這裡就不展開講啦。小哥哥,檢索式chatbot瞭解一下?從實驗效果來看,SMN相比較之前的Multi-view有很大的提升,這也說明了:

  1. 在q-r匹配上,基於互動的模型相比基於表示的模型有更大的優勢,這一點與檢索式問答和NLI任務中的實驗表現一致;

  2. 對文字進行多粒度表示是很有必要的。

utterance也要深度encoding!DUA model

雖然看似SMN已經考慮很周到了,但是如果細想一下,其實SMN的建模方式還是跟現實中人們的聊天習慣存在不小的gap的。其中一個方面就是,Multi-view和SMN都沒有重視utterances之間的語義關係,僅僅是透過一層Gated RNN進行了軟過濾和簡單encoding。然而其實很多時候建模utterances之間的關係是很有必要的,甚至對於過濾來說也是很重要的資訊,這也是DUA的motivation。我們知道,其實聊天中很少從頭到尾都是一個主題,比如下面的對話:

case1:

u1-> 路人甲:小夕,中秋節你去哪裡玩兒啦?

u2-> 小夕:當然是去買買買呀~

u3-> 路人甲:你之前不是想去爬百望山嘛?沒去嘛?

u4-> 小夕:想去呀,然鵝她們去玩兒都不帶我(。 ́︿ ̀。)

u5-> 路人甲:你稍等下啊,我下樓取個快遞

u6-> 小夕:去吧去吧,順便幫我買個辣條!

u7-> 路人甲:好呀,要啥口味的?雞肉味?

u8-> 小夕:這特喵的還分口味?

u9-> 路人甲:回來啦,對了,要不然下週我帶你去吧?

u10-> 小夕:好呀好呀,喵喵喵~

這裡如果把小夕看作是檢索式chatbot,假如對話進行到第6步(u6),這時候最後一個utterance是u5,也就是“你稍等下啊,我下樓去取個快遞”。顯然,這時候其實相當於對話的話題發生了劇烈偏移,如果這時候小夕去跟一堆candidate responses做匹配的時候還去考慮u1-u4這些爬山相關的utterances的話,顯然就容易召回跟u5很不相關的回覆。同樣的道理,如果對話進行到u8,其實這時候真正有用的historical utterances是u6-u7;對話進行到u10的時候,有用的utterances又變成了u1-u4。

除此之外,對話中還容易夾雜一些類似於停用詞的噪聲,比如

case2:

u1-> 路人乙:小夕,明天約約約?

u2-> 小夕:。。。

u3-> 路人甲:哈哈

u4-> 小夕:應該木有時間

這裡的u2和u3就是類似於停用詞的“停用utterance”,所以對於這一類utterance,最好的辦法就是忽略掉而不是讓它們參與匹配。

怎麼解決上述這兩類問題呢?那就直接上這個讓人看著灰常懵逼的DUA的模型圖吧:
小哥哥,檢索式chatbot瞭解一下?如圖,這個圖乍一看有點亂(其實畫的確實很不怎麼樣(作者應該不會看我的文章吧2333)),論文裡的公式標記也用的亂亂的(尤其第3.3節憑空冒出來的n弄得我懵逼了好久,到底是不是3.1節的n,是的話這裡貌似就不對了,如果不是,這裡又代表啥),一些細節也沒交代清楚(比如3.1的S到底是個矩陣還是向量,如果是向量,那麼怎麼得到的這個向量?是矩陣的話3.2節的聚合又不對了)。

好了不吐槽了,不過其實這裡的思想很直接,就是說,以前的paper呀,得到utterance embedding後就直接拿去RNN了,都沒有像處理word embedding那樣去好好做encoding,所以我們這裡對utterance embedding也同樣要做深度的encoding!

那麼怎麼做這個encoding呢?透過觀察上面的倆cases可以發現,很多時候對話中是有hole的(比如上面case1中的u9的上一句話是u4,所以u5-u8形成了一個空洞),甚至可能很多個hole,所以這裡做encoding的時候最合適的是使用self-attention而不是RNN更不是CNN。所以作者在這裡先用了一層(加性)self-attention來把上下文編碼進每個utterance embedding:
小哥哥,檢索式chatbot瞭解一下?

這裡ft是t時刻的utterance embedding(就是前面聚合操作之後的那個向量表示),fj (j=1,2,...n) 是其上下文(即全部時刻的utterance embedding,一共n個)。 透過這個encoding操作,一下子每個時刻的utterance都能跨越時間和空洞把自己的那一群小夥伴聚在一起啦。

然鵝顯然self-attention丟失了utterance的順序資訊,因此作者這裡又把encoding後的utterance embedding跟encoding前的utterance embedding拼接起來又過了一層Gated RNN:小哥哥,檢索式chatbot瞭解一下?

Gated RNN(GRU、LSTM等)一方面可以按照時序進一步encoding,另一方面裡面的輸入門也起到了filter的作用,正好可以在加強encoding的同時把無用的資訊過濾掉。看,這樣就完成了當時的motivation,最後的這個utterance embedding可以說乾淨合理的多了。整個模型的其他部分則跟SMN基本沒區別。

小哥哥,檢索式chatbot瞭解一下?

從實驗結果來看,DUA的效能確實比SMN有了進一步明顯的提升。

state-of-the-art:DAM model

這篇是多輪對話領域難得的好paper,可能xiangyang大佬太忙,都木有打打廣告什麼的╮( ̄▽ ̄"")╭。作者這裡拋棄了之前的建模utterance embedding sequence的思路,而是把NLP很多領域的前沿操作優雅乾淨的整合為一個全新的框架來建模多輪對話問題,不僅模型非常work,實驗章節也對模型各個component的特點和有效性進行了充分的探索和論證,是繼Multi-view和SMN以來多輪對話領域又一個不得不提的經典模型。

另外,遇到一張清晰漂亮的模型圖不容易哇,就直接上圖吧
小哥哥,檢索式chatbot瞭解一下?

ps:這張圖這麼少女心,我猜是lilu女神畫的。

還記得前面說的SMN的一個亮點是做了兩級粒度的文字表示嘛?那麼很自然的就有了一個問題:兩級就夠了嘛?有沒有必要設定更多級呢?如果有必要的話,那麼怎麼去表示和學習這更多級粒度的語義表示呢?

首先答案當然是肯定的,17年的SSE文字匹配模型和今年特別火的ELMo[10]都說明了對文字的深層表示可以學習到更加高level的語義單元,然而我們知道像SSE和ELMo這種堆多層RNN的做法會極大的增加模型的推理代價,這極大的限制了它們在工業界的應用。而堆多層CNN在文字里又不容易調work,需要精細的設計網路並藉助一些tricks,因此很自然的做法就是使用Transformer[11] encoder來得到文字的多級表示啦(沒看過transformer那篇paper的趕緊去補啦,做NLP哪能不知道transformer)。

所以如圖,DAM首先就用transformer的encoder來得到了每個utterance和response的多粒度文字表示(即圖中的Representation部分),之後作者對每個utterance-response pair的每個粒度下的表示分別計算兩個對齊矩陣(即圖中的Matching部分)。

等下,怎麼是倆對齊矩陣?除了傳統的計算對齊矩陣的方式,還有新的玩法啦?

這裡作者提出了一種更加深(隱)層(晦)的匹配方法,操作不難,但是為什麼會work還是挺難以理解透徹的(雖然作者在5.2節已經有很努力的講了)。總之,先來簡單提一下傳統的attention計算對齊矩陣的方式。

傳統的方法無非就是把文字1中的word embedding sequence和文字2中的word embedding sequence進行詞-詞比較,這裡的比較分為加性方法和乘性方法,基礎差的同學可以看下面這段複習一下。

注:詞-詞比較的方式分為加性和乘性,加性就是將要比較的兩個word embedding進行相加(相加前可以先過一個線性變換甚至MLP)然後啟用後跟一個虛擬的向量做內積(其實這個虛擬向量就是個可訓練的同維度向量,我理解的它存在的意義就是對每個維度的加法比較+啟用後的結果進行scaling,畢竟維度不同方差也可能不同嘛),內積的結果就是對齊程度啦。乘性則容易理解一些,就是將兩個word embedding直接進行相乘(準確說是內積)或中間夾一個可訓練方陣(即小哥哥,檢索式chatbot瞭解一下?的形式),內積的結果就是對齊的程度啦。不過要記得當維度很高時,乘性方式最好對結果做個歸一化以免進入softmax飽和區(參考Transformer)。小哥哥,檢索式chatbot瞭解一下?如上式,作者這裡使用的是乘性的方式,這裡的l就是指的第l級粒度,ui是指的第i個utterance,ui有小哥哥,檢索式chatbot瞭解一下?個詞,response有nr個詞。這裡就是說,對於每級語義粒度的每個utterance,都是將其中的每個詞k去跟response中該粒度下的每個詞t去算內積,從而得到一個小哥哥,檢索式chatbot瞭解一下?的對齊矩陣。

對於傳統的attention,如果兩個詞在semantic或syntactic上離得近,就容易得到比較大的匹配值(如run和runs, do和what)。然而對於一些比較深層和隱晦的語義關係就很難直接匹配了(我們不能強求前面的網路把各級粒度的語義單元的embedding都學的那麼完美呀對吧),所以作者這裡提出了一個更加間接和隱晦的attention方式,如下:
小哥哥,檢索式chatbot瞭解一下?這裡的AttentiveModule的3個引數依次為attention的Query、Key和Value,不熟悉的同學去複習Transformer,這裡就不贅述啦。首先看公式8和9,這裡先透過傳統的attention來把utterance和response中的每個詞用對面文字的詞加權表示,得到新的utterance的word embeding sequence表示和新的response的word embedding sequence表示,之後再用一層傳統的attention來計算出一個對齊矩陣來作為第二個對齊矩陣。

顯然這種方式將utterance中的詞和response中的詞之間的依賴關係(dependency information)也作為詞的表示加入了對齊矩陣的計算,所以說是建模了更加深(復)層(雜)的語義關係。不過,作者在論文5.2節有提到這兩種attention方式匹配文字的操作其實是互補的,並且給出了一個case解釋,然而小夕功力有限,努力理解了一下還是沒理解 ╮( ̄▽ ̄"")╭希望有看懂的小夥伴給小夕講講或者貼到評論區~

經過這麼深層的匹配後,每個utterance中的每個詞位都包含了2(L+1)維的匹配資訊(L為Transformer encoder的層數,1為原始的word embedding,2為對齊矩陣的數量),作者這裡又把utterances堆疊到一起,就形成了這個漂亮的3D粉色大立方體
小哥哥,檢索式chatbot瞭解一下?所以這個大立方體的三個維度分別代表對話上下文中的每個utterance、utterance中的每個詞(位)、response中的每個詞(位)。

之後,再透過一個兩層的3D的卷積神經網路來從這個大立方體中抽取特徵,得到匹配層的特徵,最後的最後透過一個單層感知機得到該candidate response的匹配機率。

說了這麼多,來看看實驗結果吧~

小哥哥,檢索式chatbot瞭解一下?

可以看到實驗結果非常漂亮(當前的state-of-art),尤其是小哥哥,檢索式chatbot瞭解一下?這種比較有實際意義的指標(從10個candidates裡召回top1)。而且DAM沒有像DUA那樣對utterance embedding sequence做深層encoding(這裡直接用的3D conv抽特徵了),但是實驗結果明顯比DUA好,可以說網路設計的很棒棒啦。另外,作者這裡也給出了去掉各個component後的效能情況:

小哥哥,檢索式chatbot瞭解一下?

比如對比DAM與倒數第二行可以看到,去掉那個複雜的深度注意力機制後,網路效能出現了明顯的下降,說明論文中提出的這個“間接”的注意力機制確實能捕獲到一些神奇的模式。

總結

最後小夕非常主觀的總結一下這四個模型的亮點:

Multi-view提出了將utterance建模為一個語義單元來建模多輪對話問題;

SMN使用基於互動的匹配模型代替基於表示的匹配模型,並對文字進行多粒度表示;

DUA對utterance embedding進行深度的encoding來建模utterances之間的依賴關係;

DAM一方面對文字對進行多粒度表示並提出了一種深度attention的方法,另一方面拋棄了之前建模utterance embedding sequence的思路,提出了一種將word-level和utterance-level的資訊整合到一起,構建一個多通道的3D Image(其實把utterance看成單幀的影像,那這個大方塊更像是一個影片),進而透過3D Image分類器完成匹配的新思路。

夕小瑤的賣萌屋
夕小瑤的賣萌屋

轉自微信公眾號【夕小瑤的賣萌屋】,幾個有顏有料的小仙女分享機器學習乾貨的公眾號,專注於NLP、搜尋與推薦技術前沿

相關文章