国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí)

這篇具有很好參考價(jià)值的文章主要介紹了【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

無(wú)監(jiān)督對(duì)比學(xué)習(xí):Moco

文章內(nèi)容理解

以下內(nèi)容全部來(lái)自于:自監(jiān)督學(xué)習(xí)-MoCo-論文筆記. 侵刪

論文:Momentum Contrast for Unsupervised Visual Representation Learning

CVPR 2020 最佳論文提名

用動(dòng)量對(duì)比學(xué)習(xí)的方法做無(wú)監(jiān)督的表征學(xué)習(xí)任務(wù)。

動(dòng)量的理解即是指數(shù)移動(dòng)平均(EMA),公式理解:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

moco中利用動(dòng)量來(lái)緩慢的更新編碼器,這樣處理的好處是編碼器學(xué)習(xí)的特征盡可能的保持一致(一致性)。

對(duì)比學(xué)習(xí)

自監(jiān)督學(xué)習(xí)中有一類(lèi)方法主要就是基于對(duì)比學(xué)習(xí)的方法進(jìn)行的,并取得了很好的效果,包括SimCLR和MoCo。由于是自監(jiān)督學(xué)習(xí),目的是想要學(xué)習(xí)到數(shù)據(jù)樣本的好的表征,但是沒(méi)有樣本的標(biāo)簽信息或者其他信息,因此需要設(shè)計(jì)一些代理任務(wù)。一個(gè)比較常用的代理任務(wù)是instance discrimination(個(gè)體判別),它是一個(gè)對(duì)比學(xué)習(xí)的任務(wù),這樣就能夠定義正樣本和負(fù)樣本,然后就可以使用一些對(duì)比損失函數(shù)。

關(guān)于正樣本和負(fù)樣本的定義,方法有很多,不同場(chǎng)景下,可以靈活進(jìn)行處理。

摘要

動(dòng)量對(duì)比學(xué)習(xí)用于無(wú)監(jiān)督表征學(xué)習(xí)。moco從另外一個(gè)角度來(lái)理解對(duì)比學(xué)習(xí),即從一個(gè)字典查詢(xún)的角度來(lái)理解對(duì)比學(xué)習(xí)。moco中建立一個(gè)動(dòng)態(tài)的字典,這個(gè)字典由兩個(gè)部分組成:一個(gè)隊(duì)列和一個(gè)移動(dòng)平均的編碼器。隊(duì)列中的樣本不需要做梯度反傳,因此可以在隊(duì)列中存儲(chǔ)很多負(fù)樣本,從而使這個(gè)字典可以變得很大。使用移動(dòng)平均編碼器的目的是使隊(duì)列中的樣本特征盡可能保持一致(即不同的樣本通過(guò)盡量相似的編碼器獲得特征的編碼表示)。實(shí)驗(yàn)研究發(fā)現(xiàn),一個(gè)更大的字典對(duì)于無(wú)監(jiān)督的對(duì)比學(xué)習(xí)會(huì)有很大的幫助。

moco預(yù)訓(xùn)練好的模型在加上一個(gè)linear protocol(一個(gè)分類(lèi)頭)就能夠在imageNet取得很好的結(jié)果。moco學(xué)習(xí)到的特征能夠很好的遷移到下游任務(wù)?。ㄟ@是moco這篇文章的精髓,因?yàn)闊o(wú)監(jiān)督學(xué)習(xí)的目的就是通過(guò)大規(guī)模無(wú)監(jiān)督預(yù)訓(xùn)練,獲得一個(gè)較好的預(yù)訓(xùn)練模型,然后能夠部署在下游的其他任務(wù)上,這些下游任務(wù)通??赡軟](méi)有那么多有標(biāo)簽數(shù)據(jù)可以用于模型訓(xùn)練)。這樣,有監(jiān)督和無(wú)監(jiān)督之間的鴻溝在很大程度上被填平了。

Introduction

GPT和BERT在NLP中證明了無(wú)監(jiān)督預(yù)訓(xùn)練的成功。視覺(jué)領(lǐng)域中還是有監(jiān)督占據(jù)主導(dǎo)地位。語(yǔ)言模型和視覺(jué)模型這種表現(xiàn)上的差異,原因可能來(lái)自于視覺(jué)和語(yǔ)言模型的原始信號(hào)空間的不同。語(yǔ)言模型任務(wù)中,原始信號(hào)空間是離散的。這些輸入信號(hào)都是一些單詞或者詞根詞綴,能夠相對(duì)容易建立tokenized的字典。(tokenize:把某一個(gè)單詞變成一個(gè)特征)。有了這個(gè)字典,無(wú)監(jiān)督學(xué)習(xí)能夠較容易的基于它展開(kāi),(可以把字典里所有的key(條目)看成一個(gè)類(lèi)別,從而無(wú)監(jiān)督語(yǔ)言模型也能是類(lèi)似有監(jiān)督范式,即有一個(gè)類(lèi)似于標(biāo)簽一樣的東西來(lái)幫助模型進(jìn)行學(xué)習(xí),所以在NLP中,就相對(duì)容易進(jìn)行建模,且模型相對(duì)容易進(jìn)行優(yōu)化)。但是視覺(jué)的原始信號(hào)是在一個(gè)連續(xù)且高維的空間中的,它不像單詞那樣有很強(qiáng)的語(yǔ)義信息(單詞能夠濃縮的很好、很簡(jiǎn)潔)。所以圖像(由于原始信號(hào)連續(xù)且高維)就不適合建立一個(gè)字典,而使無(wú)監(jiān)督學(xué)習(xí)不容易建模,進(jìn)一步導(dǎo)致視覺(jué)中無(wú)監(jiān)督模型打不過(guò)有監(jiān)督模型。

有一些基于對(duì)別學(xué)習(xí)的無(wú)監(jiān)督學(xué)習(xí)取得了不錯(cuò)的效果,雖然這些方法的出發(fā)點(diǎn)、具體做法不太一樣,但可以歸納為(即對(duì)比學(xué)習(xí)可以歸納為)構(gòu)造一個(gè)動(dòng)態(tài)字典。

【對(duì)比學(xué)習(xí)中的一些概念:錨點(diǎn)-anchor-一個(gè)樣本-一個(gè)圖像,正樣本-positive-由錨點(diǎn)通過(guò)transformation得到,負(fù)樣本-negative-其他樣本,然后把這些樣本送到編碼器中得到特征表示,對(duì)比學(xué)習(xí)的目標(biāo)就是在特征空間中,使錨點(diǎn)和正樣本盡可能相近,而和負(fù)樣本之間盡可能遠(yuǎn)離】

【進(jìn)一步,把對(duì)比學(xué)習(xí)中,正樣本和負(fù)樣本都放在一起,理解成一個(gè)字典,每個(gè)樣本就是一個(gè)key,然后一開(kāi)始選中作為錨點(diǎn)anchor的那個(gè)樣本看作query,對(duì)比學(xué)習(xí)就轉(zhuǎn)換成一個(gè)字典查詢(xún)的問(wèn)題,也就是說(shuō)對(duì)比學(xué)習(xí)要訓(xùn)練一些編碼器,然后進(jìn)行字典的查找,查找的目的是讓一個(gè)已經(jīng)編碼好的query盡可能和它匹配的那個(gè)特征(正樣本編碼得到的特征)相似,并和其他的key(負(fù)樣本編碼得到的特征)遠(yuǎn)離,這樣整個(gè)自監(jiān)督學(xué)習(xí)就變成了一個(gè)對(duì)比學(xué)習(xí)的框架,然后使用對(duì)比學(xué)習(xí)的損失函數(shù)】

【moco中把對(duì)比學(xué)習(xí)歸納為一個(gè)字典查找的問(wèn)題,因此論文后面基本上用query來(lái)代替anchor,用字典來(lái)代替正負(fù)樣本】

從動(dòng)態(tài)字典的角度來(lái)看對(duì)比學(xué)習(xí),要想獲得比較好的學(xué)習(xí)效果,字典需要兩個(gè)特性:一個(gè)是字典要盡可能大,另一個(gè)是字典中的樣本表示(key)在訓(xùn)練過(guò)程中要盡可能保持一致?!驹蚍治觯鹤值湓酱?,就能更好的在高維視覺(jué)空間進(jìn)行采樣,字典中的key越多,字典表示的視覺(jué)信息越豐富,然后用query和這些key進(jìn)行對(duì)比學(xué)習(xí)的時(shí)候,才更有可能學(xué)習(xí)到能夠把物體區(qū)分開(kāi)的更本質(zhì)的特征。而如果字典很小,模型有可能會(huì)學(xué)習(xí)到一個(gè)捷徑(short cut solution)。導(dǎo)致預(yù)訓(xùn)練好的模型不能很好的做泛化。關(guān)于一致性,是希望字典中的key是通過(guò)相同或者相似的編碼器得到的樣本特征,這樣在與query進(jìn)行對(duì)比時(shí),才能盡量保證對(duì)比的有效性。反之,如果這些key是經(jīng)過(guò)不同的編碼器得到的,query在進(jìn)行查詢(xún)時(shí),有可能會(huì)找到一個(gè)相同或者相似編碼器產(chǎn)生的那個(gè)key。這就相當(dāng)于變相的引入了一個(gè)捷徑(short cut solution),使得模型學(xué)不好】以有的對(duì)比學(xué)習(xí)方法都被上述兩個(gè)方面中至少一個(gè)方面所限制。

文章提出的moco方法是為了給無(wú)監(jiān)督對(duì)比學(xué)習(xí)構(gòu)造一個(gè)又大又一致的字典。MoCo的整體框架如下圖所示:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

?moco中最大的一個(gè)貢獻(xiàn)就是上圖中的隊(duì)列queue,

【這是在對(duì)比學(xué)習(xí)中第一次使用隊(duì)列這種數(shù)據(jù)結(jié)構(gòu)。隊(duì)列queue主要是用來(lái)存儲(chǔ)前面提到的字典,當(dāng)字典很大時(shí),顯卡的內(nèi)存就不不夠用。因此希望模型每次前向過(guò)程時(shí),字典的大小和batch size 的大小剝離開(kāi)。具體的,這個(gè)隊(duì)列可以很大,但是在每次更新這個(gè)隊(duì)列時(shí),是一點(diǎn)一點(diǎn)進(jìn)行的,即模型訓(xùn)練的每個(gè)前向過(guò)程時(shí),當(dāng)前batch抽取的特征進(jìn)入隊(duì)列,最早的一個(gè)batch的特征出隊(duì)列。因?yàn)殛?duì)列的一個(gè)重要特性就是先入先出。引入隊(duì)列的操作后,就可以把mini-batch的大小和字典(隊(duì)列)的大小分開(kāi)了,所以最后這個(gè)字典(隊(duì)列)的大小可以設(shè)置的很大(論文最大設(shè)置為65536),隊(duì)列中的所有元素并不是每個(gè)iteration都要更新的,這樣只使用一個(gè)普通的GPU就可以訓(xùn)練一個(gè)很好的模型,(因?yàn)閟imclr這種模型會(huì)需要TPU進(jìn)行訓(xùn)練,非常吃設(shè)備)】

moco的另一個(gè)重要的地方就是對(duì)編碼器的動(dòng)量更新?!痉治觯鹤值渲械膋ey最好要保持一致性,即字典中的key最好是通過(guò)同一個(gè)或者相似的編碼器得到的。這個(gè)隊(duì)列queue在更新時(shí),當(dāng)前batch的特征是當(dāng)前編碼器得到的,但是前面batch的特征并不是當(dāng)前這個(gè)編碼器得到的特征,他們是不同時(shí)刻的編碼器得到的特征,這樣就與前面說(shuō)的一致性有了沖突,為了解決這個(gè)問(wèn)題,因此moco中提出使用momentum encoder動(dòng)量編碼器,公式表示:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

在模型的訓(xùn)練過(guò)程中,如過(guò)選用一個(gè)很大的動(dòng)量m,那么這個(gè)動(dòng)量編碼器的更新其實(shí)是非常緩慢的,編碼器??在訓(xùn)練過(guò)程中的更新其實(shí)是很快的,編碼器后文中的實(shí)驗(yàn)也證明了使用較大的動(dòng)量0.999會(huì)取得更好的效果。通過(guò)這個(gè)動(dòng)量編碼器,盡可能的保證了隊(duì)列中不同batch之間抽取特征的一致性】

基于前面的兩點(diǎn)貢獻(xiàn),作者總結(jié)moco通過(guò)構(gòu)建一個(gè)又大又一致的隊(duì)列,基于對(duì)比學(xué)習(xí),能夠去無(wú)監(jiān)督的學(xué)習(xí)較好的視覺(jué)表征。

接下來(lái)是關(guān)于自監(jiān)督學(xué)習(xí)中代理任務(wù)的選擇。moco提供的是一種機(jī)制,它為無(wú)監(jiān)督對(duì)比學(xué)習(xí)提供一個(gè)動(dòng)態(tài)字典,所以還需要考慮選擇什么樣的代理任務(wù)。moco是非常靈活的,他可以和很多代理任務(wù)相結(jié)合。moco論文使用的一個(gè)簡(jiǎn)單的代理任務(wù)instance discrimination,但是效果很好。用預(yù)訓(xùn)練好的模型再結(jié)合一個(gè)線性分類(lèi)器就可以在imageNet上取得和有監(jiān)督相媲美的結(jié)果?!緄nstance discrimination 個(gè)體判別任務(wù),例子:有一個(gè)query和一個(gè)key,是同一個(gè)物體的不同視角不同的隨機(jī)裁剪,這是一個(gè)正樣本對(duì),其他的都是負(fù)樣本】

無(wú)監(jiān)督學(xué)習(xí)最主要的目的是在大量無(wú)標(biāo)注數(shù)據(jù)上,預(yù)訓(xùn)練一個(gè)模型,這個(gè)模型獲得特征能夠直接遷移到下游任務(wù)上。moco在7個(gè)下游任務(wù)上(檢測(cè)、分割等)都取得了很好的結(jié)果,打平甚至超過(guò)有監(jiān)督方式?!緈oco是無(wú)監(jiān)督中第一個(gè)都做到了這么好的結(jié)果】

