NLP系列之句子向量、語義匹配(二):BERT_avg/BERT_Whitening/SBERT/SimCSE—方法解讀
作者簡介
作者:ZHOU-JC (廣州云迪科技有限公司 NLP算法工程師)
原文:https://zhuanlan.zhihu.com/p/387271169
轉(zhuǎn)載者:楊夕
面筋地址:https://github.com/km1994/NLP-Interview-Notes
個人筆記:https://github.com/km1994/nlp_paper_study
前言
上一篇博客,討論了語義匹配的語義場景,這篇博文跟大家討論相關(guān)的技術(shù),主要包括BERT-avg、BERT-Whitening、SBERT、SimCES四個。
為了方便,還是從狹義的語義匹配的場景出發(fā),場景目標(biāo)是輸入一對句子,輸出這對句子相似性(回歸,0~1)。

BERT-avg
BERT-avg做法很簡單,直接拿預(yù)訓(xùn)練后的模型來做相似度匹配,因為默認(rèn)經(jīng)過預(yù)訓(xùn)練后的模型含有知識,能夠編碼句子的語義。

注意的是,不經(jīng)過fine-tuning的模型,不能單純把它們拼接起來作為輸入,而是兩個句子要分別輸入BERT模型。具體的,選擇句子的embedding有幾種策略:
取CLS token的的最后一層輸出作為embedding;
取序列最后一層的輸出求平均(通常,做分類的時候求max效果會較好,做語義表征的時候求mean效果較好);
把第一層和最后一層的輸出加起來后做平均(有研究表明頭幾層,主要蘊含詞匯信息,靠任務(wù)的層主要蘊含語義信息,把它們拼接起來,讓兩種信息得到融合)。
得到兩個句子的embedding后,再對embedding求余弦距離作為它們的相似度。
但實質(zhì)上,這種效果并不好。原因在于各向異性。什么叫各向異性?這里引入知乎某答主的回答。

我理解的是輸出的每個token是768維的(即向量空間的基向量由768個768維的向量組成),embedding的數(shù)值大小取決于當(dāng)前選的坐標(biāo)系,假如當(dāng)前坐標(biāo)系非標(biāo)準(zhǔn)正交基,則會出現(xiàn)空間上是正交的向量(空間正交不依賴于坐標(biāo)系,無論你取哪個作為基底,在空間中它們就是正交),但在該坐標(biāo)系下計算出的投影不為0。
BERT-Whitening
論文全稱:《Whitening Sentence Representations for Better Semantics and Faster Retrieval》
項目代碼:github.com/bojone/BERT-
解決各向異性有BERT-flow、BERT-Whitening等方法。其中BERT-Whitening尤為簡單,目標(biāo)就是對語料數(shù)據(jù)求特征值分解,然后把當(dāng)前坐標(biāo)系變換到標(biāo)準(zhǔn)正交基。
特征值分解還有個好處是能降維,大家想想PCA的原理,假如目前是768維的向量空間,經(jīng)過正交標(biāo)準(zhǔn)變換后,有一些方向的特征值是很小的,可以把這些維度拋棄,達(dá)到節(jié)約存儲空間,提高計算效率的目的。

上圖為BERT-Whitening的實現(xiàn)步驟,首先把當(dāng)前任務(wù)的語料,一句句地輸入到預(yù)訓(xùn)練模型中得到各自的embedding,然后對embeddings做特征值分解,得到變換矩陣,存起來。應(yīng)用時,把新的句子輸入預(yù)訓(xùn)練模型,得到句子embedding,再用存起來的變換矩陣u和W做坐標(biāo)變換,這時候變換后的embedding就是標(biāo)準(zhǔn)正交基表示的embedding。
SBERT
論文全稱:《Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks》
項目代碼:github.com/UKPLab/sente

