轉載自 | 李rumor
語義相似度是自然語言理解(NLU)裡面一大核心拼圖,無論是機器翻譯、搜索、對話等,都有很大的應用空間。
語義相似度,顧名思義,主要是為了衡量兩個句子之間的相似度,來自天池新冠疫情相似句判定大賽的例子:
相似句:肺部發炎是什麼原因引起的-肺部發炎是什麼引起的不相似句:肺部發炎是什麼原因引起的-肺部炎症有什麼症狀一般都會有非常明確的案例告訴我們,什麼叫做相似,什麼叫做不相似,這個有非常明顯的場景願意,還是上面那句話,在判斷query意圖上,如果是判斷大粒度意圖的話(是否是醫療問句)那就是相似句了,如果是小粒度(症狀意圖、病因意圖)那這兩句就不相似。
常規的語義相似度架構語義相似度架構其實非常簡單,簡單地說就是兩個句子進去,進行特徵抽取,簡單到BOW、TF-IDF,複雜的就是bert(跳過word2vector、elmo???),然後進行相關性匹配計算,這塊也花樣繁多,簡單的就是餘弦相似、歐氏距離等,複雜的可以矩陣相乘等,最終到達標籤,完成一次語義相似度評估計算。OK,上圖:
孿生網絡孿生網絡本身是CV領域的東西,後來被NLP領域拿來直接用了,生根發芽,發揚光大,最經典的使用要數DSSM了。其實孿生網絡的核心思想還是藏在訓練方式上,一般的語義相似度我們都是用比較簡單二分類來訓練了,說白了就是預測出一個相似度概率和實際標籤算交叉熵,而孿生網絡,顧名思義,就是要考慮兩個網絡,具體考慮的思路,就非常像LTR裡面的pair wise,但是更為暴力一些,pairwise是兩者PK,而在DSSM裡,會給到一個正樣本(與原句相似)和N個負樣本(與原句不相似)來共同構造成一個樣本,具體的圖就長這樣:
這種方式的核心在於,以一個句子為核心來進行對比,能精準告訴模型「什麼是對的,什麼是錯的」,邊界清楚能讓模型分的更好(SVM的思想),舉個例子,我們都再說「人工智慧」,我們不知道的一切都可以被戴上這個帽子,但是邊界非常模糊,這讓人容易被忽悠,這就是因為我們不知道什麼不是「人工智慧」,模型也是一樣,給到清晰的邊界,模型能分得更好,這個是「主動學習」的一大初衷。
表徵的優化DSSM終究試一次簡單的嘗試,但以這個為出發點,大家又圍繞著DSSM做了很多工作,其中一大重點就是把DSSM這種base line級別的操作(文章用的是word hashing)升級為一些效果更好的操作:
CNN-DSSM:也被叫做CLSM,把全連接層換成了CNN。LSTM-DSSM:把全連接層換成了LSTM,嚴謹的應該說是peephole LSTM。比較新潮的Attention操作也偶有見到。self-attention和co-attention都有,attention能夠一定程度的充當「關鍵詞抽取」的作用,因此在特定場景(例如信息冗餘較多的對話場景)效果提升有些明顯。有關attention的使用,推薦一篇論文Attention-Based Convolutional Neural Network for Modeling Sentence Pairs,也就是所謂的ABCNN,感覺把attention在這塊的使用講的比較好:
BCNN(basic cnn)其實就是用cnn作為特徵提取的關鍵步驟,只不過這裡的卷積參數是雙塔共享的。ABCNN-1針對兩個句子的原始表徵(沒有進行CNN時),構造了attenton矩陣作為卷積輸入的另一個通道。ABCNN-2在1的基礎上,把attention的步驟放在了池化之前,該attention用來對卷積的結果進行reweight,然後再做池化。換積木這種事情姑且只能算小打小鬧,我們的目標不止於此,而是會——換大積木,BERT,它具有更為強力的BERT能力,效果自然也越好,sentence-bert就是對bert在語義相似度上的一個重要的使用。
向量化表徵語義相似度能讓我們衡量兩個句子的語義相似度,但是實際上我們的應用場景更多是「在句子庫裡面找到最接近給定句子的句子」,例如一個句子「明天天氣」,我要找到整個庫裡面最接近的那個句子,例如「明天的天氣」、「明天下雨嗎」、「天氣之子」等,如果簡單的一個一個匹配去找,複雜度就是O(N),這個數字無疑非常可怕,當庫是千萬級別大小的時候,這個搜索就變得非常低效,因此我們是需要特定的手段來解決這個問題的,這套解決方案就是——最近鄰召回檢索,這裡依賴兩個技術點,一個是基於語義相似度的句子向量化表徵,另一個是最近鄰向量索引。
最近鄰向量索引不知道大家對KNN有沒有了解,在統計學習方法中,第一個講的方法就是他,說白了就是找最接近給定樣本的N個訓練樣本,他們大部分屬於什麼什麼類,那這個給定樣本就是什麼類,而問題在於怎麼找到最接近的N個樣本,這實際上就是一個通過向量找向量的工作,在《統計學習方法》裡面提出的是kd tree,而現在比較流行的主要是兩個——同樣是基於樹的annoy和基於圖的hnsw,經過一些評測(https://zhuanlan.zhihu.com/p/152522906),這兩個方案都有比較領先的性能,網絡上有比較明確的原理和實現方案,此處就不贅述啦~
向量化表徵向量化表徵對語義相似度有了更高的要求,它不僅僅要求我們要算出兩者的相似度,還要求在計算過程中,需要把句子表徵都需要降維到向量級別,因為後續下遊要通過最近鄰向量完成搜索,這個問題其實還是比較簡單的,常規的操作不外乎就是2種,平均池化和最大池化,在Sentence-BERT中又提到了一種,所以總共就是3種:
平均池化,對表徵的矩陣整體進行平均池化,mean/average pooling,得到向量。最大池化,對表徵的矩陣整體進行最大池化,max pooling,得到向量。更多前沿操作上面應該都是業界比較公認的比較基本的操作和理解,在此基礎上帶大家看一些比較前沿的一些使用方案和方法。
機器之心-百度NLP針對傳統匹配(如BM25)的多義同義詞處理、句子結構複雜、匹配非對稱等問題,在sim-net(即一一匹配計算相似度)的基礎上,做了多粒度切詞、高頻判斷語義引入等先驗信息的方式來對提升效果,並在實驗上針對正負樣本比例、閾值判斷等做了很多的嘗試(文章具體沒說)。
Facebook使用經驗在KDD2020裡面facebook分享了自己在文本匹配方面的經驗:Embedding-based Retrieval in Facebook Search。
首先在訓練上,使用的是比較常見的三元組hinge loss。
至於模型,則是和DSSM類似的雙塔結構,query和doc分別表徵後進行相似度匹配,但是在特徵上花費了一些功夫,新增了位置特徵、社交特徵,後兩個都是個性化特徵,大家就根據實際情況選用即可。
在訓練上,負樣本的構建一直是語義相似度的一個老大難問題,根據他們的經驗,曝光未點擊和資料庫隨機抽取一起用的效果會更好。
至於服務上,即最近鄰召回,facebook則用的是自己開源的faiss引擎,內部搭載的是annoy索引機制。
另一方面,文章再提到了負樣本構建,即Hard negative mining問題,一般是通過在線曝光未點擊、離線相似度閾值範圍抽取的方式挖掘。
文章還提到一個很有意思的提升方案,就是模型融合,簡單地說就是模型預測的向量分別進行歸一化後進行concat,然後進行檢索。
螞蟻金服語義相似度競賽的經驗特徵工程的嘗試,除了語義向量外,還可以加入長度、編輯距離、n-gram相似度、詞彙統計特徵、關鍵詞、疑問詞相似度、主題意圖相似等。小結小結幾個關鍵點吧
分別表徵後進行交互仍然是主流,但是由於向量召回的存在,歐氏距離餘弦距離仍然是主流,所以模型的優化核心就放在了如何更好地表徵句子上。訓練方式基本就固定在了DSSM或者是孿生網絡類似的聯合訓練上。負樣本的構造,HNM問題是提升效果的一個關鍵因素。業界的嘗試沒有想像中的複雜,而是在業務和實際的操作中尋找經驗和結論,這很大一部分原因和向量召回這一需求的約束有關。