moco在imageNet上做了實(shí)驗(yàn),該數(shù)據(jù)集有100W樣本量。進(jìn)一步,為了探索無(wú)監(jiān)督的性能上限,moco在Instagram【facebook公司自己的,十億級(jí)規(guī)模數(shù)據(jù)集,更偏向于真實(shí)世界,這個(gè)數(shù)據(jù)集沒(méi)有像imageNet那樣進(jìn)行精心挑選過(guò),每個(gè)圖片只有一個(gè)物品在中間】數(shù)據(jù)集上進(jìn)行了相關(guān)實(shí)驗(yàn),Instagram數(shù)據(jù)集有10億樣本量,并且Instagram上訓(xùn)練的模型有更好的性能。Instagram數(shù)據(jù)集更偏向于真實(shí)世界,存在很多真實(shí)場(chǎng)景中的問(wèn)題,如數(shù)據(jù)分類(lèi)不均衡導(dǎo)致的長(zhǎng)尾問(wèn)題、一張圖片含有多個(gè)物體,Instagram數(shù)據(jù)集圖片的挑選和標(biāo)注都沒(méi)有那么嚴(yán)格。

因此,movo通過(guò)實(shí)驗(yàn),填平了有監(jiān)督和無(wú)監(jiān)督之間的一個(gè)坑,取得了媲美甚至更好的結(jié)果,并且無(wú)監(jiān)督預(yù)訓(xùn)練的模型可能會(huì)取代有監(jiān)督預(yù)訓(xùn)練的模型?!緦W(xué)術(shù)界和工業(yè)界有很多基于imageNet預(yù)訓(xùn)練的模型進(jìn)行擴(kuò)展的工作,所以moco才會(huì)有很大的影響力。】

Related Work

無(wú)監(jiān)督學(xué)習(xí)中,主要有兩個(gè)方面做文章,一個(gè)是代理任務(wù),一個(gè)是目標(biāo)函數(shù)。代理任務(wù)的最終目的是能夠獲得更好的特征表示,目標(biāo)函數(shù)是可以剝離代理任務(wù)進(jìn)行一些設(shè)計(jì),moco主要就是從目標(biāo)函數(shù)上進(jìn)行的設(shè)計(jì)與改進(jìn)。moco中的框架設(shè)計(jì)最終影響的就是InfoNCE這個(gè)目標(biāo)函數(shù)。

目標(biāo)函數(shù),根據(jù)代理任務(wù),設(shè)計(jì)生成式模型(重建整張圖),使用L1或者L2損失函數(shù)等都可以,如果設(shè)計(jì)一個(gè)判別式模型(eight positions,預(yù)測(cè)位置)可以通過(guò)交叉熵等損失函數(shù)的形式。

對(duì)比損失函數(shù):在特征空間中衡量每個(gè)樣本對(duì)之間的相似性,目標(biāo)是讓相似的物體之間的特征拉的比較近,不相似物體之間的特征盡量推開(kāi)。對(duì)比損失函數(shù)與生成式或者判別式損失函數(shù)不同,后者的目標(biāo)是固定的,前者(對(duì)比學(xué)習(xí))的目標(biāo)是在模型訓(xùn)練過(guò)程中不斷改變的。即對(duì)比學(xué)習(xí)中目標(biāo)是編碼器抽取得到的特征(字典)決定的。

對(duì)抗性損失函數(shù),主要衡量的是兩個(gè)概率分布之間的差異,主要用來(lái)做無(wú)監(jiān)督的數(shù)據(jù)生成,也有做特征學(xué)習(xí)的,遷移學(xué)習(xí)中很多方法就是通過(guò)對(duì)抗性損失函數(shù)來(lái)進(jìn)行特征的學(xué)習(xí)。因?yàn)槿绻軌蛏珊芾硐氲膱D像,也就意味著模型學(xué)習(xí)到了數(shù)據(jù)的底層的分布,這樣的模型學(xué)習(xí)到的特征可能也會(huì)很好。

代理任務(wù):重建整張圖,重建圖片的某個(gè)patch,colorization圖片上色,生成偽標(biāo)簽,九宮格,聚類(lèi)等各種各樣的方法。

對(duì)比學(xué)習(xí)VS代理任務(wù):某個(gè)代理任務(wù)可以和某個(gè)對(duì)比損失函數(shù)配對(duì)使用。CPC,預(yù)測(cè)性對(duì)比學(xué)習(xí),利用上下文信息預(yù)測(cè)未來(lái),CMC,利用一個(gè)物體的不同視角進(jìn)行對(duì)比,和圖片上色比較像?!綜PC, CMC是對(duì)比學(xué)習(xí)方法早期的一些經(jīng)典工作。】

【目標(biāo)函數(shù)和代理任務(wù)是無(wú)監(jiān)督學(xué)習(xí)中和有監(jiān)督學(xué)習(xí)任務(wù)中主要不同的地方,有監(jiān)督任務(wù)有標(biāo)簽信息,無(wú)監(jiān)督學(xué)習(xí)沒(méi)有標(biāo)簽,只能通過(guò)代理任務(wù)來(lái)生成自監(jiān)督信號(hào),來(lái)充當(dāng)標(biāo)簽信息】

Method

之前的對(duì)比學(xué)習(xí)的工作基本上都可以總結(jié)為一個(gè)query在字典中進(jìn)行查詢(xún)的任務(wù)。假設(shè)有一個(gè)編碼好的query,以及一些列樣本key,假設(shè)字典中只有一個(gè)key(記做key+)和這個(gè)query是配對(duì)的,即這個(gè)目標(biāo)key和query互為正樣本對(duì)?!纠碚撋?,這里可以使用多個(gè)正樣本對(duì),之后也有一些工作證明了使用多個(gè)正樣本對(duì)有可能提升任務(wù)的性能】。

有了正樣本和負(fù)樣本,就可以使用對(duì)比學(xué)習(xí)的目標(biāo)函數(shù),我們希望這個(gè)目標(biāo)函數(shù)具有下面的性質(zhì):query和唯一正樣本key+相似的時(shí)候,希望這個(gè)目標(biāo)函數(shù)的值比較低,當(dāng)query和其他key不相似的時(shí)候,loss的值也應(yīng)該很小,【因?yàn)閷?duì)比學(xué)習(xí)的目標(biāo)就是拉近query和正樣本key+的距離,同時(shí)拉遠(yuǎn)query和其他樣本的距離,如果能達(dá)到這個(gè)目標(biāo),就說(shuō)明模型訓(xùn)練的差不多了,此時(shí)的目標(biāo)函數(shù)的值就應(yīng)該盡量小,不再繼續(xù)更新模型?!客瑯拥?,當(dāng)query和正樣本key+不相似或者query和負(fù)樣本key相似時(shí),我們希望目標(biāo)函數(shù)的loss值盡量大一些,來(lái)懲罰模型,讓模型繼續(xù)更新參數(shù)。

moco中使用的對(duì)比損失函數(shù)是InfoNCE:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能? ?···········(1)

其中,k表示字典中的樣本數(shù)

對(duì)比損失函數(shù)

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能中括號(hào)里面是softmax函數(shù),把one-hot向量當(dāng)作ground-truth時(shí)的損失函數(shù)中的計(jì)算,加上前面的-log,就是cross entropy 損失函數(shù),這里的K表示數(shù)據(jù)集的類(lèi)別數(shù),在一個(gè)任務(wù)上是固定的數(shù)字。對(duì)比學(xué)習(xí)中理論上是可以使用cross entropy來(lái)當(dāng)作目標(biāo)函數(shù)的,但是在很多代理任務(wù)的具體實(shí)現(xiàn)上是行不通的,比如使用instance discrimination個(gè)體判別代理任務(wù),類(lèi)別數(shù)k就變成了字典中的樣本數(shù),是一個(gè)很大的數(shù)字,softmax在有巨量類(lèi)別時(shí),是工作不了的,同時(shí)exponential指數(shù)操作,在向量維度是幾百萬(wàn)時(shí),計(jì)算復(fù)雜度會(huì)很高,在模型訓(xùn)練時(shí),每個(gè)iteration里面這樣去計(jì)算,會(huì)很耗費(fèi)時(shí)間。基于以上情況,有了NCE loss,noise contrastive estimation,前面說(shuō)因?yàn)轭?lèi)別數(shù)太多,不能進(jìn)行softmax計(jì)算,NCE的思路就是把這么多類(lèi)別問(wèn)題簡(jiǎn)化成一個(gè)二分類(lèi)問(wèn)題,數(shù)據(jù)類(lèi)別data sample和噪聲類(lèi)別 noise sample,然后每次拿數(shù)據(jù)樣本和噪聲樣本做對(duì)比。另外,如果字典的大小是整個(gè)數(shù)據(jù)集,計(jì)算復(fù)雜度還是沒(méi)有降下來(lái),為了解決這個(gè)問(wèn)題,思路就是從整個(gè)數(shù)據(jù)集中選一些負(fù)樣本進(jìn)行l(wèi)oss計(jì)算,來(lái)估計(jì)整個(gè)數(shù)據(jù)集上的loss,即estimation。所以另一個(gè)問(wèn)題就是,負(fù)樣本如果選少了,近似的結(jié)果偏差就大了,所以字典的大小也就成了影響模型性能的一個(gè)因素,即字典越大,提供更好的近似,模型效果會(huì)越好,moco在強(qiáng)調(diào)希望字典能夠足夠大??偨Y(jié)就是NCE把一個(gè)超級(jí)多分類(lèi)問(wèn)題轉(zhuǎn)成一個(gè)二分類(lèi)問(wèn)題,使softmax操作能夠繼續(xù)進(jìn)行。

InfoNCE是對(duì)NCE的一個(gè)簡(jiǎn)單的變體,思路是,如果只看作二分類(lèi)問(wèn)題,只有數(shù)據(jù)樣本和噪聲樣本,對(duì)模型學(xué)習(xí)不是那么友好,因?yàn)樵肼晿颖竞芸赡懿皇且粋€(gè)類(lèi),所以把噪聲樣本看作多個(gè)類(lèi)別會(huì)比較合理,最終NCE就變成了上面的公式(1)InfoNCE。】

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

這個(gè)公式中,q 和 k 是模型的logits輸出,?是一個(gè)溫度參數(shù),?用來(lái)控制分布的形狀,?取值越大,分布越平滑smooth,取值越小,分布越尖銳peak,因此對(duì)比學(xué)習(xí)中對(duì)溫度參數(shù)的設(shè)置會(huì)比較講究,溫度參數(shù)過(guò)大,對(duì)比損失對(duì)所有負(fù)樣本一視同仁,導(dǎo)致模型的學(xué)習(xí)沒(méi)有輕重,溫度參數(shù)國(guó)小,導(dǎo)致模型只關(guān)注特別困難的負(fù)樣本,而這些負(fù)樣本也有可能是潛在的正樣本(比如和query是同一類(lèi)別的樣本等),模型過(guò)多關(guān)注困難的負(fù)樣本,會(huì)導(dǎo)致模型很難收斂,或者模型學(xué)習(xí)的特征泛化性能比較差】

公式分母中,求和是針對(duì)字典中的所有key,即一個(gè)正樣本和所有負(fù)樣本,InfoNCE其實(shí)就是cross entropy loss,它處理的是一個(gè)k+1的分類(lèi)任務(wù),目的是將q分成k+這個(gè)類(lèi)別。moco代碼實(shí)現(xiàn)中,目標(biāo)函數(shù)實(shí)現(xiàn)用的就是cross entropy loss,下文偽代碼中可以看到。

?正負(fù)樣本有了,目標(biāo)函數(shù)有了,下面看輸入和模型。普遍來(lái)講,模型的輸入query就是編碼器得到的,key也是通過(guò)一個(gè)編碼器得到的,具體的x和編碼器則有具體的代理任務(wù)決定,輸入x可以是圖片,圖片的一個(gè)patch或幾個(gè)patch等,query的編碼器和字典的編碼器,可以同一個(gè)編碼器,也可以是不同的編碼器,兩個(gè)編碼器的架構(gòu)可以一樣也可以不一樣,架構(gòu)一樣時(shí),兩個(gè)編碼器參數(shù)可以共享,也可以不共享,還可以部分共享。

Momentum Contrast

通過(guò)前文的分析,對(duì)比學(xué)習(xí)是在連續(xù)高維的信號(hào)空間上,通過(guò)構(gòu)建一個(gè)字典的方式來(lái)進(jìn)行的。字典是一個(gè)動(dòng)態(tài)字典,字典中的key都是隨機(jī)采樣得到的,且獲得key的編碼器在訓(xùn)練中也是在不斷改變的?!居斜O(jiān)督中的target一般是一個(gè)固定的目標(biāo),而無(wú)監(jiān)督中不是,這是兩者最大的區(qū)別?!孔髡哒J(rèn)為,如果想學(xué)習(xí)到好的特征,字典就需要足夠大,并且具有一致性。因?yàn)橐粋€(gè)大的樣本能夠包含很多語(yǔ)義豐富的負(fù)樣本,有助于學(xué)習(xí)到更有判別性的特征。一致性主要是為了模型的訓(xùn)練,避免模型學(xué)習(xí)到trivial solution捷徑解。

隊(duì)列-字典

論文的第一個(gè)貢獻(xiàn)就是如何將一個(gè)字典看成一個(gè)隊(duì)列,用隊(duì)列把一個(gè)字典表示出來(lái)。【隊(duì)列,這種數(shù)據(jù)結(jié)構(gòu)最大的特點(diǎn)就是先進(jìn)先出,F(xiàn)IFO】。整個(gè)隊(duì)列就是一個(gè)字典,每個(gè)元素就是那些key。模型訓(xùn)練過(guò)程中,每一個(gè)batch就會(huì)有新的一批key送進(jìn)來(lái),同時(shí)最老的那批key會(huì)被移出去。用隊(duì)列的好處,就是可以重復(fù)使用那些已經(jīng)編碼好的那些 key(之前mini-batch中得到的)。使用字典之后,就可以把字典的大小和mini-batch的大小完全剝離開(kāi)。這樣就可以在模型訓(xùn)練中使用一個(gè)比較標(biāo)準(zhǔn)的batch size,如128、256,同時(shí)字典的大小可以變得很大,并且可以作為一個(gè)超參數(shù)進(jìn)行調(diào)節(jié)。字典一直都是所有數(shù)據(jù)的一個(gè)子集,(前面NCE進(jìn)行近似loss時(shí)也提到了這個(gè)子集)。另外,維護(hù)隊(duì)列(字典)的計(jì)算開(kāi)銷(xiāo)會(huì)很小,【字典的大小可以設(shè)置幾百到幾萬(wàn),整體訓(xùn)練時(shí)間基本上差不多】。由于使用了隊(duì)列,隊(duì)列先進(jìn)先出的特性,使得每一次移除隊(duì)列的key都是最老的那批,使得字典中的key能夠保持比較好的一致性,有利于對(duì)比學(xué)習(xí)。