SBERT是近年工業(yè)上應(yīng)用很廣泛的方法,思想很簡單,就是如上圖左邊的雙塔模型,有的地方稱為Siamese network(孿生網(wǎng)絡(luò))和Bi-Encoder。
有的朋友會疑問,這幾年句子相似度的算法競賽,發(fā)現(xiàn)都沒見到這種雙塔模型的身影,常常是上圖右邊這種Cross-Encoder的結(jié)構(gòu)。原因是,雙塔模型相對Cross-Encoder結(jié)構(gòu)效是稍差的,但落到工業(yè)應(yīng)用上,它的優(yōu)點就是快很多!
回想上一篇博客檢索式機(jī)器人的場景,假設(shè)現(xiàn)在知識庫中有500個候選問題,現(xiàn)在傳來一個用戶的問題,Cross-Encoder結(jié)構(gòu)要把用戶問題和500個候選問題,分別拼接后輸入模型,相當(dāng)于要做500次前向計算。而雙塔模型則只需要把500個候選問題的embeddings提前算好存儲起來,當(dāng)有新問題時,只需要算這個問題的embedding,然后用新問題的embedding與500個embeddings做矩陣計算就OK了,相當(dāng)于只進(jìn)行了一次前向計算!所以檢索的一種方法是,首先用SBERT做檢索,然后用Cross-Encoder做精排。
論文中的一些一些細(xì)節(jié):
預(yù)測時,SBERT是對BERT的輸出做pooling來得到固定維度的句子embedding。作者實驗了三種做法:包括使用CLS token的embedding、求句子序列的輸出求mean、對句子序列的輸出求max。實驗發(fā)現(xiàn),mean效果是最好的。
訓(xùn)練的損失函數(shù)

Classification Objective Function:如上圖的左邊,當(dāng)訓(xùn)練集是分類數(shù)據(jù)集時,采用優(yōu)化交叉熵?fù)p失。值得注意的是,這里的concatenation可以采用多種方式,如(u,v)、(|u-v|)及圖中的(u, v, |u-v|)等等,論文實驗證明,|u-v|是影響最大的因子。強(qiáng)調(diào)一下,concatenation只有在訓(xùn)練采用交叉熵?fù)p失才考慮,預(yù)測時,用的只有u和v。
Regression Objective Function:如上圖右邊,采用平方損失。
Triplet Objective Function:三元組損失,當(dāng)訓(xùn)練的數(shù)據(jù)集是如NLI這種三元組數(shù)據(jù)集時(即包含原句、與原句語義相同的句子、與原句矛盾的句子組成一個三元組),就可以采用這種目標(biāo)函數(shù),損失計算如下

使用哪種損失函數(shù)依據(jù)手頭數(shù)據(jù)集的形式,但無論采用哪種方式進(jìn)行訓(xùn)練,預(yù)測時,用的都是兩個句子分別輸入encoder,得到輸出后求pooling得到u和v,再求余弦相似度從而得到句子對的相似度。
SBERT-Semantic Textual Similarity庫
庫地址:sbert.net/examples/trai
該庫發(fā)布了用不同數(shù)據(jù)訓(xùn)練的SBERT模型可供直接調(diào)用(不過沒看到中文的,只看到個多語言的),也封裝了用你自己數(shù)據(jù)訓(xùn)練SBERT模型、Cross-Encoder模型的代碼,以及訓(xùn)練完后如何調(diào)用的API。
庫里還列舉了SBERT的使用場景,如下圖,包括計算句子的embedding、計算語義相似度、語義搜索、檢索重排、聚類等等應(yīng)用,每個應(yīng)用都有示例代碼。

