- 前言:
員工Bot是e成科技一款服務於企業內部員工的機器人助理產品。其中,自動解答員工頻繁會問到的業務知識類問題是員工Bot的核心應用場景,藉助員工Bot可以顯著的減少HR日常重複性工作。
本文主要討論自然語言處理演算法在員工Bot場景下的應用,其核心是短文字(問題)的相似度匹配。這是一個自然語言處理領域成熟的方向,有很多經典方法,但隨著近些年來深度學習的進展,效果更好的新方法也在不斷湧現。作為一名NLP領域的演算法工程師,一方面需要追蹤最新NLP領域的最新研究進展固然重要,同時也必須結合實際情況,探尋和落地可行的方案。
- 方案選擇:
在員工Bot場景中,產品經理基於業務場景收集人力資源場景的FAQ知識庫,包含人力資源領域員工經常提出的問題和對應的解答。演算法需要根據使用者的提問匹配到知識庫裡面最合適的那一個答案,並判斷是否進行回答。在這個場景中,知識庫是垂直領域的,它的大小取決於這個業務場景需要支援的範圍有多大,一般來說問題對(問題-答案)的數量都在幾百到幾千不等。從技術上說,上述問題可以抽象成一個文字與文字的相似度匹配問題,下面我們給出基本的技術方案:
召回方案
考慮到模型的負載和延時情況,使用者的問題的內容並不會和語料庫中的所有問題進行匹配,而是提前將語料庫中的問題進行索引,並先進行粗粒度的相似召回,然後再用精細化的匹配模型去計算最相似的那個問題。粗粒度的索引常見的方案有:(1)基於詞的倒排索引(Inverted Index);(2)基於稠密向量的向量召回。兩種方法都能實現粗粒度的召回,但是倒排索引需要構建有效的索引詞表,因此需要根據應用場景調整詞表。而基於向量召回的方法,只要確定構建稠密向量的方法,就可以用Faiss[1]或者annoy[2]等工具索引起來,在犧牲少量精度的情況下,高效地完成問題的召回。本文最後採用的方案:基於文字中詞的IDF(Inverse Document Frequency)值,獲得加權句向量(Sentence Embedding),然後用annoy工具,將資料庫中的問題集索引起來,實現粗粒度的相似問題召回。
傳統的文字匹配方法
我們分別調研了傳統的文字匹配方法和深度學習方法,比較了兩種方法的優點和不足。傳統的BM25/Jaccard/Cosine Similarity 等基於詞匹配的模型都具有表示方法簡潔、運算方便的特點,解決了詞彙層面的匹配問題。另一方面,基於詞匹配的模型也有一定的侷限,如一詞多義、同義詞關聯以及語序問題。舉例來說,同樣是想知道公司的位置,“公司位置”和“辦公地點在哪兒”這兩個問題的意思完全一致,但是字面上沒有任何的重疊,用傳統文字匹配方法來計算,他們的相似度都是0。文字匹配模型需要解決這種在詞袋層上雖然沒有overlap,但是語義層面是相似的文字匹配問題。
深度學習文字匹配的方法分類
深度學習的蓬勃發展為我們提供了新的思路,基於神經網路訓練出來的詞向量(Word Embedding)來進行文字匹配的計算獲得了大家的一致認可,就像在問答系統裡大家預設將 query與question進行匹配一樣,在深度學習模型中加入預訓練的詞向量是“預設”的選項。
基於深度學習的的文字匹配方法主要分為兩類,一類是Representation-based模型,這類方法先分別學習出query和question的句向量表示,然後用兩個向量做餘弦相似度計算或者連線多層感知機(MLP)得到最後的匹配分,重點是學習query和question對應的句向量表示;另外一類是Interaction-based 模型,這類先構建匹配矩陣(Matching Matrix),然後利用匹配矩陣學習一個匹配函式,最後連線多層感知機輸出匹配分,重點是匹配函式的學習。
圖一:問題相似度匹配模型總結
- 技術演進:
深度學習匹配模型
經過最初的第一輪調研後,我們確定採用深度學習方案。而在模型的選擇上,我們一開始選擇了在各大賽事中評價很好的representation-based 的孿生網路(Siamese Network)模型(也叫“雙塔”模型)。具體的結構實現我們參考的是Paul Neculoiu等人在2016年發表的工作(Learning Text Similarity with Siamese Recurrent Networks[3]),模型的結構如下所示:
圖二: “雙塔”模型結構
基本方案流程是:構建query和question的文字pair,透過embedding layer生成詞向量矩陣,這兩個詞向量矩陣分別透過神經網路計算得到句向量。有了句向量之後,在匹配層進行相似度計算,實際中最常用的就是cosine函式,或者連線一個多層感知機(MLP)網路,輸出最終的匹配分。
完成模型的搭建和訓練之後,透過測試集的測試,我們發現模型的效果完全沒有達到預期,模型基本上是無法工作的狀態。分析主要原因在於有標註資料過少,導致模型過擬合嚴重,效果無法達到預期。在短期內無法得到足夠標註資源的情況下,我們不得不求助於不依賴大規模標註樣本的傳統文字匹配方法。
傳統文字匹配模型
構建傳統的文字匹配模型,需要人工的設計才能保證一個不錯的效果。因為構建的模型就是直接用來做預測的,因此特徵以及特徵的引數選擇會決定最初模型的可用程度。除了文字的原始特徵(TF/IDF等)之外,還有傳統的Jaccard/BM25 (BM:Best Matching)資訊匹配特徵[4],以及WMD(Word Mover ‘s Distance)/餘弦相似度(Cosine Similarity)來構建組合文字匹配方法;
其中 BM25/Jaccard/WMD 是一系列基於文字之間詞表重合度的評分函式,只是不同函式之間側重點和引數不同。CosineSimilairy 是最為常用的餘弦相似度。ai 是不同的評分函式的引數,因為引數較少可以直接透過手動除錯的方式獲得最佳可用的值。
文字匹配模型最佳化
針對前面講到的傳統匹配方法存在的問題,我們也進行了改進工作。比如,透過對大量的平行語料進行統計分析,構建同義詞表和多義詞表。然後基於同義/多義詞表,改進分詞的效果,同時對訓練集進行擴充套件或者對訓練集進行同義詞替換(同義詞用統一的識別符號表示)的方式,顯著的改進了匹配演算法的效果。
最佳化後的傳統資訊匹配模型,在匹配效果上遠遠超過了深度學習模型,基本能夠達到業務方的要求。同時模型計算效能也大大提升,模型也更具有可解釋性。這給之前非常迷信最新深度學習演算法的我們也很好地上了一課,新方法並不是總比舊方法好,關鍵在於結合場景選擇合適的方法。
但隨著業務的發展,我們也發現隨著語料的增加,同義詞、相關詞及人工規則也要隨之增加也調整,使得整體的邏輯變得複雜,增加了很多工作量。在傳統的匹配方法最佳化到了瓶頸之後,我們希望重新使用深度學習學習模型。
深度學習模型進一步探索
圖二和圖三顯示了深度學習匹配模型中Representation-based框架和Interaction-based框架。從圖中可以看出模型的差異主要在於是否直接得到句向量及匹配層的實現方式。Representation-based的主要目的是儘可能的將輸入層的 query 和 question 學習到充分表示的句向量,然後進行匹配計算。但這需要大量語料的支援,這在特定的垂直領域並不容易獲得。而Interaction-based模型,首先構建query和question在詞粒度的匹配矩陣(或張量),然後將這個匹配矩陣(或張量)輸入到預測函式中得到最終的相似度。相比於Representation-based模型,Interaction-based模型的預測函式只需要輸入抽象的匹配矩陣,與語料的領域無關。
因為我們選擇採用無監督的方式構造互動矩陣,並利用其他領域語料訓練預測函式。這樣既可以獲得充足的訓練語料,又可以避免不同領域之間的鴻溝,本質上屬於一種改進的遷移學習方法。具體在Interaction-based模型中我們採用了K-NRM[5],主要出於計算效率和模型效果的考慮。該方法對於 query中的每個term計算它在question中的匹配訊號,計算整體的匹配強度的分佈即離散化分桶,統計在每一個桶上的次數,這樣就可以得到一個關於query中每個term和question匹配分的一個直方圖,即一個向量。再透過全連線層學習到最終的匹配分。K-NRM模型結構如圖三所示。
圖三 K-NRM模型結構
經過實際測試獲得了令我們驚喜的結果,在不做任何調優的情況下,模型在測試集上分類任務的準確率就達到了65%。模型的實際表現驗證了我們開始的猜測,為後續最佳化提供了空間,同時也為更加複雜的組合模型提供了探索基礎。
傳統模型和深度學習模型的融合
除模型演算法的調研以及本身的最佳化改進之外,同時我們將傳統的匹配模型的特徵融合和深度學習中間隱層網路進行拼接,實現了傳統文字匹配方法和深度學習模型的融合(如圖四所示),進一步提升了模型效果。我們將組合模型在上面同樣的開源中文訓練集上進行訓練,在同樣的測試集中,準確率直接提高到了81%。而這樣的結果,不僅說明融合模型的有效性,也驗證了我們的探索方向。
圖四 改進後的K-NRM模型結構
- 總結
回顧整個專案過程,我們經歷了深度學習方法到傳統文字匹配方法,到深度學習演算法,最終到深度學習演算法與傳統文字匹配方法結合的過程。在這個過程中,我們對業務及不同演算法的理解也上了一個臺階。針對文字任務的特點結合實際應用場景,除了從深度學習模型更好地設計選型之外,也可以將一些傳統的文字匹配技術更好地和模型融合,更高效地獲取更好的效果。
- 參考
[1] A library for efficient similarity search and clustering of dense vectors
[2] Annoy (Approximate Nearest Neighbors Oh Yeah) is a C++ library with Python bindings to search for points in space that are close to a given query point.
[3] Learning Text Similarity with Siamese Recurrent Networks
[4] 演算法導論 第三版 Thomas H.Cormen , Charles E.Leiserson,Ronald L.Rivest, Clifford Stein
[5] End-to-End Neural Ad-hoc Ranking with Kernel Pooling