動(dòng)量更新

用隊(duì)列的形式,可以讓字典變得很大,但也導(dǎo)致隊(duì)列中之前batch的key不能進(jìn)行梯度回傳,key的編碼器不能通過(guò)反向傳播來(lái)更新參數(shù),【不能讓query的編碼器一直更新,而key的編碼器一直不動(dòng)】,為了解決這個(gè)問(wèn)題,一種想法是每次把更新后的query的編碼器拿給key作為編碼器,但這種方式的結(jié)果并不好,作者認(rèn)為這樣效果不好的原因是,query的編碼器q是快速更新的,直接作為編碼器k,會(huì)導(dǎo)致隊(duì)列中key的一致性降低。進(jìn)一步為了解決這個(gè)問(wèn)題,作者提出使用動(dòng)量更新方式,來(lái)更新編碼器k:

?【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

模型訓(xùn)練更開(kāi)始時(shí),編碼器k用編碼器q進(jìn)行初始化,之后就通過(guò)動(dòng)量更新的方式進(jìn)行更新,當(dāng)動(dòng)量參數(shù)設(shè)置的很大時(shí),編碼器k的更新就會(huì)非常緩慢,這樣即使隊(duì)列中的key是通過(guò)不同的編碼器k得到的,但這些編碼器之間的差異很小,使得隊(duì)列中key的一致性很好,實(shí)驗(yàn)中,動(dòng)量0.999要比動(dòng)量0.9的效果好得多,因此要充分利用好這個(gè)隊(duì)列,就需要設(shè)置一個(gè)較大的動(dòng)量參數(shù)。

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

Relations to previous work

之前的對(duì)比學(xué)習(xí)的方法基本都可以歸納為一個(gè)字典查找的問(wèn)題,到都或多或少受限制于字典的大小或者一致性的問(wèn)題。

之前對(duì)比學(xué)習(xí)的兩種架構(gòu):end-to-end,端到端的學(xué)習(xí)方式,上圖(a)所示,端到端的學(xué)習(xí)方式中,編碼器q和編碼器k都可以通過(guò)梯度回傳的方式進(jìn)行更新,兩個(gè)編碼器可以是不同的網(wǎng)絡(luò),也可以是相同的網(wǎng)絡(luò)。moco中兩個(gè)編碼器是同樣的網(wǎng)絡(luò)架構(gòu)Res50,因?yàn)閝uery和key都是從同一個(gè)batch中獲得的,通過(guò)一次前向傳播就可以獲得所有樣本的特征,并且這些特征是高度一致的。局限性在于字典的大小受限,端到端的方式中,字典的大小和mini-batch的大小是一樣,如果想讓字典很大,batch size 就要很大,目前GPU加載不了這么大的batch size,另外,即使硬件條件達(dá)到,大batch size 的優(yōu)化也是一個(gè)難點(diǎn),處理不得當(dāng),模型會(huì)很難收斂。

【simclr(google)就是端到端的學(xué)習(xí)方式,并且使用了更多的數(shù)據(jù)增強(qiáng)方式,在編碼器之后還有一個(gè)pojector,讓學(xué)習(xí)的特征效果更好,此外還需要TPU,內(nèi)存大,能夠支持更大的batch size 8192,有16382個(gè)負(fù)樣本。】端到端的學(xué)習(xí)方式,優(yōu)點(diǎn)是,由于能夠?qū)崟r(shí)更新編碼器k,字典中的key的一致性會(huì)很好,缺點(diǎn)是batch size很大,內(nèi)存不夠。

另外一個(gè)流派就是memory bank上圖(b),更關(guān)注字典的大小,希望字典很大,以犧牲一定的一致性為代價(jià)。這種方法中只有一個(gè)編碼器q,并能夠通過(guò)梯度回傳進(jìn)行更新,字典的處理,則是把整個(gè)數(shù)據(jù)集的特征都存儲(chǔ),如ImageNet有128萬(wàn)個(gè)特征,每個(gè)特征128維,600M內(nèi)存空間,近鄰查詢(xún)效率也很高,然后每次模型訓(xùn)練時(shí),從memory bank中僅從隨機(jī)采樣key,來(lái)組成字典,memory bank相當(dāng)于線下進(jìn)行的,字典就可以設(shè)置的非常大,但是memory bank的特征一致性就不好,memory bank中的樣本特征,每次訓(xùn)練時(shí)選中作為key的那些樣本特征,會(huì)通過(guò)編碼器q進(jìn)行更新,而編碼器q的更新會(huì)很快,每次更新的特征的差異性會(huì)很大,所以memory bank上特征的一致性會(huì)很差。另外,由于memory上存放了整個(gè)數(shù)據(jù)集的堂本,也就意味著,模型要訓(xùn)練一整個(gè)epoch,memory bank上的特征才能全部更新一次。

moco解決了上面提到的字典大小和特征一致性的問(wèn)題,通過(guò)這個(gè)動(dòng)態(tài)字典和動(dòng)量編碼器。

【moco和memory bank方法更相似,都只有一個(gè)編碼器,都需要額外的內(nèi)存空間存放字典,memory bank中還提出了proximal optimization損失,目的是讓訓(xùn)練變得更加平滑,和moco中的動(dòng)量更新異曲同工。memory bangk動(dòng)量更新的是特征,moco動(dòng)量更新的是編碼器k,moco的擴(kuò)展性很好,可以在億集數(shù)據(jù)集上使用,memory bank方法在數(shù)據(jù)集很大時(shí),還是會(huì)受限于內(nèi)存大小。】

moco簡(jiǎn)單高效,擴(kuò)展性好。

代理任務(wù):為了簡(jiǎn)單起見(jiàn),moco中使用簡(jiǎn)單的個(gè)體判別任務(wù)instance discrimination。

?MoCo的偽代碼風(fēng)格非常簡(jiǎn)潔明了!偽代碼如下:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

moco中默認(rèn)使用的batch size大小是256. 數(shù)據(jù)增強(qiáng)得到正樣本對(duì)。memory bank中query長(zhǎng)度(特征維數(shù))128,為了保持一致,moco也用的128。

Shuffing BN

作者在之后的工作中,如SimSam中并沒(méi)有在繼續(xù)使用shuffing BN操作。使用BN之后,可能會(huì)導(dǎo)致當(dāng)前batch中的樣本信息的泄露?!疽?yàn)锽N要計(jì)算running mean和running variance,模型會(huì)通過(guò)泄露的信息很容易找到正樣本,這樣學(xué)到的可能就不是一個(gè)好的模型,模型會(huì)走一條捷徑trivial solution。解決方法,在模型的訓(xùn)練之前,將樣本的順序打亂,在送到GPU上,提取完特征之后,再恢復(fù)順序,計(jì)算loss。這樣對(duì)最終的loss沒(méi)有影響,但每個(gè)batch上BN的計(jì)算會(huì)被改變,從而避免信息泄露的問(wèn)題?!?/p>

【BN在另一個(gè)自監(jiān)督的重要工作BYOL中,引起了一些烏龍事件,相關(guān)的內(nèi)容可以參考文章BYOL、BYOL work without BN和一個(gè)博客https://generallyintelligent.ai/blog/2020-08-24-understanding-self-supervised-contrastive-learning/,最終BYOL論文作者和博客作者達(dá)成的共識(shí)是,BYOL模型的訓(xùn)練依賴(lài)于一個(gè)比較合理的模型參數(shù)初始化,BN能夠幫助提高模型訓(xùn)練過(guò)程中的穩(wěn)定性。先挖個(gè)坑,之后有機(jī)會(huì)筆者會(huì)對(duì)BYOL系列的一些工作進(jìn)行詳細(xì)的解讀】

【關(guān)于BN,BN使用的好,模型效果能夠有很好的提升,但更多的情況下可能是用不好的,并且不易debug,如果換成transformer,使用LN替代BN】

Experiments

數(shù)據(jù)集:ImageNet-1M,100W數(shù)據(jù)量,Instagram-1B,10億數(shù)據(jù)量。后者是為了驗(yàn)證moco模型擴(kuò)展性好。由于使用個(gè)體判別的代理任務(wù),ImageNet的類(lèi)別量就是數(shù)據(jù)量。另外,Inatagram數(shù)據(jù)集更能反應(yīng)真實(shí)世界的數(shù)據(jù)分布,這個(gè)數(shù)據(jù)集中的樣本不是精心挑選的,有長(zhǎng)尾、不均衡等問(wèn)題,圖片中物體有一個(gè)或多個(gè)。

訓(xùn)練:CNN模型,SGD優(yōu)化器,batch size 256,8GPU,200epoch,ResNet50,53h?!鞠噍^于之后的SimCLR、BYOL等工作,moco對(duì)硬件的要求都是最低的,相對(duì)更容易實(shí)現(xiàn)的,affordable。并且moco、moco-v2系列工作,其泛化性能都很好,做下游任務(wù)時(shí),預(yù)訓(xùn)練學(xué)習(xí)到的特征依舊非常強(qiáng)大。SimCLR的論文引用相對(duì)更高一些,moco的方法更平易近人一些】

Linear classification protocol

預(yù)訓(xùn)練模型加一個(gè)線性分類(lèi)頭,即一個(gè)全連接層。

作者做了一個(gè)grid search,發(fā)現(xiàn)分類(lèi)頭的最佳學(xué)習(xí)率是30,非常不可思議。一般深度學(xué)習(xí)中的工作,很少有l(wèi)earning rate會(huì)超過(guò)1。因此,作者認(rèn)為,這么詭異的學(xué)習(xí)率的原因在于,無(wú)監(jiān)督對(duì)比學(xué)習(xí)學(xué)到的特征分布,和有監(jiān)督學(xué)習(xí)到的特征分布是非常不一樣的。

Ablation:contrastive loss mechanisms

消融實(shí)驗(yàn)。三種對(duì)比學(xué)習(xí)流派之間的比較。實(shí)驗(yàn)結(jié)果如下圖所示:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

?上圖中,橫坐標(biāo)k表示負(fù)樣本的數(shù)量,可以近似理解為字典的大小,縱坐標(biāo)是ImageNet上的top one 準(zhǔn)確率。end-to-end方法,受限于顯卡內(nèi)存,字典大小有限,32G的顯卡內(nèi)存,能用的最大的batch size是1024。memory bank方法整體上比end-to-end和moco效果都要差一些,主要就是因?yàn)樘卦\的不一致性導(dǎo)致的。另外,黑線的走勢(shì)是不知道的,因?yàn)橛布o(wú)法支撐相關(guān)的實(shí)驗(yàn),其后面結(jié)果可能會(huì)更高,也可能會(huì)變差。moco的字典大小,從16384增長(zhǎng)到65536,效果提升已經(jīng)不是很明顯了,所以沒(méi)有更大的字典的比較。上圖結(jié)論:moco性能好、硬件要求低、擴(kuò)展性好。

Ablation:momentum

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

消融實(shí)驗(yàn),動(dòng)量更新。實(shí)驗(yàn)結(jié)果下圖所示:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

動(dòng)量參數(shù)0.99-0.9999,效果會(huì)好一些。?大的動(dòng)量參數(shù),保證了字典中特征的一致性。動(dòng)量參數(shù)為0,即每個(gè)iteration里面,直接把編碼器q拿來(lái)作為編碼器k,導(dǎo)致模型無(wú)法收斂,loss一致在震蕩,最終模型訓(xùn)練失敗。這個(gè)實(shí)驗(yàn)非常有力的證明了字典一致性的重要性。

Comparison with previous results.

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

上面實(shí)驗(yàn)結(jié)果表明:基于對(duì)比學(xué)習(xí)的方法效果更好,模型容量越大效果越好?,moco在小模型和大模型上都能取得好的效果。

Transferring Features

無(wú)監(jiān)督學(xué)習(xí)最主要的目標(biāo)是要學(xué)習(xí)一個(gè)可以遷移的特征,驗(yàn)證moco模型得到的特征在下游任務(wù)上的表現(xiàn),能不能有好的遷移學(xué)習(xí)效果。

另外,由于前面講到,無(wú)監(jiān)督學(xué)習(xí)到的特征分布和有監(jiān)督學(xué)習(xí)到的特征分布是很不一樣的,在將無(wú)監(jiān)督預(yù)訓(xùn)練模型應(yīng)用到下游任務(wù)時(shí),不能每個(gè)任務(wù)的分類(lèi)頭都進(jìn)行參數(shù)搜索,這樣就失去了無(wú)監(jiān)督學(xué)習(xí)的意義,解決方法是:歸一化,然后整個(gè)模型進(jìn)行參數(shù)微調(diào)。BN層用的是synchronized BN,即多卡訓(xùn)練時(shí),把所有卡的信息都進(jìn)行統(tǒng)計(jì),計(jì)算總的running mean 和running variance,然后更新BN層,讓特征歸一化更徹底,模型訓(xùn)練更穩(wěn)定。

Schedules.如果下游任務(wù)數(shù)據(jù)集很大,不在ImageNet上進(jìn)行預(yù)訓(xùn)練,當(dāng)訓(xùn)練時(shí)間足夠長(zhǎng),模型效果依然可以很好,這樣就體現(xiàn)不出moco的優(yōu)越性了。但是下游數(shù)據(jù)集訓(xùn)練時(shí)間很短時(shí),moco中預(yù)訓(xùn)練還是有效果的。所以moco中用的是較短的訓(xùn)練時(shí)間。

PASCAL VOC Object Detection,數(shù)據(jù)集PASCAL VOC,任務(wù):目標(biāo)檢測(cè),實(shí)驗(yàn)結(jié)果如下圖:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

?coco數(shù)據(jù)集,實(shí)驗(yàn)結(jié)果如下圖:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