總而言之,這個庫對工業(yè)應(yīng)用十分友好,建議做工程的同學(xué)充分掌握,業(yè)務(wù)上就能快速實現(xiàn)閉環(huán)。
SimCSE
論文全稱:《SimCSE: Simple Contrastive Learning of Sentence Embeddings》
項目代碼:github.com/princeton-nl
上面提到的BERT-avg和BERT-whitening都是無監(jiān)督的方法,SBERT是有監(jiān)督的方法,這里提到的SimCSE有無監(jiān)督和有監(jiān)督兩種模式,其中的無監(jiān)督模式是當(dāng)前無監(jiān)督的SOTA方法。
SimCSE的核心思想是當(dāng)前較火的對比學(xué)習(xí),對比學(xué)習(xí)的目標(biāo)是使語義相近的句子在向量空間中臨近,語義不同的互相遠(yuǎn)離。
具體的過程如下圖所示。


有監(jiān)督學(xué)習(xí):如上圖右,不同于無監(jiān)督學(xué)習(xí)通過dropout制作語義相同的句子對,論文中的有監(jiān)督學(xué)習(xí)用的是NLI數(shù)據(jù)集,NLI數(shù)據(jù)集,針對推理前提(primise)與推理假設(shè)(hypothesis)之間是否存在邏輯關(guān)系,人工標(biāo)注了三種標(biāo)簽entailment蘊含、contradiction矛盾、neutral中立,如下圖為一些示例展示

本來NLI的任務(wù)是輸入一個句子對,輸出它們的label是【entailment、contradiction、neutral】中的一個。SimCSE里作了點小改動,label為entailment的句子對作為語義相近的樣本,目標(biāo)拉近它們的余弦距離,而label為contradiction的句子對則作為語義不同的句子,要拉遠(yuǎn)它們的距離。損失函數(shù)如下

這里再介紹一下論文里重要的一些細(xì)節(jié):
dropout效果是最好的:無監(jiān)督訓(xùn)練時,除了用dropout生成語義相同的句子對,論文里還采用過如:
Crop:隨機(jī)刪掉一段span
Word deletion:隨機(jī)刪除詞
MLM:用BERT預(yù)訓(xùn)練任務(wù)之一,用一些隨機(jī)token或【MASK】token代替原序列的某些token
等等,最后發(fā)現(xiàn)dropout效果是最好的,而且最容易實現(xiàn)。
解決各向異性:論文里一章數(shù)據(jù)證明了對比學(xué)習(xí)的目標(biāo)能有效平滑(論文里叫flatten)句子embedding矩陣的特征值分布。
從線性代數(shù)的角度講,特征值分布不均勻,代表這個矩陣所表示的線性變換在某些方向上變化大,某些方向上變化小,導(dǎo)致各向異性,而平滑特征值可以使得這個線性變換在各個方向的變化均勻化,有效減緩各向異性。
Pooling策略:以往的經(jīng)驗,編碼句子embedding時最好用最后一層的輸出求平均,或第一層加最后一層的輸出求平均,但論文里發(fā)現(xiàn),用CLS token最后一層輸出加全連接層后的輸出作為embedding效果差不多,所以論文里采用這種CLS,畢竟較為簡單;
uniformity and alignment:
alignment表示對齊,則語義相同的句子在句子embedding的向量空間中方向相同
uniformity即均勻性,表示不同句子在句子embedding的向量空間中應(yīng)該盡可能分布均勻。
從下圖可以看出,訓(xùn)練完的SimCSE無論是uniformity和alignment都表現(xiàn)不俗,像BERT-flow、BERT-whitening能提高uniformity,但alignment的表現(xiàn)卻很差。

總結(jié)
四種方法中,SBERT和SimCSE的效果應(yīng)該是最好的,而且實現(xiàn)都十分簡單,能快速應(yīng)用到業(yè)務(wù)中,下一篇博文會用實驗更加嚴(yán)謹(jǐn)對比不同方法的效果。
參考資料
Whitening Sentence Representations for Better Semantics and Faster Retrieval
Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks
SimCSE: Simple Contrastive Learning of Sentence Embeddings
張俊林:對比學(xué)習(xí)(Contrastive Learning):研究進(jìn)展精要

