對比學習/度量學習
對比學習和度量學習從定義上看沒有本質的差別。
最近發現票圈被陳丹奇的simCSE刷屏了,讓筆者也深刻的認識到,現如今文本表示領域研究已經是對比學習的天下了。筆者在本文中將從對比學習的定義,損失函數以及CV和NLP領域的相關文章逐步解析對比學習。
- 文本表示是什么?就是一個文本x用z進行表示,通過z能夠反找到x。
對比學習的思想最早源於cv領域的研究。
對比學習是自監督學習的一種,也就是說,不依賴標注數據,要從無標注圖像中自己學習知識。我們知道,自監督學習其實在圖像領域里已經被探索了很久了。總體而言,圖像領域里的自監督可以分為兩種類型:生成式自監督學習,判別式自監督學習。VAE和GAN是生成式自監督學習的兩類典型方法,即它要求模型重建圖像或者圖像的一部分,這類型的任務難度相對比較高,要求像素級的重構,中間的圖像編碼必須包含很多細節信息。對比學習則是典型的判別式自監督學習,相對生成式自監督學習,對比學習的任務難度要低一些。目前,對比學習貌似處於“無明確定義、有指導原則”的狀態,它的指導原則是:“通過自動構造相似實例和不相似實例,要求習得一個表示學習模型,通過這個模型,使得相似的實例在投影空間中比較接近,而不相似的實例在投影空間中距離比較遠”。而如何構造相似實例,以及不相似實例,如何構造能夠遵循上述指導原則的表示學習模型結構,以及如何防止模型坍塌(Model Collapse),這幾個點是其中的關鍵。
目前出現的對比學習方法已有很多,如果從防止模型坍塌的不同方法角度,我們可大致把現有方法划分為:基於負例的對比學習方法、基於對比聚類的方法、基於不對稱網絡結構的方法,以及基於冗余消除損失函數的方法。張俊林
模型坍塌:全部都收斂到一個常數值,全都變成一個表示。
對比學習的定義
再給出明確定義之前,先舉個有趣的例子:
我們大多數人能分辨出很多真假幣,但如果要我們畫一張百元大鈔出來,我相信基本上畫得一點都不像。這表明,對於真假幣識別這個任務,可以設想我們有了一堆真假幣供學習,我們能從中提取很豐富的特征,但是這些特征並不足以重構原圖,它只能讓我們分辨出這堆紙幣的差異。也就是說,對於數據集和任務來說,合理的、充分的特征並不一定能完成圖像重構。蘇劍林
定義:對比學習是較為典型的無監督or自監督學習,其常見的主要思想是模型能夠更加重新的學習到編碼器的特征:盡可能的縮小相似樣本的距離,拉大正負樣本的距離,這里可以理解為讓聚類的界限更加明顯。即:
d表示歐式距離,s這里表示向量的內積,也就是余弦相似度。后文給出詳細的解釋。
給定一個錨點縮小與正樣本間的距離,擴大與負樣本間的距離,使正樣本與錨點的距離遠遠小於負樣本與錨點的距離,(或使正樣本與錨點的相似度遠遠大於負樣本與錨點的相似度),從而達到他們間原有空間分布的真實距離。
距離度量:歐幾里得距離,余弦相似度,馬氏距離,明氏距離等,自行選擇
這里講的錨點:其實就是一個參照點。
對比學習的損失函數
互信息
在預測未來信息時,我們將目標x(預測)和上下文c(已知)編碼成一個緊湊的分布式向量表示(通過非線性學習映射),其方式最大限度地保留了定義為的原始信號x和c的互信息。公式定義如下:
通過最大化編碼之間互信息(它以輸入信號之間的MI為界),提取輸入中的隱變量。
互信息往往是算不出來的,但是我們這里將他進行估計,通過不同方法進行估計,從而衍生出自監督的兩種方式:生成式和對比式。
互信息上界估計:減少互信息,即VAE的目標。
互信息下界估計:增加互信息,即對比學習(CL)的目標。后來也有CLUB上界估計和下界估計一起使用的對比學習。
互信息就是在知道c的條件下,x的信息減少量,在對比損失的場景下,我們希望互信息越大越好。詳細可以參考【這篇知乎】
infoNCE loss
如果對最大化互信息的目標進行推導無監督特征提取,就會得到對比學習的loss(也稱InfoNCE),其核心是通過計算樣本表示間的距離,拉近正樣本,拉遠負樣本。也就是說,當我們能夠區分該樣本的正負例時,得到的表示就夠用了。
在對比學習的場景下,我們希望選定的錨點與其相似的樣本的內積盡可能的小,與其相反的樣本的內積越大越好(內積度量兩個樣本的相似性),
infoNCE是在Representation Learning with Contrastive Predictive Coding這篇文章提出的。定義的公式如下:
怎么理解這個損失函數?假設樣本中只有一個正例,其余都是負例,此時這個公式不就是一個softmax~本質上變成了一個多分類的問題。依靠NCE來計算損失函數(和學習詞嵌入方式類似),從而可以對整個模型進行端到端的訓練。另外對於多模態的數據有可以學到高級信息。CPC這篇文章主要是在語音序列進行的實驗,增加了噪聲樣本作為數據增強的正例。
詳細內容可以直接看paper,這篇文章對筆者來說有點難搞,后面會再看看~
- 論文標題:Representation Learning with Contrastive Predictive Coding
- 論文鏈接:arxiv.org/abs/1807.0374
- 代碼鏈接:github.com/davidtellez/
對比學習研究進展cv篇
MoCo
- 論文標題:Momentum Contrast for Unsupervised Visual Representation Learning
- 論文鏈接:arxiv.org/abs/1911.0572
- 代碼鏈接:github.com/facebookrese
MoCo系列是何凱明大神提出的,受NLP任務的啟發,MoCo將圖片數據分別編碼成查詢向量和鍵向量,即,查詢 q 與鍵隊列k ,隊列包含單個正樣本和多個負樣本。通過對比損失來學習特征表示。
主線依舊是不變的:在訓練過程中盡量提高每個查詢向量與自己相對應的鍵向量的相似度,同時降低與其他圖片的鍵向量的相似度。
MoCo使用兩個神經網絡對數據進行編碼:encoder和momentum encoder。
- encoder負責編碼當前實例的抽象表示。
- momentum encoder負責編碼多個實例(包括當前實例)的抽象表示。
對於當前實例,最大化其encoder與momentum encoder中自身的編碼結果,同時最小化與momentum encoder中其他實例的編碼結果。 - Memory Bank
MoCo保留了Memory Bank,同時也對此進行了改進,因為其存在一個重要的問題“新舊候選樣本編碼不一致的問題”。
由於對比學習的特性,參與對比學習損失的實例數往往越多越好,但Memory Bank中存儲的都是 encoder 編碼的特征,容量很大,導致采樣的特征具有不一致性(是由不同的encoder產生的)。所以,對所有參與過momentum encoder的實例建立動態字典(dynamic dictionary)作為Memory Bank,在之后訓練過程中每一個batch會淘汰掉字典中最早被編碼的數據。
- Momentum 更新
在參數更新階段,MOCO在設計的時候只會對encoder中的參數進行更新。大多數對比學習的idea都是只對encoder中的參數進行更新。
由於Memory Bank,導致引入大量實例的同時,會使反向傳播十分困難,而momentum encoder參數更新就依賴於Momentum 更新法,使momentum encoder的參數逐步向encoder參數逼近:
這樣每次入隊的新編碼都是上一步更新后的編碼器輸出,以很低的速度慢慢迭代,與舊編碼盡量保持一致。實驗發現,theta=0.999時比theta=0.9好上很多。最終在ImageNet的實驗效果也遠超前人,成為當時的SOTA:
simCLR
- 論文標題:A Simple Framework for Contrastive Learning of Visual Representations
- 論文鏈接:arxiv.org/abs/2002.0570
- 代碼鏈接:github.com/google-resea
這篇是基於負例的對比學習,由hinton的學生提出,實驗效果直接比moco高了7個點。SimCLR不采用memory bank,而是選用了更大的batchsize,以及構造更多的負例。
SimCLR如何構造正例和負例呢?
如何構造對比學習的正負例。對於某張圖片圖片,我們從可能的增強操作集合圖片中,隨機抽取兩種:圖片t1及圖片t2(筆者這里不會用這個編輯器打希臘字母),分別作用在原始圖像上,形成兩張經過增強的新圖像圖片,兩者互為正例。訓練時,Batch內任意其它圖像,都可做為圖片或圖片的負例。
idea非常的簡單:通過數據增強的樣本作為相似樣本,任意的其他樣本作為負例,這里也是后面simCSE主要思想,只不過在文本領域,有獨特的數據增強方法。
這樣,對比學習希望習得某個表示模型,它能夠將圖片映射到某個投影空間,並在這個空間內拉近正例的距離,推遠負例距離。也就是說,迫使表示模型能夠忽略表面因素,學習圖像的內在一致結構信息,即學會某些類型的不變性,比如遮擋不變性、旋轉不變性、顏色不變性等。SimCLR證明了,如果能夠同時融合多種圖像增強操作,增加對比學習模型任務難度,對於對比學習效果有明顯提升作用。
有了正例和負例,接下來需要做的是:構造一個表示學習系統,通過它將訓練數據投影到某個表示空間內,並采取一定的方法,使得正例距離能夠比較近,負例距離比較遠。在這個對比學習的指導原則下,我們來看SimCLR是如何構造表示學習系統的。AINLP
SimCLR模型的整體結構。它由對稱的上下兩個分枝(Branch)構成,是一種典型的雙塔模型。不過圖像領域不這么叫,一般叫Branch。隨機從無標訓練數據中取n個構成一個batch,對於每個batch里的任意圖像,根據數據增強的方法構造正例,形成兩個圖像增強視圖:aug1和aug2。aug1 和aug2各自包含n個增強數據,並分別經過上下兩個分枝,對增強圖像做非線性變換,這兩個分枝就是SimCLR設計出的表示學習所需的投影函數,負責將圖像數據投影到某個表示空間。
因為上下分枝是對稱的,所以這里僅用aug1所經過的上分枝來介紹投影過程。aug1首先經過特征編碼器encoder(cv這里一般采用ResNet做為模型結構),經CNN轉換成對應的特征表示圖片。緊隨其后,是另外一個非線性變換結構Projector(由[FC-BN-RELU-FC]兩層MLP構成,這里以圖片函數代表),進一步將特征表示圖片映射成另外一個空間里的向量圖片。這樣,增強圖像經過圖片兩次非線性變換,就將增強圖像投影到了表示空間,下分枝的aug2過程類似。總之simCLR中得出的結論是batchsize越大越好,而且負例越多越好。具體的原理部分筆者不再贅述。詳看paper。
SimCLR的batch-size也達到了8192,用了128塊TPU,又是算力黨的一大勝利。
MoCov2
SimCLR推出后一個月,何凱明團隊對MoCo進行了一些小改動:
改進了數據增強方法
訓練時在encoder的表示上增加了相同的非線性層
為了對比,學習率采用SimCLR的cosine衰減
而改進后的效果也超過了simCLR.
是不是有種神仙打架的趕腳~有內味了
后續simCLR v2,v3,Moco v3陸續推出,筆者還沒來得及看,將在下一篇ttc中呈現(可以知音樓催更~push筆者)
對比學習研究進展NLP篇
simCSE
論文題目:https://github.com/princeton-nlp/SimCSE
論文地址:https://arxiv.org/pdf/2104.08821.pdf
論文代碼:SimCSE: Simple Contrastive Learning of Sentence Embeddings
同樣也是基於負例的對比學習~simCLR在cv上的騷操作在NLP上發揮的淋漓盡至。
句子向量表示也是nlp領域的一個大熱門,從前段時間的BERT-Flow, BERT-whitening到最近的這個SimCSE。讓筆者終於認識到句向量的重要性。
BERT-Flow以及BERT-whitenning其實像是后處理,將bert的輸出進行一定的處理來解決各向異性的問題。
SIMCSE的這個工作則是采用了自監督來提升模型的句子表示能力,說到自監督最關鍵的問題應該就是如何構建正負例了。simcse的正負例有兩種構建方式,對於無監督來說,作者使用了Droupout來構建正例(其實就是一種數據增強的方法),將一個樣本經過encoder兩次,就得到了一個正例對,負例則是同一個batch里的其它句子。而對於有監督則采用了SNLI數據集天然的結構,對立類別的是負例,另外兩個類別的就是正例。沒錯就是如此簡單的方法催生了新的SOTA,而且提升還非常的明顯,下面就詳細的講一下細節。
SimCSE模型主要分為兩大塊,一個是無監督的部分,一個是有監督的部分。整體結構如下圖所示:
無監督部分
對於無監督的部分,最核心的創新點就是使用droupout來對文本增加噪音,從而構造一個正樣本對,而負樣本對則是在batch中選取的其它句子。和simCLR的idea是何其相似。其實對於圖像任務來說,做數據增強其實非常簡單,有各種的手段。但是對於NLP任務來說,傳統的方法有詞替,裁剪以及回譯,但是作者發現這些方法都沒有簡單的dropout效果好。結果如下:
此外這篇文章提出了uniform和align兩個值是用來衡量向量表示的質量。當然了這並不是這篇論文最早提出的,最早提出這兩個概念的可以追溯到這篇文章:Understanding Contrastive Representation Learning through Alignment and Uniformity on the Hypersphere感興趣的可以讀讀。
alignment計算了句子對距離的期望,而uniformity則用來衡量向量的分布是否一致。從上圖的對比可以看出SimCSE在保證align穩定的同時,能更多的提高uniform。
有監督部分
另外一部分就是有監督的模型了,這一部分的句子對直接采用了NLI數據集的數據,因為其中有天然的正負例句子對。作者也做了試驗選取了效果最好的數據集,結果如下:
從結果可以看出來效果最好的是使用SNLI+MNLI數據集訓練的,而且結果要比無監督的高出不少。其中的hard neg是使用NLI數據集中的contradiction作為負例,所以整體的優化公式也是infoNCE,公式如下:
所以縱觀這篇文章的創新性其實並不強,但是效果絕絕子~~
Anisotropy
在這里作者還對最近提出的文本表示各向異性的現象做出了說明,總體來說就是由於各向異性的存在導致了文本表示能力大打折扣。前面提到的flow和whitening都是采用后處理的方式將數據分布變成各向同性的。而本文則是使用了對比學習來保證正例間的相似以及負例間的疏遠,從而解決了文本表示退化的問題。文中有詳細的公式推導以及證明,感興趣的大家可以自己去看。
實驗效果
在文本相似度上的實驗基本上全部sota
同樣作者也做了下游任務的finetune,此處略,感興趣請自行去看paper
模型測試
筆者這里直接調預訓練模型做了一個小小的測試,感覺效果很不錯的樣子
# Import our models. The package will take care of downloading the models automatically
tokenizer = AutoTokenizer.from_pretrained("princeton-nlp/sup-simcse-bert-base-uncased")
model = AutoModel.from_pretrained("princeton-nlp/sup-simcse-bert-base-uncased")
# Tokenize input texts
texts = [
"馬雲說本周六要來京和高文欣會面",
"馬雲計划周六在北京會見高文欣",
"馬雲周六沒空"
]
inputs = tokenizer(texts, padding=True, truncation=True, return_tensors="pt")
# Get the embeddings
with torch.no_grad():
embeddings = model(**inputs, output_hidden_states=True, return_dict=True).pooler_output
# Calculate cosine similarities
# Cosine similarities are in [-1, 1]. Higher means more similar
cosine_sim_0_1 = 1 - cosine(embeddings[0], embeddings[1])
cosine_sim_0_2 = 1 - cosine(embeddings[0], embeddings[2])
print("Cosine similarity between \"%s\" and \"%s\" is: %.3f" % (texts[0], texts[1], cosine_sim_0_1))
print("Cosine similarity between \"%s\" and \"%s\" is: %.3f" % (texts[0], texts[2], cosine_sim_0_2))
效果
對於對比學習領域,筆者的學習不算全面,也請各位卷友批評指正~
注:表情包圖來源於網絡
其他圖來源於對應的paper
參考文獻
1.https://mp.weixin.qq.com/s/aficf_CWWEWv2D3pCV2R_g
2.https://mp.weixin.qq.com/s/0JXDKJ1veNbNdbrxjibxhQ
3.https://mp.weixin.qq.com/s/f9yRra5RS1QZ4KXOt74PRg
4.https://mp.weixin.qq.com/s/1SAITLGlyVJJigFDzG4eqQ
5.https://ankeshanand.com/blog/2020/01/26/contrative-self-supervised-learning.html
6.https://mp.weixin.qq.com/s/6qqFAQBaOFuXtaeRSmQgsQ