?其他任務(wù):人體關(guān)鍵點(diǎn)檢測(cè)、姿態(tài)檢測(cè)、實(shí)例分割、語(yǔ)義分割,實(shí)驗(yàn)結(jié)果如下圖:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

?實(shí)驗(yàn)結(jié)果總結(jié):moco在很多任務(wù)上都超過(guò)了ImageNet上有監(jiān)督預(yù)訓(xùn)練的結(jié)果,在少數(shù)幾個(gè)任務(wù)上稍微差一些,主要是實(shí)例分割和語(yǔ)義分割任務(wù),【所以后面有人認(rèn)為,對(duì)比學(xué)習(xí)不適合dence prediction的任務(wù),這種任務(wù)每個(gè)像素點(diǎn)都需要進(jìn)行預(yù)測(cè),之后有一些相關(guān)的工作,如dence contrast,pixel contrast等】。

在所有這些任務(wù)中,在Instagram上預(yù)訓(xùn)練的模型要比ImageNet上的效果好一些,說(shuō)明moco擴(kuò)展性好,與NLP中結(jié)論相似,即自監(jiān)督預(yù)訓(xùn)練數(shù)據(jù)量越多越好,符合無(wú)監(jiān)督學(xué)習(xí)的終極目標(biāo)。

Discussion and Conclusion

從imageNet到Instagram,雖然有效果上的提升,但是很小,而數(shù)據(jù)集是從100W增加到10億,擴(kuò)大了1000倍,所以大規(guī)模數(shù)據(jù)集可能還是沒(méi)有被很好的利用起來(lái),可能更好的代理任務(wù)能夠解決這個(gè)問(wèn)題。

自監(jiān)督中,個(gè)體判別任務(wù),還可以考慮向NLP中mask auto-encoders那樣設(shè)計(jì)代理任務(wù),完成完形填空,何凱明大神之后在2021年有了MAE這個(gè)文章?!綧AE文章在2021年公布,但是思路應(yīng)該至少在moco這篇文章中已經(jīng)有了】

moco設(shè)計(jì)的初衷,是基于對(duì)比學(xué)習(xí),設(shè)計(jì)一個(gè)大且一致的字典,能夠讓正負(fù)樣本更好的進(jìn)行對(duì)比。

總結(jié)

moco雖然是2020年的工作,但最近一兩年自監(jiān)督學(xué)習(xí)相關(guān)的工作刷新是很快的。

自監(jiān)督學(xué)習(xí)第一階段相關(guān)工作:InsDis,CPC,CMC等,百花齊放

第二階段:moco,SimCLR雙雄并立,都是基于對(duì)比學(xué)習(xí)的

第三階段:BYOL,SimSam,不需要對(duì)比學(xué)習(xí),不需要負(fù)樣本

第四階段:moco-v3,DINO等,基于transformer的工作,不再基于ResNet等CNN結(jié)構(gòu)。

參考

MoCo 論文逐段精讀【論文精讀】_嗶哩嗶哩_bilibili文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-832600.html

補(bǔ)充
【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

代碼解釋

類(lèi)定義:

class MoCo(nn.Module):
    """
    Build a MoCo model with: a query encoder, a key encoder, and a queue
    https://arxiv.org/abs/1911.05722
    """

    def __init__(self, base_encoder, dim=128, K=65536, m=0.999, T=0.07, mlp=False):
        """
        dim: feature dimension (default: 128)
        K: queue size; number of negative keys (default: 65536)
        m: moco momentum of updating key encoder (default: 0.999)
        T: softmax temperature (default: 0.07)
        """
        super(MoCo, self).__init__()

        self.K = K
        self.m = m
        self.T = T

        # create the encoders
        # num_classes is the output fc dimension
        self.encoder_q = base_encoder(num_classes=dim)
        self.encoder_k = base_encoder(num_classes=dim)

        if mlp:  # hack: brute-force replacement
            dim_mlp = self.encoder_q.fc.weight.shape[1]
            self.encoder_q.fc = nn.Sequential(
                nn.Linear(dim_mlp, dim_mlp), nn.ReLU(), self.encoder_q.fc
            )
            self.encoder_k.fc = nn.Sequential(
                nn.Linear(dim_mlp, dim_mlp), nn.ReLU(), self.encoder_k.fc
            )

        for param_q, param_k in zip(
            self.encoder_q.parameters(), self.encoder_k.parameters()
        ):
            param_k.data.copy_(param_q.data)  # initialize
            param_k.requires_grad = False  # not update by gradient

        # create the queue
        self.register_buffer("queue", torch.randn(dim, K))
        self.queue = nn.functional.normalize(self.queue, dim=0)

        self.register_buffer("queue_ptr", torch.zeros(1, dtype=torch.long))

動(dòng)量更新key編碼器:

    @torch.no_grad()
    def _momentum_update_key_encoder(self):
        """
        Momentum update of the key encoder
        """
        for param_q, param_k in zip(
            self.encoder_q.parameters(), self.encoder_k.parameters()
        ):
            param_k.data = param_k.data * self.m + param_q.data * (1.0 - self.m)

forward計(jì)算對(duì)比損失 (InfoNCE loss,看成K+1類(lèi)樣本分類(lèi),第一個(gè)位置是正樣本,其余的是負(fù)樣本,使用的是個(gè)體判別任務(wù)):

    def forward(self, im_q, im_k):
        """
        Input:
            im_q: a batch of query images
            im_k: a batch of key images
        Output:
            logits, targets
        """

        # compute query features
        q = self.encoder_q(im_q)  # queries: NxC; C這里為128
        q = nn.functional.normalize(q, dim=1)

        # compute key features
        with torch.no_grad():  # no gradient to keys
            self._momentum_update_key_encoder()  # update the key encoder

            # shuffle for making use of BN
            # im_k, idx_unshuffle = self._batch_shuffle_ddp(im_k)

            k = self.encoder_k(im_k)  # keys: NxC
            k = nn.functional.normalize(k, dim=1)

            # undo shuffle
            # k = self._batch_unshuffle_ddp(k, idx_unshuffle)

        # compute logits
        # Einstein sum is more intuitive
        # positive logits: Nx1
        l_pos = torch.einsum("nc,nc->n", [q, k]).unsqueeze(-1)
        # negative logits: NxK
        l_neg = torch.einsum("nc,ck->nk", [q, self.queue.clone().detach()])

        # logits: Nx(1+K)
        logits = torch.cat([l_pos, l_neg], dim=1)

        # apply temperature
        logits /= self.T

        # labels: positive key indicators
        labels = torch.zeros(logits.shape[0], dtype=torch.long).cuda()

        # dequeue and enqueue
        self._dequeue_and_enqueue(k)

        return logits, labels

T的選取,可以是0.07,0.1,0.5等

有監(jiān)督對(duì)比學(xué)習(xí):Supervised Contrastive Learning

文章內(nèi)容理解

以下內(nèi)容全部來(lái)自于:NIPS20 - 將對(duì)比學(xué)習(xí)用于監(jiān)督學(xué)習(xí)任務(wù)《Supervised Contrastive Learning》

原文地址

原文

論文閱讀方法

三遍論文法

初識(shí)

對(duì)比學(xué)習(xí)這兩年在自監(jiān)督學(xué)習(xí)、無(wú)監(jiān)督學(xué)習(xí)任務(wù)中非?;?,取得了非常優(yōu)秀的性能。這個(gè)工作就是想辦法將其用在監(jiān)督學(xué)習(xí)任務(wù)中,在訓(xùn)練過(guò)程中更有效地利用標(biāo)簽信息。

文章研究的點(diǎn)主要在于對(duì)比學(xué)習(xí)在分類(lèi)任務(wù)中的應(yīng)用

作者首先分析了分類(lèi)任務(wù)中最常采用的交叉熵?fù)p失函數(shù)的缺點(diǎn):① 對(duì)噪聲數(shù)數(shù)據(jù)缺乏魯棒性; ② 分類(lèi)邊界的問(wèn)題(the possibility of poor margins)。這樣會(huì)導(dǎo)致模型泛化能力下降,因此也有不少工作針對(duì)交叉熵進(jìn)行改進(jìn)(比如人臉領(lǐng)域的LargeMargin Loss, ArcFace,以及Label smoothing,知識(shí)蒸餾等),但目前大數(shù)據(jù)集上的分類(lèi)任務(wù)(比如ImageNet),使用最多的仍然是交叉熵。

因此本文就探索了對(duì)比學(xué)習(xí)在ImageNet任務(wù)上的效果,提出了Supervised Contrastive Learning,并驗(yàn)證了其性能優(yōu)越性。如下圖所示,對(duì)比了在ImageNet上的實(shí)驗(yàn)性能。
【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

auto-augmentrand-augment可以參考博客,簡(jiǎn)單理解的話,就是一種自動(dòng)增廣策略,針對(duì)數(shù)據(jù)集找到最有效的增廣策略,提升模型泛化性。

相知

對(duì)比學(xué)習(xí)

對(duì)比學(xué)習(xí)的核心思想就是在特征空間將拉近achor和正樣本,推遠(yuǎn)負(fù)樣本。其目前主要用于無(wú)監(jiān)督表征學(xué)習(xí)中,在這個(gè)任務(wù)中沒(méi)有標(biāo)注信息,所以正常樣本通常是同一個(gè)實(shí)例的兩個(gè)View(同一圖像的兩個(gè)增廣結(jié)果),而負(fù)樣本來(lái)自同一個(gè)batch中的其他樣本。

可以視為在最大化數(shù)據(jù)不同視角下的互信息,這個(gè)思路最先由SimCLR提出,目前已經(jīng)廣泛采用。

而本文的出發(fā)點(diǎn)非常簡(jiǎn)單,既然有了標(biāo)簽信息,那我不就可以準(zhǔn)確地找到anchor對(duì)應(yīng)的正樣本和負(fù)樣本嗎?因此Supervised Contrastive Learning的目標(biāo)就是在特征空間中拉近同一類(lèi)數(shù)據(jù)的特征,推遠(yuǎn)不同類(lèi)之間的特征。

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

訓(xùn)練框架

采用兩階段訓(xùn)練的方法,第一階段非常與SimCLR非常像。首先對(duì)batch內(nèi)的圖像都進(jìn)行兩次增廣,得到兩倍Batch大小(2N)的數(shù)據(jù)。

先送入Encoder網(wǎng)絡(luò)得到2048維的特征輸出,然后再進(jìn)一步經(jīng)過(guò)一個(gè)Project網(wǎng)絡(luò)映射到另一個(gè)空間中(通常維度更小,本文中為128),經(jīng)過(guò)歸一化(normalization映射到超球面)后在這個(gè)特征空間中計(jì)算Supervised Contrastive Learning。

第一階段訓(xùn)練好之后,移除掉Project網(wǎng)絡(luò),固定住Encoder網(wǎng)絡(luò),用交叉熵?fù)p失再訓(xùn)練一個(gè)分類(lèi)head,用于后續(xù)測(cè)試。

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

一些細(xì)節(jié):① 也可以不采用2階段的方式,而是使用交叉熵聯(lián)合訓(xùn)練分類(lèi)head,效果也能差不多。但這里為了更好地體現(xiàn)所提出的監(jiān)督學(xué)習(xí)效果(遷移任務(wù)上),選擇分離訓(xùn)練。② 達(dá)到相同的形象,SupCon需要的學(xué)習(xí)率比交叉熵的要更大。③ 理論上溫度系數(shù)越小越好,但是過(guò)小容易數(shù)值不穩(wěn)定。④ 實(shí)驗(yàn)過(guò)程中嘗試了不同的優(yōu)化器(LARS,RMSProp,SGDm)。

監(jiān)督對(duì)比學(xué)習(xí)形式

自監(jiān)督對(duì)比學(xué)習(xí)的形式如下所示:
【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能
其中I包含了一個(gè)Batch中的所有數(shù)據(jù)(2N),·表示內(nèi)積,其實(shí)在超球面上就可以表示余弦相似度, τ τ τ表示溫度系數(shù),A(i)表示I\{i},1個(gè)anchor對(duì)應(yīng)1個(gè)正樣本和2N-2個(gè)負(fù)樣本。

根據(jù)自監(jiān)督對(duì)比學(xué)習(xí)的定義,引入標(biāo)簽信息后,可以非常容易地對(duì)其進(jìn)行更改。作者首先提出了兩種監(jiān)督對(duì)比學(xué)習(xí)形式:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能
其中,P(i)表示在當(dāng)前batch內(nèi),anchor樣本i所對(duì)應(yīng)的所有正樣本。在形式2中,會(huì)先計(jì)算所有正樣本對(duì)之間的log項(xiàng)再求均值,而形式3會(huì)先計(jì)算求得均值再計(jì)算log項(xiàng)。

首先,無(wú)論是形式2還是形式3,他們都有以下幾個(gè)性質(zhì):

  1. 可以很好地泛化到多個(gè)正樣本對(duì):也就是說(shuō)對(duì)于正樣本的個(gè)數(shù)沒(méi)有限制;
  2. 負(fù)樣本越多,對(duì)比性能越強(qiáng):形式2和形式3在分母的負(fù)樣本求和,這也保留了在原對(duì)比學(xué)習(xí)中的負(fù)樣本越多越好的性質(zhì)(實(shí)際上負(fù)樣本越多,對(duì)比時(shí)就有更多hard negative,效果更好);
  3. 具有困難樣本挖掘能力:不僅僅是正樣本也包含了負(fù)樣本,在損失中hard positive/negative的貢獻(xiàn)遠(yuǎn)大于easy positive/negative(作者在附錄中給了數(shù)學(xué)上的證明)。

但這兩中形式實(shí)際上是不一樣的,根據(jù)杰森不等式能得到如下關(guān)系:
【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

Jensen’s Inequality: 過(guò)一個(gè)下凸函數(shù)上任意兩點(diǎn)所作割線一定在這兩點(diǎn)間的函數(shù)圖象的上方

這或許推測(cè)in形式要優(yōu)于out形式,但結(jié)論卻恰好相反,作者經(jīng)過(guò)實(shí)驗(yàn)表明,out的性能要更優(yōu)。作者在也給出了數(shù)學(xué)上的證明,說(shuō)明in形式更容易達(dá)到次優(yōu)解,因此在之后的實(shí)驗(yàn)中均采用out形式。
【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能
部分實(shí)驗(yàn)
【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能
表2展示了本文提出的supervised contrastive learning要優(yōu)于SimCLR,交叉熵以及Max-Margin,表3展示了其也優(yōu)于其他的數(shù)據(jù)增廣策略。

需要注意的是,訓(xùn)練過(guò)程中的batch size為6144,增廣后就是12288了。
作者也嘗試了MoCo這類(lèi)方法,使用memory bank,memory size為8192,batch size為256,取得了79.1%的top-1準(zhǔn)確率,效果更好(Kaiming yyds)。
但即使使用的是memory bank也需要8塊V100… …

作者也在ImageNet-C數(shù)據(jù)集上進(jìn)行了測(cè)試,其包含一些人造噪聲,效果也很不錯(cuò)。這也說(shuō)明了supervised contrastive learning要更魯棒。
【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能
作者還測(cè)試了損失對(duì)超參數(shù)的穩(wěn)定性以及一些消融實(shí)驗(yàn),如下圖所示,均優(yōu)于交叉熵。
【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

作者還驗(yàn)證了Supervissed Contrastive Learning的模型遷移能力。
【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

回顧

對(duì)比學(xué)習(xí)核心在于“在特征空間拉近anchor與正樣本對(duì)之間的距離,推遠(yuǎn)與負(fù)樣本之間的距離”

往簡(jiǎn)單了說(shuō),對(duì)比學(xué)習(xí)就是一種損失函數(shù)類(lèi)型。往深了說(shuō),就是對(duì)數(shù)據(jù)分布的一種先驗(yàn)假設(shè)。在無(wú)監(jiān)督學(xué)習(xí)任務(wù)中,由于沒(méi)有具體的標(biāo)簽信息,所以在對(duì)比學(xué)習(xí)任務(wù)中采用同一實(shí)例的不同增廣結(jié)果作為正樣本對(duì),其他實(shí)例作為負(fù)樣本。這樣會(huì)受到false negative的影響,比如兩張圖片全是cat這一類(lèi),但你卻要強(qiáng)行推遠(yuǎn)它們?cè)谔卣骺臻g中的距離,這樣會(huì)損害特征的判別性(缺少了捕獲同類(lèi)特征的能力)。

因此本文引入了標(biāo)簽信息,在強(qiáng)監(jiān)督學(xué)習(xí)設(shè)置下進(jìn)行對(duì)比學(xué)習(xí)SupCon。提出了兩種損失形式,并通過(guò)實(shí)驗(yàn)和數(shù)學(xué)上的證明,保留了效果最好最魯棒的一種。

SupCon也保留了對(duì)比學(xué)習(xí)本身的一些特性,其中有一條就是隨著負(fù)樣本的增加,性能會(huì)越來(lái)越好。實(shí)驗(yàn)也證明了在大batch size下性能優(yōu)于普通的交叉熵。但在batch size較小的情況下卻沒(méi)有給出實(shí)驗(yàn)結(jié)果(我覺(jué)得可能不如交叉熵)。如果只有在大batch size的情況下才能彰顯SupCon的優(yōu)越性顯然就限制了它的應(yīng)用場(chǎng)景,畢竟不是誰(shuí)都像G家卡那么多,所以這也意味著還有很大的改進(jìn)空間。

代碼

官方tf代碼鏈接:https://t.ly/supcon,torch代碼鏈接:https://github.com/HobbitLong/SupContrast

論文:Momentum Contrast for Unsupervised Visual Representation Learning

CVPR 2020 最佳論文提名

用動(dòng)量對(duì)比學(xué)習(xí)的方法做無(wú)監(jiān)督的表征學(xué)習(xí)任務(wù)。

動(dòng)量的理解即是指數(shù)移動(dòng)平均(EMA),公式理解:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

moco中利用動(dòng)量來(lái)緩慢的更新編碼器,這樣處理的好處是編碼器學(xué)習(xí)的特征盡可能的保持一致(一致性)。

對(duì)比學(xué)習(xí)

自監(jiān)督學(xué)習(xí)中有一類(lèi)方法主要就是基于對(duì)比學(xué)習(xí)的方法進(jìn)行的,并取得了很好的效果,包括SimCLR和MoCo。由于是自監(jiān)督學(xué)習(xí),目的是想要學(xué)習(xí)到數(shù)據(jù)樣本的好的表征,但是沒(méi)有樣本的標(biāo)簽信息或者其他信息,因此需要設(shè)計(jì)一些代理任務(wù)。一個(gè)比較常用的代理任務(wù)是instance discrimination(個(gè)體判別),它是一個(gè)對(duì)比學(xué)習(xí)的任務(wù),這樣就能夠定義正樣本和負(fù)樣本,然后就可以使用一些對(duì)比損失函數(shù)。

關(guān)于正樣本和負(fù)樣本的定義,方法有很多,不同場(chǎng)景下,可以靈活進(jìn)行處理。

摘要

動(dòng)量對(duì)比學(xué)習(xí)用于無(wú)監(jiān)督表征學(xué)習(xí)。moco從另外一個(gè)角度來(lái)理解對(duì)比學(xué)習(xí),即從一個(gè)字典查詢(xún)的角度來(lái)理解對(duì)比學(xué)習(xí)。moco中建立一個(gè)動(dòng)態(tài)的字典,這個(gè)字典由兩個(gè)部分組成:一個(gè)隊(duì)列和一個(gè)移動(dòng)平均的編碼器。隊(duì)列中的樣本不需要做梯度反傳,因此可以在隊(duì)列中存儲(chǔ)很多負(fù)樣本,從而使這個(gè)字典可以變得很大。使用移動(dòng)平均編碼器的目的是使隊(duì)列中的樣本特征盡可能保持一致(即不同的樣本通過(guò)盡量相似的編碼器獲得特征的編碼表示)。實(shí)驗(yàn)研究發(fā)現(xiàn),一個(gè)更大的字典對(duì)于無(wú)監(jiān)督的對(duì)比學(xué)習(xí)會(huì)有很大的幫助。

moco預(yù)訓(xùn)練好的模型在加上一個(gè)linear protocol(一個(gè)分類(lèi)頭)就能夠在imageNet取得很好的結(jié)果。moco學(xué)習(xí)到的特征能夠很好的遷移到下游任務(wù)?。ㄟ@是moco這篇文章的精髓,因?yàn)闊o(wú)監(jiān)督學(xué)習(xí)的目的就是通過(guò)大規(guī)模無(wú)監(jiān)督預(yù)訓(xùn)練,獲得一個(gè)較好的預(yù)訓(xùn)練模型,然后能夠部署在下游的其他任務(wù)上,這些下游任務(wù)通??赡軟](méi)有那么多有標(biāo)簽數(shù)據(jù)可以用于模型訓(xùn)練)。這樣,有監(jiān)督和無(wú)監(jiān)督之間的鴻溝在很大程度上被填平了。

Introduction

GPT和BERT在NLP中證明了無(wú)監(jiān)督預(yù)訓(xùn)練的成功。視覺(jué)領(lǐng)域中還是有監(jiān)督占據(jù)主導(dǎo)地位。語(yǔ)言模型和視覺(jué)模型這種表現(xiàn)上的差異,原因可能來(lái)自于視覺(jué)和語(yǔ)言模型的原始信號(hào)空間的不同。語(yǔ)言模型任務(wù)中,原始信號(hào)空間是離散的。這些輸入信號(hào)都是一些單詞或者詞根詞綴,能夠相對(duì)容易建立tokenized的字典。(tokenize:把某一個(gè)單詞變成一個(gè)特征)。有了這個(gè)字典,無(wú)監(jiān)督學(xué)習(xí)能夠較容易的基于它展開(kāi),(可以把字典里所有的key(條目)看成一個(gè)類(lèi)別,從而無(wú)監(jiān)督語(yǔ)言模型也能是類(lèi)似有監(jiān)督范式,即有一個(gè)類(lèi)似于標(biāo)簽一樣的東西來(lái)幫助模型進(jìn)行學(xué)習(xí),所以在NLP中,就相對(duì)容易進(jìn)行建模,且模型相對(duì)容易進(jìn)行優(yōu)化)。但是視覺(jué)的原始信號(hào)是在一個(gè)連續(xù)且高維的空間中的,它不像單詞那樣有很強(qiáng)的語(yǔ)義信息(單詞能夠濃縮的很好、很簡(jiǎn)潔)。所以圖像(由于原始信號(hào)連續(xù)且高維)就不適合建立一個(gè)字典,而使無(wú)監(jiān)督學(xué)習(xí)不容易建模,進(jìn)一步導(dǎo)致視覺(jué)中無(wú)監(jiān)督模型打不過(guò)有監(jiān)督模型。

有一些基于對(duì)別學(xué)習(xí)的無(wú)監(jiān)督學(xué)習(xí)取得了不錯(cuò)的效果,雖然這些方法的出發(fā)點(diǎn)、具體做法不太一樣,但可以歸納為(即對(duì)比學(xué)習(xí)可以歸納為)構(gòu)造一個(gè)動(dòng)態(tài)字典。

【對(duì)比學(xué)習(xí)中的一些概念:錨點(diǎn)-anchor-一個(gè)樣本-一個(gè)圖像,正樣本-positive-由錨點(diǎn)通過(guò)transformation得到,負(fù)樣本-negative-其他樣本,然后把這些樣本送到編碼器中得到特征表示,對(duì)比學(xué)習(xí)的目標(biāo)就是在特征空間中,使錨點(diǎn)和正樣本盡可能相近,而和負(fù)樣本之間盡可能遠(yuǎn)離】

【進(jìn)一步,把對(duì)比學(xué)習(xí)中,正樣本和負(fù)樣本都放在一起,理解成一個(gè)字典,每個(gè)樣本就是一個(gè)key,然后一開(kāi)始選中作為錨點(diǎn)anchor的那個(gè)樣本看作query,對(duì)比學(xué)習(xí)就轉(zhuǎn)換成一個(gè)字典查詢(xún)的問(wèn)題,也就是說(shuō)對(duì)比學(xué)習(xí)要訓(xùn)練一些編碼器,然后進(jìn)行字典的查找,查找的目的是讓一個(gè)已經(jīng)編碼好的query盡可能和它匹配的那個(gè)特征(正樣本編碼得到的特征)相似,并和其他的key(負(fù)樣本編碼得到的特征)遠(yuǎn)離,這樣整個(gè)自監(jiān)督學(xué)習(xí)就變成了一個(gè)對(duì)比學(xué)習(xí)的框架,然后使用對(duì)比學(xué)習(xí)的損失函數(shù)】

【moco中把對(duì)比學(xué)習(xí)歸納為一個(gè)字典查找的問(wèn)題,因此論文后面基本上用query來(lái)代替anchor,用字典來(lái)代替正負(fù)樣本】

從動(dòng)態(tài)字典的角度來(lái)看對(duì)比學(xué)習(xí),要想獲得比較好的學(xué)習(xí)效果,字典需要兩個(gè)特性:一個(gè)是字典要盡可能大,另一個(gè)是字典中的樣本表示(key)在訓(xùn)練過(guò)程中要盡可能保持一致?!驹蚍治觯鹤值湓酱?,就能更好的在高維視覺(jué)空間進(jìn)行采樣,字典中的key越多,字典表示的視覺(jué)信息越豐富,然后用query和這些key進(jìn)行對(duì)比學(xué)習(xí)的時(shí)候,才更有可能學(xué)習(xí)到能夠把物體區(qū)分開(kāi)的更本質(zhì)的特征。而如果字典很小,模型有可能會(huì)學(xué)習(xí)到一個(gè)捷徑(short cut solution)。導(dǎo)致預(yù)訓(xùn)練好的模型不能很好的做泛化。關(guān)于一致性,是希望字典中的key是通過(guò)相同或者相似的編碼器得到的樣本特征,這樣在與query進(jìn)行對(duì)比時(shí),才能盡量保證對(duì)比的有效性。反之,如果這些key是經(jīng)過(guò)不同的編碼器得到的,query在進(jìn)行查詢(xún)時(shí),有可能會(huì)找到一個(gè)相同或者相似編碼器產(chǎn)生的那個(gè)key。這就相當(dāng)于變相的引入了一個(gè)捷徑(short cut solution),使得模型學(xué)不好】以有的對(duì)比學(xué)習(xí)方法都被上述兩個(gè)方面中至少一個(gè)方面所限制。

文章提出的moco方法是為了給無(wú)監(jiān)督對(duì)比學(xué)習(xí)構(gòu)造一個(gè)又大又一致的字典。MoCo的整體框架如下圖所示:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

?moco中最大的一個(gè)貢獻(xiàn)就是上圖中的隊(duì)列queue,

【這是在對(duì)比學(xué)習(xí)中第一次使用隊(duì)列這種數(shù)據(jù)結(jié)構(gòu)。隊(duì)列queue主要是用來(lái)存儲(chǔ)前面提到的字典,當(dāng)字典很大時(shí),顯卡的內(nèi)存就不不夠用。因此希望模型每次前向過(guò)程時(shí),字典的大小和batch size 的大小剝離開(kāi)。具體的,這個(gè)隊(duì)列可以很大,但是在每次更新這個(gè)隊(duì)列時(shí),是一點(diǎn)一點(diǎn)進(jìn)行的,即模型訓(xùn)練的每個(gè)前向過(guò)程時(shí),當(dāng)前batch抽取的特征進(jìn)入隊(duì)列,最早的一個(gè)batch的特征出隊(duì)列。因?yàn)殛?duì)列的一個(gè)重要特性就是先入先出。引入隊(duì)列的操作后,就可以把mini-batch的大小和字典(隊(duì)列)的大小分開(kāi)了,所以最后這個(gè)字典(隊(duì)列)的大小可以設(shè)置的很大(論文最大設(shè)置為65536),隊(duì)列中的所有元素并不是每個(gè)iteration都要更新的,這樣只使用一個(gè)普通的GPU就可以訓(xùn)練一個(gè)很好的模型,(因?yàn)閟imclr這種模型會(huì)需要TPU進(jìn)行訓(xùn)練,非常吃設(shè)備)】

moco的另一個(gè)重要的地方就是對(duì)編碼器的動(dòng)量更新?!痉治觯鹤值渲械膋ey最好要保持一致性,即字典中的key最好是通過(guò)同一個(gè)或者相似的編碼器得到的。這個(gè)隊(duì)列queue在更新時(shí),當(dāng)前batch的特征是當(dāng)前編碼器得到的,但是前面batch的特征并不是當(dāng)前這個(gè)編碼器得到的特征,他們是不同時(shí)刻的編碼器得到的特征,這樣就與前面說(shuō)的一致性有了沖突,為了解決這個(gè)問(wèn)題,因此moco中提出使用momentum encoder動(dòng)量編碼器,公式表示:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

在模型的訓(xùn)練過(guò)程中,如過(guò)選用一個(gè)很大的動(dòng)量m,那么這個(gè)動(dòng)量編碼器的更新其實(shí)是非常緩慢的,編碼器??在訓(xùn)練過(guò)程中的更新其實(shí)是很快的,編碼器后文中的實(shí)驗(yàn)也證明了使用較大的動(dòng)量0.999會(huì)取得更好的效果。通過(guò)這個(gè)動(dòng)量編碼器,盡可能的保證了隊(duì)列中不同batch之間抽取特征的一致性】

基于前面的兩點(diǎn)貢獻(xiàn),作者總結(jié)moco通過(guò)構(gòu)建一個(gè)又大又一致的隊(duì)列,基于對(duì)比學(xué)習(xí),能夠去無(wú)監(jiān)督的學(xué)習(xí)較好的視覺(jué)表征。

接下來(lái)是關(guān)于自監(jiān)督學(xué)習(xí)中代理任務(wù)的選擇。moco提供的是一種機(jī)制,它為無(wú)監(jiān)督對(duì)比學(xué)習(xí)提供一個(gè)動(dòng)態(tài)字典,所以還需要考慮選擇什么樣的代理任務(wù)。moco是非常靈活的,他可以和很多代理任務(wù)相結(jié)合。moco論文使用的一個(gè)簡(jiǎn)單的代理任務(wù)instance discrimination,但是效果很好。用預(yù)訓(xùn)練好的模型再結(jié)合一個(gè)線性分類(lèi)器就可以在imageNet上取得和有監(jiān)督相媲美的結(jié)果?!緄nstance discrimination 個(gè)體判別任務(wù),例子:有一個(gè)query和一個(gè)key,是同一個(gè)物體的不同視角不同的隨機(jī)裁剪,這是一個(gè)正樣本對(duì),其他的都是負(fù)樣本】

無(wú)監(jiān)督學(xué)習(xí)最主要的目的是在大量無(wú)標(biāo)注數(shù)據(jù)上,預(yù)訓(xùn)練一個(gè)模型,這個(gè)模型獲得特征能夠直接遷移到下游任務(wù)上。moco在7個(gè)下游任務(wù)上(檢測(cè)、分割等)都取得了很好的結(jié)果,打平甚至超過(guò)有監(jiān)督方式?!緈oco是無(wú)監(jiān)督中第一個(gè)都做到了這么好的結(jié)果】

moco在imageNet上做了實(shí)驗(yàn),該數(shù)據(jù)集有100W樣本量。進(jìn)一步,為了探索無(wú)監(jiān)督的性能上限,moco在Instagram【facebook公司自己的,十億級(jí)規(guī)模數(shù)據(jù)集,更偏向于真實(shí)世界,這個(gè)數(shù)據(jù)集沒(méi)有像imageNet那樣進(jìn)行精心挑選過(guò),每個(gè)圖片只有一個(gè)物品在中間】數(shù)據(jù)集上進(jìn)行了相關(guān)實(shí)驗(yàn),Instagram數(shù)據(jù)集有10億樣本量,并且Instagram上訓(xùn)練的模型有更好的性能。Instagram數(shù)據(jù)集更偏向于真實(shí)世界,存在很多真實(shí)場(chǎng)景中的問(wèn)題,如數(shù)據(jù)分類(lèi)不均衡導(dǎo)致的長(zhǎng)尾問(wèn)題、一張圖片含有多個(gè)物體,Instagram數(shù)據(jù)集圖片的挑選和標(biāo)注都沒(méi)有那么嚴(yán)格。

因此,movo通過(guò)實(shí)驗(yàn),填平了有監(jiān)督和無(wú)監(jiān)督之間的一個(gè)坑,取得了媲美甚至更好的結(jié)果,并且無(wú)監(jiān)督預(yù)訓(xùn)練的模型可能會(huì)取代有監(jiān)督預(yù)訓(xùn)練的模型。【學(xué)術(shù)界和工業(yè)界有很多基于imageNet預(yù)訓(xùn)練的模型進(jìn)行擴(kuò)展的工作,所以moco才會(huì)有很大的影響力?!?/p>

Related Work

無(wú)監(jiān)督學(xué)習(xí)中,主要有兩個(gè)方面做文章,一個(gè)是代理任務(wù),一個(gè)是目標(biāo)函數(shù)。代理任務(wù)的最終目的是能夠獲得更好的特征表示,目標(biāo)函數(shù)是可以剝離代理任務(wù)進(jìn)行一些設(shè)計(jì),moco主要就是從目標(biāo)函數(shù)上進(jìn)行的設(shè)計(jì)與改進(jìn)。moco中的框架設(shè)計(jì)最終影響的就是InfoNCE這個(gè)目標(biāo)函數(shù)。

目標(biāo)函數(shù),根據(jù)代理任務(wù),設(shè)計(jì)生成式模型(重建整張圖),使用L1或者L2損失函數(shù)等都可以,如果設(shè)計(jì)一個(gè)判別式模型(eight positions,預(yù)測(cè)位置)可以通過(guò)交叉熵等損失函數(shù)的形式。

對(duì)比損失函數(shù):在特征空間中衡量每個(gè)樣本對(duì)之間的相似性,目標(biāo)是讓相似的物體之間的特征拉的比較近,不相似物體之間的特征盡量推開(kāi)。對(duì)比損失函數(shù)與生成式或者判別式損失函數(shù)不同,后者的目標(biāo)是固定的,前者(對(duì)比學(xué)習(xí))的目標(biāo)是在模型訓(xùn)練過(guò)程中不斷改變的。即對(duì)比學(xué)習(xí)中目標(biāo)是編碼器抽取得到的特征(字典)決定的。

對(duì)抗性損失函數(shù),主要衡量的是兩個(gè)概率分布之間的差異,主要用來(lái)做無(wú)監(jiān)督的數(shù)據(jù)生成,也有做特征學(xué)習(xí)的,遷移學(xué)習(xí)中很多方法就是通過(guò)對(duì)抗性損失函數(shù)來(lái)進(jìn)行特征的學(xué)習(xí)。因?yàn)槿绻軌蛏珊芾硐氲膱D像,也就意味著模型學(xué)習(xí)到了數(shù)據(jù)的底層的分布,這樣的模型學(xué)習(xí)到的特征可能也會(huì)很好。

代理任務(wù):重建整張圖,重建圖片的某個(gè)patch,colorization圖片上色,生成偽標(biāo)簽,九宮格,聚類(lèi)等各種各樣的方法。

對(duì)比學(xué)習(xí)VS代理任務(wù):某個(gè)代理任務(wù)可以和某個(gè)對(duì)比損失函數(shù)配對(duì)使用。CPC,預(yù)測(cè)性對(duì)比學(xué)習(xí),利用上下文信息預(yù)測(cè)未來(lái),CMC,利用一個(gè)物體的不同視角進(jìn)行對(duì)比,和圖片上色比較像?!綜PC, CMC是對(duì)比學(xué)習(xí)方法早期的一些經(jīng)典工作。】

【目標(biāo)函數(shù)和代理任務(wù)是無(wú)監(jiān)督學(xué)習(xí)中和有監(jiān)督學(xué)習(xí)任務(wù)中主要不同的地方,有監(jiān)督任務(wù)有標(biāo)簽信息,無(wú)監(jiān)督學(xué)習(xí)沒(méi)有標(biāo)簽,只能通過(guò)代理任務(wù)來(lái)生成自監(jiān)督信號(hào),來(lái)充當(dāng)標(biāo)簽信息】

Method

之前的對(duì)比學(xué)習(xí)的工作基本上都可以總結(jié)為一個(gè)query在字典中進(jìn)行查詢(xún)的任務(wù)。假設(shè)有一個(gè)編碼好的query,以及一些列樣本key,假設(shè)字典中只有一個(gè)key(記做key+)和這個(gè)query是配對(duì)的,即這個(gè)目標(biāo)key和query互為正樣本對(duì)?!纠碚撋?,這里可以使用多個(gè)正樣本對(duì),之后也有一些工作證明了使用多個(gè)正樣本對(duì)有可能提升任務(wù)的性能】。

有了正樣本和負(fù)樣本,就可以使用對(duì)比學(xué)習(xí)的目標(biāo)函數(shù),我們希望這個(gè)目標(biāo)函數(shù)具有下面的性質(zhì):query和唯一正樣本key+相似的時(shí)候,希望這個(gè)目標(biāo)函數(shù)的值比較低,當(dāng)query和其他key不相似的時(shí)候,loss的值也應(yīng)該很小,【因?yàn)閷?duì)比學(xué)習(xí)的目標(biāo)就是拉近query和正樣本key+的距離,同時(shí)拉遠(yuǎn)query和其他樣本的距離,如果能達(dá)到這個(gè)目標(biāo),就說(shuō)明模型訓(xùn)練的差不多了,此時(shí)的目標(biāo)函數(shù)的值就應(yīng)該盡量小,不再繼續(xù)更新模型?!客瑯拥模?dāng)query和正樣本key+不相似或者query和負(fù)樣本key相似時(shí),我們希望目標(biāo)函數(shù)的loss值盡量大一些,來(lái)懲罰模型,讓模型繼續(xù)更新參數(shù)。

moco中使用的對(duì)比損失函數(shù)是InfoNCE:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能? ?···········(1)

其中,k表示字典中的樣本數(shù)

對(duì)比損失函數(shù)

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能,中括號(hào)里面是softmax函數(shù),把one-hot向量當(dāng)作ground-truth時(shí)的損失函數(shù)中的計(jì)算,加上前面的-log,就是cross entropy 損失函數(shù),這里的K表示數(shù)據(jù)集的類(lèi)別數(shù),在一個(gè)任務(wù)上是固定的數(shù)字。對(duì)比學(xué)習(xí)中理論上是可以使用cross entropy來(lái)當(dāng)作目標(biāo)函數(shù)的,但是在很多代理任務(wù)的具體實(shí)現(xiàn)上是行不通的,比如使用instance discrimination個(gè)體判別代理任務(wù),類(lèi)別數(shù)k就變成了字典中的樣本數(shù),是一個(gè)很大的數(shù)字,softmax在有巨量類(lèi)別時(shí),是工作不了的,同時(shí)exponential指數(shù)操作,在向量維度是幾百萬(wàn)時(shí),計(jì)算復(fù)雜度會(huì)很高,在模型訓(xùn)練時(shí),每個(gè)iteration里面這樣去計(jì)算,會(huì)很耗費(fèi)時(shí)間?;谝陨锨闆r,有了NCE loss,noise contrastive estimation,前面說(shuō)因?yàn)轭?lèi)別數(shù)太多,不能進(jìn)行softmax計(jì)算,NCE的思路就是把這么多類(lèi)別問(wèn)題簡(jiǎn)化成一個(gè)二分類(lèi)問(wèn)題,數(shù)據(jù)類(lèi)別data sample和噪聲類(lèi)別 noise sample,然后每次拿數(shù)據(jù)樣本和噪聲樣本做對(duì)比。另外,如果字典的大小是整個(gè)數(shù)據(jù)集,計(jì)算復(fù)雜度還是沒(méi)有降下來(lái),為了解決這個(gè)問(wèn)題,思路就是從整個(gè)數(shù)據(jù)集中選一些負(fù)樣本進(jìn)行l(wèi)oss計(jì)算,來(lái)估計(jì)整個(gè)數(shù)據(jù)集上的loss,即estimation。所以另一個(gè)問(wèn)題就是,負(fù)樣本如果選少了,近似的結(jié)果偏差就大了,所以字典的大小也就成了影響模型性能的一個(gè)因素,即字典越大,提供更好的近似,模型效果會(huì)越好,moco在強(qiáng)調(diào)希望字典能夠足夠大??偨Y(jié)就是NCE把一個(gè)超級(jí)多分類(lèi)問(wèn)題轉(zhuǎn)成一個(gè)二分類(lèi)問(wèn)題,使softmax操作能夠繼續(xù)進(jìn)行。

InfoNCE是對(duì)NCE的一個(gè)簡(jiǎn)單的變體,思路是,如果只看作二分類(lèi)問(wèn)題,只有數(shù)據(jù)樣本和噪聲樣本,對(duì)模型學(xué)習(xí)不是那么友好,因?yàn)樵肼晿颖竞芸赡懿皇且粋€(gè)類(lèi),所以把噪聲樣本看作多個(gè)類(lèi)別會(huì)比較合理,最終NCE就變成了上面的公式(1)InfoNCE。】

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

這個(gè)公式中,q 和 k 是模型的logits輸出,?是一個(gè)溫度參數(shù),?用來(lái)控制分布的形狀,?取值越大,分布越平滑smooth,取值越小,分布越尖銳peak,因此對(duì)比學(xué)習(xí)中對(duì)溫度參數(shù)的設(shè)置會(huì)比較講究,溫度參數(shù)過(guò)大,對(duì)比損失對(duì)所有負(fù)樣本一視同仁,導(dǎo)致模型的學(xué)習(xí)沒(méi)有輕重,溫度參數(shù)國(guó)小,導(dǎo)致模型只關(guān)注特別困難的負(fù)樣本,而這些負(fù)樣本也有可能是潛在的正樣本(比如和query是同一類(lèi)別的樣本等),模型過(guò)多關(guān)注困難的負(fù)樣本,會(huì)導(dǎo)致模型很難收斂,或者模型學(xué)習(xí)的特征泛化性能比較差】

公式分母中,求和是針對(duì)字典中的所有key,即一個(gè)正樣本和所有負(fù)樣本,InfoNCE其實(shí)就是cross entropy loss,它處理的是一個(gè)k+1的分類(lèi)任務(wù),目的是將q分成k+這個(gè)類(lèi)別。moco代碼實(shí)現(xiàn)中,目標(biāo)函數(shù)實(shí)現(xiàn)用的就是cross entropy loss,下文偽代碼中可以看到。

?正負(fù)樣本有了,目標(biāo)函數(shù)有了,下面看輸入和模型。普遍來(lái)講,模型的輸入query就是編碼器得到的,key也是通過(guò)一個(gè)編碼器得到的,具體的x和編碼器則有具體的代理任務(wù)決定,輸入x可以是圖片,圖片的一個(gè)patch或幾個(gè)patch等,query的編碼器和字典的編碼器,可以同一個(gè)編碼器,也可以是不同的編碼器,兩個(gè)編碼器的架構(gòu)可以一樣也可以不一樣,架構(gòu)一樣時(shí),兩個(gè)編碼器參數(shù)可以共享,也可以不共享,還可以部分共享。

Momentum Contrast

通過(guò)前文的分析,對(duì)比學(xué)習(xí)是在連續(xù)高維的信號(hào)空間上,通過(guò)構(gòu)建一個(gè)字典的方式來(lái)進(jìn)行的。字典是一個(gè)動(dòng)態(tài)字典,字典中的key都是隨機(jī)采樣得到的,且獲得key的編碼器在訓(xùn)練中也是在不斷改變的?!居斜O(jiān)督中的target一般是一個(gè)固定的目標(biāo),而無(wú)監(jiān)督中不是,這是兩者最大的區(qū)別。】作者認(rèn)為,如果想學(xué)習(xí)到好的特征,字典就需要足夠大,并且具有一致性。因?yàn)橐粋€(gè)大的樣本能夠包含很多語(yǔ)義豐富的負(fù)樣本,有助于學(xué)習(xí)到更有判別性的特征。一致性主要是為了模型的訓(xùn)練,避免模型學(xué)習(xí)到trivial solution捷徑解。

隊(duì)列-字典

論文的第一個(gè)貢獻(xiàn)就是如何將一個(gè)字典看成一個(gè)隊(duì)列,用隊(duì)列把一個(gè)字典表示出來(lái)。【隊(duì)列,這種數(shù)據(jù)結(jié)構(gòu)最大的特點(diǎn)就是先進(jìn)先出,F(xiàn)IFO】。整個(gè)隊(duì)列就是一個(gè)字典,每個(gè)元素就是那些key。模型訓(xùn)練過(guò)程中,每一個(gè)batch就會(huì)有新的一批key送進(jìn)來(lái),同時(shí)最老的那批key會(huì)被移出去。用隊(duì)列的好處,就是可以重復(fù)使用那些已經(jīng)編碼好的那些 key(之前mini-batch中得到的)。使用字典之后,就可以把字典的大小和mini-batch的大小完全剝離開(kāi)。這樣就可以在模型訓(xùn)練中使用一個(gè)比較標(biāo)準(zhǔn)的batch size,如128、256,同時(shí)字典的大小可以變得很大,并且可以作為一個(gè)超參數(shù)進(jìn)行調(diào)節(jié)。字典一直都是所有數(shù)據(jù)的一個(gè)子集,(前面NCE進(jìn)行近似loss時(shí)也提到了這個(gè)子集)。另外,維護(hù)隊(duì)列(字典)的計(jì)算開(kāi)銷(xiāo)會(huì)很小,【字典的大小可以設(shè)置幾百到幾萬(wàn),整體訓(xùn)練時(shí)間基本上差不多】。由于使用了隊(duì)列,隊(duì)列先進(jìn)先出的特性,使得每一次移除隊(duì)列的key都是最老的那批,使得字典中的key能夠保持比較好的一致性,有利于對(duì)比學(xué)習(xí)。

動(dòng)量更新

用隊(duì)列的形式,可以讓字典變得很大,但也導(dǎo)致隊(duì)列中之前batch的key不能進(jìn)行梯度回傳,key的編碼器不能通過(guò)反向傳播來(lái)更新參數(shù),【不能讓query的編碼器一直更新,而key的編碼器一直不動(dòng)】,為了解決這個(gè)問(wèn)題,一種想法是每次把更新后的query的編碼器拿給key作為編碼器,但這種方式的結(jié)果并不好,作者認(rèn)為這樣效果不好的原因是,query的編碼器q是快速更新的,直接作為編碼器k,會(huì)導(dǎo)致隊(duì)列中key的一致性降低。進(jìn)一步為了解決這個(gè)問(wèn)題,作者提出使用動(dòng)量更新方式,來(lái)更新編碼器k:

?【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

模型訓(xùn)練更開(kāi)始時(shí),編碼器k用編碼器q進(jìn)行初始化,之后就通過(guò)動(dòng)量更新的方式進(jìn)行更新,當(dāng)動(dòng)量參數(shù)設(shè)置的很大時(shí),編碼器k的更新就會(huì)非常緩慢,這樣即使隊(duì)列中的key是通過(guò)不同的編碼器k得到的,但這些編碼器之間的差異很小,使得隊(duì)列中key的一致性很好,實(shí)驗(yàn)中,動(dòng)量0.999要比動(dòng)量0.9的效果好得多,因此要充分利用好這個(gè)隊(duì)列,就需要設(shè)置一個(gè)較大的動(dòng)量參數(shù)。

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

Relations to previous work

之前的對(duì)比學(xué)習(xí)的方法基本都可以歸納為一個(gè)字典查找的問(wèn)題,到都或多或少受限制于字典的大小或者一致性的問(wèn)題。

之前對(duì)比學(xué)習(xí)的兩種架構(gòu):end-to-end,端到端的學(xué)習(xí)方式,上圖(a)所示,端到端的學(xué)習(xí)方式中,編碼器q和編碼器k都可以通過(guò)梯度回傳的方式進(jìn)行更新,兩個(gè)編碼器可以是不同的網(wǎng)絡(luò),也可以是相同的網(wǎng)絡(luò)。moco中兩個(gè)編碼器是同樣的網(wǎng)絡(luò)架構(gòu)Res50,因?yàn)閝uery和key都是從同一個(gè)batch中獲得的,通過(guò)一次前向傳播就可以獲得所有樣本的特征,并且這些特征是高度一致的。局限性在于字典的大小受限,端到端的方式中,字典的大小和mini-batch的大小是一樣,如果想讓字典很大,batch size 就要很大,目前GPU加載不了這么大的batch size,另外,即使硬件條件達(dá)到,大batch size 的優(yōu)化也是一個(gè)難點(diǎn),處理不得當(dāng),模型會(huì)很難收斂。

【simclr(google)就是端到端的學(xué)習(xí)方式,并且使用了更多的數(shù)據(jù)增強(qiáng)方式,在編碼器之后還有一個(gè)pojector,讓學(xué)習(xí)的特征效果更好,此外還需要TPU,內(nèi)存大,能夠支持更大的batch size 8192,有16382個(gè)負(fù)樣本?!慷说蕉说膶W(xué)習(xí)方式,優(yōu)點(diǎn)是,由于能夠?qū)崟r(shí)更新編碼器k,字典中的key的一致性會(huì)很好,缺點(diǎn)是batch size很大,內(nèi)存不夠。

另外一個(gè)流派就是memory bank上圖(b),更關(guān)注字典的大小,希望字典很大,以犧牲一定的一致性為代價(jià)。這種方法中只有一個(gè)編碼器q,并能夠通過(guò)梯度回傳進(jìn)行更新,字典的處理,則是把整個(gè)數(shù)據(jù)集的特征都存儲(chǔ),如ImageNet有128萬(wàn)個(gè)特征,每個(gè)特征128維,600M內(nèi)存空間,近鄰查詢(xún)效率也很高,然后每次模型訓(xùn)練時(shí),從memory bank中僅從隨機(jī)采樣key,來(lái)組成字典,memory bank相當(dāng)于線下進(jìn)行的,字典就可以設(shè)置的非常大,但是memory bank的特征一致性就不好,memory bank中的樣本特征,每次訓(xùn)練時(shí)選中作為key的那些樣本特征,會(huì)通過(guò)編碼器q進(jìn)行更新,而編碼器q的更新會(huì)很快,每次更新的特征的差異性會(huì)很大,所以memory bank上特征的一致性會(huì)很差。另外,由于memory上存放了整個(gè)數(shù)據(jù)集的堂本,也就意味著,模型要訓(xùn)練一整個(gè)epoch,memory bank上的特征才能全部更新一次。

moco解決了上面提到的字典大小和特征一致性的問(wèn)題,通過(guò)這個(gè)動(dòng)態(tài)字典和動(dòng)量編碼器。

【moco和memory bank方法更相似,都只有一個(gè)編碼器,都需要額外的內(nèi)存空間存放字典,memory bank中還提出了proximal optimization損失,目的是讓訓(xùn)練變得更加平滑,和moco中的動(dòng)量更新異曲同工。memory bangk動(dòng)量更新的是特征,moco動(dòng)量更新的是編碼器k,moco的擴(kuò)展性很好,可以在億集數(shù)據(jù)集上使用,memory bank方法在數(shù)據(jù)集很大時(shí),還是會(huì)受限于內(nèi)存大小?!?/p>

moco簡(jiǎn)單高效,擴(kuò)展性好。

代理任務(wù):為了簡(jiǎn)單起見(jiàn),moco中使用簡(jiǎn)單的個(gè)體判別任務(wù)instance discrimination。

?MoCo的偽代碼風(fēng)格非常簡(jiǎn)潔明了!偽代碼如下:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

moco中默認(rèn)使用的batch size大小是256. 數(shù)據(jù)增強(qiáng)得到正樣本對(duì)。memory bank中query長(zhǎng)度(特征維數(shù))128,為了保持一致,moco也用的128。

Shuffing BN

作者在之后的工作中,如SimSam中并沒(méi)有在繼續(xù)使用shuffing BN操作。使用BN之后,可能會(huì)導(dǎo)致當(dāng)前batch中的樣本信息的泄露?!疽?yàn)锽N要計(jì)算running mean和running variance,模型會(huì)通過(guò)泄露的信息很容易找到正樣本,這樣學(xué)到的可能就不是一個(gè)好的模型,模型會(huì)走一條捷徑trivial solution。解決方法,在模型的訓(xùn)練之前,將樣本的順序打亂,在送到GPU上,提取完特征之后,再恢復(fù)順序,計(jì)算loss。這樣對(duì)最終的loss沒(méi)有影響,但每個(gè)batch上BN的計(jì)算會(huì)被改變,從而避免信息泄露的問(wèn)題?!?/p>

【BN在另一個(gè)自監(jiān)督的重要工作BYOL中,引起了一些烏龍事件,相關(guān)的內(nèi)容可以參考文章BYOL、BYOL work without BN和一個(gè)博客https://generallyintelligent.ai/blog/2020-08-24-understanding-self-supervised-contrastive-learning/,最終BYOL論文作者和博客作者達(dá)成的共識(shí)是,BYOL模型的訓(xùn)練依賴(lài)于一個(gè)比較合理的模型參數(shù)初始化,BN能夠幫助提高模型訓(xùn)練過(guò)程中的穩(wěn)定性。先挖個(gè)坑,之后有機(jī)會(huì)筆者會(huì)對(duì)BYOL系列的一些工作進(jìn)行詳細(xì)的解讀】

【關(guān)于BN,BN使用的好,模型效果能夠有很好的提升,但更多的情況下可能是用不好的,并且不易debug,如果換成transformer,使用LN替代BN】

Experiments

數(shù)據(jù)集:ImageNet-1M,100W數(shù)據(jù)量,Instagram-1B,10億數(shù)據(jù)量。后者是為了驗(yàn)證moco模型擴(kuò)展性好。由于使用個(gè)體判別的代理任務(wù),ImageNet的類(lèi)別量就是數(shù)據(jù)量。另外,Inatagram數(shù)據(jù)集更能反應(yīng)真實(shí)世界的數(shù)據(jù)分布,這個(gè)數(shù)據(jù)集中的樣本不是精心挑選的,有長(zhǎng)尾、不均衡等問(wèn)題,圖片中物體有一個(gè)或多個(gè)。

訓(xùn)練:CNN模型,SGD優(yōu)化器,batch size 256,8GPU,200epoch,ResNet50,53h?!鞠噍^于之后的SimCLR、BYOL等工作,moco對(duì)硬件的要求都是最低的,相對(duì)更容易實(shí)現(xiàn)的,affordable。并且moco、moco-v2系列工作,其泛化性能都很好,做下游任務(wù)時(shí),預(yù)訓(xùn)練學(xué)習(xí)到的特征依舊非常強(qiáng)大。SimCLR的論文引用相對(duì)更高一些,moco的方法更平易近人一些】

Linear classification protocol

預(yù)訓(xùn)練模型加一個(gè)線性分類(lèi)頭,即一個(gè)全連接層。

作者做了一個(gè)grid search,發(fā)現(xiàn)分類(lèi)頭的最佳學(xué)習(xí)率是30,非常不可思議。一般深度學(xué)習(xí)中的工作,很少有l(wèi)earning rate會(huì)超過(guò)1。因此,作者認(rèn)為,這么詭異的學(xué)習(xí)率的原因在于,無(wú)監(jiān)督對(duì)比學(xué)習(xí)學(xué)到的特征分布,和有監(jiān)督學(xué)習(xí)到的特征分布是非常不一樣的。

Ablation:contrastive loss mechanisms

消融實(shí)驗(yàn)。三種對(duì)比學(xué)習(xí)流派之間的比較。實(shí)驗(yàn)結(jié)果如下圖所示:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

?上圖中,橫坐標(biāo)k表示負(fù)樣本的數(shù)量,可以近似理解為字典的大小,縱坐標(biāo)是ImageNet上的top one 準(zhǔn)確率。end-to-end方法,受限于顯卡內(nèi)存,字典大小有限,32G的顯卡內(nèi)存,能用的最大的batch size是1024。memory bank方法整體上比end-to-end和moco效果都要差一些,主要就是因?yàn)樘卦\的不一致性導(dǎo)致的。另外,黑線的走勢(shì)是不知道的,因?yàn)橛布o(wú)法支撐相關(guān)的實(shí)驗(yàn),其后面結(jié)果可能會(huì)更高,也可能會(huì)變差。moco的字典大小,從16384增長(zhǎng)到65536,效果提升已經(jīng)不是很明顯了,所以沒(méi)有更大的字典的比較。上圖結(jié)論:moco性能好、硬件要求低、擴(kuò)展性好。

Ablation:momentum

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

消融實(shí)驗(yàn),動(dòng)量更新。實(shí)驗(yàn)結(jié)果下圖所示:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

動(dòng)量參數(shù)0.99-0.9999,效果會(huì)好一些。?大的動(dòng)量參數(shù),保證了字典中特征的一致性。動(dòng)量參數(shù)為0,即每個(gè)iteration里面,直接把編碼器q拿來(lái)作為編碼器k,導(dǎo)致模型無(wú)法收斂,loss一致在震蕩,最終模型訓(xùn)練失敗。這個(gè)實(shí)驗(yàn)非常有力的證明了字典一致性的重要性。

Comparison with previous results.

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

上面實(shí)驗(yàn)結(jié)果表明:基于對(duì)比學(xué)習(xí)的方法效果更好,模型容量越大效果越好?,moco在小模型和大模型上都能取得好的效果。

Transferring Features

無(wú)監(jiān)督學(xué)習(xí)最主要的目標(biāo)是要學(xué)習(xí)一個(gè)可以遷移的特征,驗(yàn)證moco模型得到的特征在下游任務(wù)上的表現(xiàn),能不能有好的遷移學(xué)習(xí)效果。

另外,由于前面講到,無(wú)監(jiān)督學(xué)習(xí)到的特征分布和有監(jiān)督學(xué)習(xí)到的特征分布是很不一樣的,在將無(wú)監(jiān)督預(yù)訓(xùn)練模型應(yīng)用到下游任務(wù)時(shí),不能每個(gè)任務(wù)的分類(lèi)頭都進(jìn)行參數(shù)搜索,這樣就失去了無(wú)監(jiān)督學(xué)習(xí)的意義,解決方法是:歸一化,然后整個(gè)模型進(jìn)行參數(shù)微調(diào)。BN層用的是synchronized BN,即多卡訓(xùn)練時(shí),把所有卡的信息都進(jìn)行統(tǒng)計(jì),計(jì)算總的running mean 和running variance,然后更新BN層,讓特征歸一化更徹底,模型訓(xùn)練更穩(wěn)定。

Schedules.如果下游任務(wù)數(shù)據(jù)集很大,不在ImageNet上進(jìn)行預(yù)訓(xùn)練,當(dāng)訓(xùn)練時(shí)間足夠長(zhǎng),模型效果依然可以很好,這樣就體現(xiàn)不出moco的優(yōu)越性了。但是下游數(shù)據(jù)集訓(xùn)練時(shí)間很短時(shí),moco中預(yù)訓(xùn)練還是有效果的。所以moco中用的是較短的訓(xùn)練時(shí)間。

PASCAL VOC Object Detection,數(shù)據(jù)集PASCAL VOC,任務(wù):目標(biāo)檢測(cè),實(shí)驗(yàn)結(jié)果如下圖:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

?coco數(shù)據(jù)集,實(shí)驗(yàn)結(jié)果如下圖:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

?其他任務(wù):人體關(guān)鍵點(diǎn)檢測(cè)、姿態(tài)檢測(cè)、實(shí)例分割、語(yǔ)義分割,實(shí)驗(yàn)結(jié)果如下圖:

【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí),pytorch,學(xué)習(xí),人工智能

?實(shí)驗(yàn)結(jié)果總結(jié):moco在很多任務(wù)上都超過(guò)了ImageNet上有監(jiān)督預(yù)訓(xùn)練的結(jié)果,在少數(shù)幾個(gè)任務(wù)上稍微差一些,主要是實(shí)例分割和語(yǔ)義分割任務(wù),【所以后面有人認(rèn)為,對(duì)比學(xué)習(xí)不適合dence prediction的任務(wù),這種任務(wù)每個(gè)像素點(diǎn)都需要進(jìn)行預(yù)測(cè),之后有一些相關(guān)的工作,如dence contrast,pixel contrast等】。

在所有這些任務(wù)中,在Instagram上預(yù)訓(xùn)練的模型要比ImageNet上的效果好一些,說(shuō)明moco擴(kuò)展性好,與NLP中結(jié)論相似,即自監(jiān)督預(yù)訓(xùn)練數(shù)據(jù)量越多越好,符合無(wú)監(jiān)督學(xué)習(xí)的終極目標(biāo)。

Discussion and Conclusion

從imageNet到Instagram,雖然有效果上的提升,但是很小,而數(shù)據(jù)集是從100W增加到10億,擴(kuò)大了1000倍,所以大規(guī)模數(shù)據(jù)集可能還是沒(méi)有被很好的利用起來(lái),可能更好的代理任務(wù)能夠解決這個(gè)問(wèn)題。

自監(jiān)督中,個(gè)體判別任務(wù),還可以考慮向NLP中mask auto-encoders那樣設(shè)計(jì)代理任務(wù),完成完形填空,何凱明大神之后在2021年有了MAE這個(gè)文章?!綧AE文章在2021年公布,但是思路應(yīng)該至少在moco這篇文章中已經(jīng)有了】

moco設(shè)計(jì)的初衷,是基于對(duì)比學(xué)習(xí),設(shè)計(jì)一個(gè)大且一致的字典,能夠讓正負(fù)樣本更好的進(jìn)行對(duì)比。

總結(jié)

moco雖然是2020年的工作,但最近一兩年自監(jiān)督學(xué)習(xí)相關(guān)的工作刷新是很快的。

自監(jiān)督學(xué)習(xí)第一階段相關(guān)工作:InsDis,CPC,CMC等,百花齊放

第二階段:moco,SimCLR雙雄并立,都是基于對(duì)比學(xué)習(xí)的

第三階段:BYOL,SimSam,不需要對(duì)比學(xué)習(xí),不需要負(fù)樣本

第四階段:moco-v3,DINO等,基于transformer的工作,不再基于ResNet等CNN結(jié)構(gòu)。

參考

MoCo 論文逐段精讀【論文精讀】_嗶哩嗶哩_bilibili

到了這里,關(guān)于【Pytorch】從MoCo看無(wú)監(jiān)督對(duì)比學(xué)習(xí);從SupCon看有監(jiān)督對(duì)比學(xué)習(xí)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 對(duì)比學(xué)習(xí)MoCo損失函數(shù)infoNCE理解(附代碼)

    對(duì)比學(xué)習(xí)MoCo損失函數(shù)infoNCE理解(附代碼)

    ?MoCo loss計(jì)算采用的損失函數(shù)是InfoNCE: ?? 下面是MoCo的偽代碼,MoCo這個(gè)loss的實(shí)現(xiàn)就是基于cross entropy loss。 將k作為q的正樣本,因?yàn)閗與q是來(lái)自同一張圖像的不同視圖;將queue作為q的負(fù)樣本,因?yàn)閝ueue中含有大量不同圖像的視圖。 在具體python代碼中(在/moco/builder.py和/main_m

    2024年02月05日
    瀏覽(67)
  • 復(fù)現(xiàn)圖神經(jīng)網(wǎng)絡(luò)(GNN)論文的過(guò)程以及PyTorch與TensorFlow對(duì)比學(xué)習(xí)

    復(fù)現(xiàn)圖神經(jīng)網(wǎng)絡(luò)(GNN)論文的過(guò)程通常包括以下幾個(gè)步驟: 一、理解論文內(nèi)容:首先徹底理解論文,包括其理論基礎(chǔ)、模型架構(gòu)、使用的數(shù)據(jù)集、實(shí)驗(yàn)設(shè)置和得到的結(jié)果。 二、獲取或準(zhǔn)備數(shù)據(jù)集:根據(jù)論文中描述的實(shí)驗(yàn),獲取相應(yīng)的數(shù)據(jù)集。如果論文中使用的是公開(kāi)數(shù)據(jù)集

    2024年01月20日
    瀏覽(22)
  • Pytorch 對(duì)比TensorFlow 學(xué)習(xí):Day 17-18: 循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)和LSTM

    Day 17-18: 循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)和LSTM 在這兩天的學(xué)習(xí)中,我專(zhuān)注于理解循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)和長(zhǎng)短期記憶網(wǎng)絡(luò)(LSTM)的基本概念,并學(xué)習(xí)了它們?cè)谔幚硇蛄袛?shù)據(jù)時(shí)的應(yīng)用。 1.RNN和LSTM基礎(chǔ): RNN:了解了RNN是如何處理序列數(shù)據(jù)的,特別是它的循環(huán)結(jié)構(gòu)可以用于處理時(shí)間序列或連續(xù)

    2024年01月20日
    瀏覽(18)
  • Pytorch和Tensoflow對(duì)比學(xué)習(xí)第三周--Day 19-20: 數(shù)據(jù)加載和預(yù)處理

    這兩天的學(xué)習(xí)重點(diǎn)是掌握在PyTorch和TensorFlow中進(jìn)行數(shù)據(jù)加載和預(yù)處理的方法。正確的數(shù)據(jù)處理是訓(xùn)練有效模型的關(guān)鍵步驟。 數(shù)據(jù)加載和預(yù)處理: 學(xué)習(xí)了如何使用PyTorch的DataLoader和Dataset類(lèi)以及TensorFlow的數(shù)據(jù)API來(lái)加載和預(yù)處理數(shù)據(jù)。 理解了數(shù)據(jù)標(biāo)準(zhǔn)化、轉(zhuǎn)換和批處理的重要性。

    2024年01月20日
    瀏覽(27)
  • Pytorch 與 Tensorflow對(duì)比學(xué)習(xí) 第3周:進(jìn)階主題 Day 15-16: 卷積神經(jīng)網(wǎng)絡(luò)(CNN)

    第3周:進(jìn)階主題 Day 15-16: 卷積神經(jīng)網(wǎng)絡(luò)(CNN) 在這兩天中,我專(zhuān)注于學(xué)習(xí)卷積神經(jīng)網(wǎng)絡(luò)(CNN)的基礎(chǔ)知識(shí),包括卷積層和池化層的工作原理以及它們?cè)趫D像處理中的應(yīng)用。 卷積神經(jīng)網(wǎng)絡(luò)基礎(chǔ): 卷積層:學(xué)習(xí)了卷積層如何通過(guò)濾波器(或稱(chēng)為核)提取圖像的特征。每個(gè)濾波器

    2024年01月20日
    瀏覽(48)
  • Pytorch 和 TensorFlow 對(duì)比學(xué)習(xí)筆記,第4周:綜合應(yīng)用和實(shí)戰(zhàn)項(xiàng)目 Day 21-24: 實(shí)戰(zhàn)項(xiàng)目

    第4周:綜合應(yīng)用和實(shí)戰(zhàn)項(xiàng)目 Day 21-24: 實(shí)戰(zhàn)項(xiàng)目 項(xiàng)目目標(biāo): 開(kāi)始一個(gè)小型項(xiàng)目,如圖像分類(lèi)、文本生成或其他您感興趣的任務(wù)。 應(yīng)用到目前為止所學(xué)的知識(shí)。 項(xiàng)目選擇: **圖像分類(lèi):**使用Pytorch或TensorFlow構(gòu)建一個(gè)能夠識(shí)別不同類(lèi)別圖像的模型。 文本生成:創(chuàng)建一個(gè)文本生成

    2024年01月20日
    瀏覽(26)
  • MoCo V3:視覺(jué)自監(jiān)督迎來(lái)Transformer

    MoCo V3:視覺(jué)自監(jiān)督迎來(lái)Transformer

    何凱明從 CVPR 2020 上發(fā)表的 MoCo V1(Momentum Contrast for Unsupervised Visual Representation Learning),到前幾天掛在arxiv上面的 MoCo V3(An Empirical Study of Training Self-Supervised Visual Transformers),MoCo一共走過(guò)了三個(gè)版本。 今天介紹 MoCo 系列第三版,MoCo v1 和 v2 是針對(duì) CNN 設(shè)計(jì)的,而 MoCo v3 是針

    2024年02月05日
    瀏覽(27)
  • 自監(jiān)督去噪:Noise2Noise原理及實(shí)現(xiàn)(Pytorch)

    自監(jiān)督去噪:Noise2Noise原理及實(shí)現(xiàn)(Pytorch)

    文章地址:https://arxiv.org/abs/1803.04189 ICML github 代碼: https://github.com/NVlabs/noise2noise 本文整理和參考代碼: https://github.com/shivamsaboo17/Deep-Restore-PyTorch 文章核心句子: ‘learn to turn bad images into good images by only looking at bad images, and do this just as well, sometimes even better.’ 1. 理論背景 如果有

    2024年02月14日
    瀏覽(21)
  • 自監(jiān)督去噪: self2self 原理及實(shí)現(xiàn)(Pytorch)

    自監(jiān)督去噪: self2self 原理及實(shí)現(xiàn)(Pytorch)

    文章地址:https://ieeexplore.ieee.org/document/9157420 原始代碼:https://github.com/scut-mingqinchen/self2self 本文參考代碼: https://github.com/JinYize/self2self_pytorch 本文參考博客: https://zhuanlan.zhihu.com/p/361472663 website:https://csyhquan.github.io/ 1. 原理簡(jiǎn)介 噪聲圖片 y 可以表示為 干凈圖片 x 和噪聲 n的疊

    2024年02月15日
    瀏覽(22)
  • 李沐論文精讀系列三:MoCo、對(duì)比學(xué)習(xí)綜述(MoCov1/v2/v3、SimCLR v1/v2、DINO等)

    李沐論文精讀系列三:MoCo、對(duì)比學(xué)習(xí)綜述(MoCov1/v2/v3、SimCLR v1/v2、DINO等)

    傳送門(mén): 李沐論文精讀系列一: ResNet、Transformer、GAN、BERT 李沐論文精讀系列二:Vision Transformer、MAE、Swin-Transformer 李沐論文精讀系列四:CLIP和改進(jìn)工作串講(LSeg、GroupViT、VLiD、 GLIPv1、 GLIPv2、CLIPasso) 1.1 導(dǎo)言 參考: 論文:Momentum Contrast for Unsupervised Visual Representation Learni

    2024年02月04日
    瀏覽(22)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包