現(xiàn):組合式零樣本學(xué)習(xí)如何讓CLIP識(shí)別‘紅色蘋果’)
當(dāng)業(yè)務(wù)場(chǎng)景從“給一張圖打上類別標(biāo)簽”升級(jí)為“判斷一個(gè)物體的顏色、材質(zhì)、形狀等組合屬性”時(shí)常規(guī)分類模型往往力不從心。ReCLIP 這類基于 CLIP 的項(xiàng)目之所以受到關(guān)注是因?yàn)樗蜒芯恐匦姆诺搅恕敖M合式零樣本學(xué)習(xí)”上也就是在訓(xùn)練階段沒有見過的屬性-物體組合上做分類。這篇文章會(huì)圍繞 ReCLIP 的原理分析與上手復(fù)現(xiàn)展開先從組合式零樣本學(xué)習(xí)的定義說起再拆解負(fù)傳播和區(qū)域注釋這兩項(xiàng)關(guān)鍵技術(shù)最后給出可參考的代碼框架和調(diào)參建議。如果讀者已經(jīng)接觸過 OpenAI CLIP但一直不太清楚什么叫“組合稀疏性”或者希望了解怎么讓 CLIP 從“能認(rèn)出蘋果”進(jìn)階到“能認(rèn)出紅色的蘋果與綠色的蘋果”這篇文章會(huì)很合適。整篇不會(huì)只停留在名詞解釋層面而是盡量把數(shù)據(jù)準(zhǔn)備、候選構(gòu)造、推理打分、注意力圖獲取和常見異常都串起來。1. 組合式零樣本學(xué)習(xí)ReCLIP 要解決的問題1.1 從“紅色番茄”這個(gè)組合說起傳統(tǒng)圖像分類面臨一個(gè)常見的困境訓(xùn)練集里有“紅色番茄”圖片里也出現(xiàn)“紅色番茄”時(shí)模型可以做得很好但是當(dāng)測(cè)試集出現(xiàn)“黃色番茄”時(shí)模型如果沒有見過這種顏色組合就很難做出正確判斷。這類問題被稱為組合式零樣本學(xué)習(xí)英文全稱是 Compositional Zero-Shot Learning簡(jiǎn)稱 CZSL。它把視覺概念拆成兩個(gè)維度來理解一個(gè)是屬性例如“紅色”“金屬”“木質(zhì)”另一個(gè)是物體例如“蘋果”“杯子”“汽車”。一個(gè)組合標(biāo)簽可以寫成“屬性 物體”的形式。在訓(xùn)練階段模型只能看到部分屬性-物體組合。在測(cè)試階段模型需要泛化到未出現(xiàn)過的屬性-物體對(duì)。比如訓(xùn)練集可能有“紅色蘋果”和“綠色葉子”但沒有“綠色蘋果”。如果模型真的學(xué)會(huì)了“綠色”這個(gè)屬性那么面對(duì)一張綠色蘋果的圖就應(yīng)該能夠推測(cè)出它屬于“綠色蘋果”而不是簡(jiǎn)單粗暴地把它分類成“葉子”。1.2 為什么普通分類模型很難做好 CZSL普通分類模型通常會(huì)給“紅色蘋果”一個(gè)獨(dú)立類別。如果訓(xùn)練集只有一百個(gè)屬性、一千個(gè)物體理論上組合空間就有十萬種。絕大部分組合在訓(xùn)練階段根本不會(huì)出現(xiàn)所以“給每個(gè)組合分配一個(gè)類別編號(hào)”的做法幾乎不可行。更關(guān)鍵的一點(diǎn)是屬性本身是跨物體共享的?!凹t色”可以出現(xiàn)在紅色汽車、紅色番茄、紅色杯子上物體本身又承載了多種屬性?!凹t色”和“番茄”之間不是獨(dú)立互斥的關(guān)系而是存在一種可組合結(jié)構(gòu)。因此單純用視覺特征映射到一個(gè)固定分類向量很難把屬性從物體特征中分離出來。ReCLIP 項(xiàng)目所關(guān)心的問題就是這個(gè)組合空間訓(xùn)練樣本稀疏、難以窮舉的問題。它的核心思路不是重新設(shè)計(jì)一個(gè)復(fù)雜的分類頭而是利用 CLIP 文本分支里蘊(yùn)含的豐富語義把“屬性”和“物體”之間的組合規(guī)則顯式引入推理過程。1.3 CZSL 的兩個(gè)評(píng)估設(shè)置要理解 ReCLIP 的產(chǎn)出還需要區(qū)分兩個(gè)高頻出現(xiàn)的評(píng)估場(chǎng)景。第一個(gè)叫 closed-world 設(shè)置測(cè)試時(shí)只考慮那些屬于未見組合的標(biāo)簽換句話說已知候選集合里不會(huì)混入大量無關(guān)組合。第二個(gè)叫 open-world 設(shè)置測(cè)試時(shí)要考慮全部屬性-物體組合包括很多在訓(xùn)練階段沒出現(xiàn)過的組合甚至可能包含不符合物理常識(shí)的組合例如“方形橘子”難度明顯更高。在實(shí)際論文和開源倉庫中MIT-States、UT-Zappos、C-GQA 是三個(gè)最常用的數(shù)據(jù)集。MIT-States 數(shù)據(jù)量適中屬性與物體類別豐富UT-Zappos 以鞋子圖像為主屬性更多是顏色、材質(zhì)、樣式C-GQA 是一個(gè)規(guī)模較大的組合數(shù)據(jù)集組合空間更大也更接近真實(shí)開放場(chǎng)景。2. 從 CLIP 到 ReCLIP為什么直接使用 CLIP 還不夠2.1 CLIP 零樣本分類的核心邏輯CLIP 由圖像編碼器和文本編碼器組成。訓(xùn)練時(shí)模型在海量圖文對(duì)上學(xué)習(xí)對(duì)比學(xué)習(xí)目標(biāo)讓匹配的圖片和文本在共享嵌入空間中距離更近不匹配的圖片和文本距離更遠(yuǎn)。做零樣本分類時(shí)CLIP 會(huì)把所有候選類別名稱轉(zhuǎn)成句子再用文本編碼器編碼。例如候選類別是“dog”和“cat”可以構(gòu)造“a photo of a dog”和“a photo of a cat”。同時(shí)圖片經(jīng)過圖像編碼器得到特征。最后計(jì)算圖片特征和所有文本特征的余弦相似度相似度最高的類別就是預(yù)測(cè)結(jié)果。用一段常見的代碼來表示就是下面的樣子import torch import clip from PIL import Image device cuda if torch.cuda.is_available() else cpu model, preprocess clip.load(ViT-B/32, devicedevice) image preprocess(Image.open(test.jpg)).unsqueeze(0).to(device) texts clip.tokenize([ a photo of a dog, a photo of a cat, a photo of a bird ]).to(device) with torch.no_grad(): image_features model.encode_image(image) text_features model.encode_text(texts) image_features image_features / image_features.norm(dim-1, keepdimTrue) text_features text_features / text_features.norm(dim-1, keepdimTrue) logit_scale model.logit_scale.exp() logits logit_scale * image_features text_features.t() probs logits.softmax(dim-1) print(probs)CLIP 的優(yōu)勢(shì)是文本分支可以直接描述一個(gè)由多個(gè)單詞組合成的概念。比如“a photo of a red apple”文本編碼器并不是簡(jiǎn)單地把“red”和“apple”的特征向量相加而是能夠?qū)⒄湓捑幋a成一個(gè)具有組合語義的向量。2.2 直接遷移到 CZSL 的問題既然 CLIP 能理解“red apple”那把“red”“apple”兩兩組合成文本再與圖像特征比對(duì)是不是就足夠解決組合式零樣本分類了實(shí)驗(yàn)結(jié)果表明并非如此。原因是 CLIP 的圖像編碼器和文本編碼器之間存在一定偏差。文本分支對(duì)組合語義的理解更充分但圖像分支往往把主要注意力放在“這是什么物體”上對(duì)顏色、材質(zhì)、形狀等細(xì)粒度屬性不夠敏感。舉個(gè)例子圖里有一個(gè)紅色番茄。CLIP 的圖像編碼器很擅長(zhǎng)抓住“番茄”這個(gè)主體但紅色所占的像素區(qū)域可能被全局池化過程稀釋。直接計(jì)算圖像特征與“a photo of a red tomato”的文本特征相似度很可能得到中等分?jǐn)?shù)甚至?xí)陀谀P皖A(yù)測(cè)出的“a photo of a tomato”。也就是說組合信息雖然存在于文本空間中但在圖像特征中沒有得到充分激活。這就為 ReCLIP 留下了優(yōu)化空間。ReCLIP 的核心假設(shè)是CLIP 的文本空間已經(jīng)具備組合知識(shí)不需要重新訓(xùn)練大規(guī)模分類器只需要在推理階段設(shè)計(jì)更好的組合打分方式并且對(duì)圖像特征做輕量修正。2.3 ReCLIP 的兩大改進(jìn)方向ReCLIP 的改進(jìn)可以概括為兩條線索。第一條是負(fù)傳播主要解決圖像特征中“屬性信息被物體信息遮蓋”的問題。第二條是區(qū)域注釋主要解決全局圖像特征無法體現(xiàn)局部屬性細(xì)節(jié)的問題。這兩個(gè)方向并不是脫離 CLIP 結(jié)構(gòu)重新發(fā)明輪子而是盡量以最小成本把 CLIP 變成更強(qiáng)的組合式零樣本分類器。正因如此ReCLIP 即使在零樣本、無訓(xùn)練微調(diào)的情況下也能得到不錯(cuò)的基線效果這也是它在社區(qū)里受到關(guān)注的重要原因。3. ReCLIP 方法拆解負(fù)傳播與區(qū)域注釋3.1 基本打分思路把候選組合變成提示句在實(shí)現(xiàn) ReCLIP 時(shí)最基礎(chǔ)的工作是把屬性集合和物體集合做笛卡爾積生成候選組合。比如有 100 個(gè)屬性、200 個(gè)物體就會(huì)生成 2 萬個(gè)候選組合。如果直接構(gòu)造 2 萬條文本再分別和一張圖片求相似度在 CLIP 文本編碼器上仍然可行但需要注意內(nèi)存管理。ReCLIP 在設(shè)計(jì)提示語時(shí)不會(huì)只使用單一模板。因?yàn)?CLIP 的性能高度依賴提示語格式單一模板在不同數(shù)據(jù)集上可能有偏。常見的做法是同時(shí)使用多個(gè)模板并對(duì)多個(gè)模板的輸出做平均或加權(quán)。比如a photo of a {attr} {obj}a {attr} {obj} in a photoan {attr} {obj}{attr} {obj} with a clean background每一條模板都對(duì)應(yīng)一個(gè)文本嵌入。得到多個(gè)候選分?jǐn)?shù)后再通過聚合函數(shù)得到最終分?jǐn)?shù)。這里有一個(gè)容易理解偏差的地方CLIP 的文本編碼器不是把所有單詞的 embedding 簡(jiǎn)單求平均而是通過 Transformer 對(duì)整句話建模。因此“a red tomato”和單獨(dú)編碼“red”與“tomato”后相加結(jié)果并不一樣。ReCLIP 實(shí)際使用中通常以整句文本為主屬性單詞和物體單詞只作為輔助特征。3.2 負(fù)傳播讓組合評(píng)分學(xué)習(xí)“拒絕錯(cuò)誤組合”負(fù)傳播是 ReCLIP 方法名字里最吸引人的部分也是理解門檻最高的部分。直接看圖分類時(shí)模型只需要回答“這是什么物體”但在 CZSL 中模型需要同時(shí)回答“屬性是什么”和“物體是什么”。如果模型只能識(shí)別物體但完全忽略屬性它就會(huì)把紅色番茄和黃色番茄看作同一個(gè)類別。負(fù)傳播的核心思路是在推理階段除了給正樣本組合高分?jǐn)?shù)之外還要主動(dòng)讓圖像特征在某些負(fù)樣本組合上降低分?jǐn)?shù)。比如模型識(shí)別出圖片中的物體很可能是“番茄”那么對(duì)“紅色番茄”的分?jǐn)?shù)應(yīng)該高于“綠色番茄”。如果 CLIP 默認(rèn)把綠色和番茄關(guān)聯(lián)得更強(qiáng)那么負(fù)傳播就會(huì)利用屬性與物體之間的不匹配關(guān)系給出一個(gè)梯度更新信號(hào)。這個(gè)操作不是對(duì)模型權(quán)重做梯度更新而是像一個(gè)“測(cè)試時(shí)優(yōu)化模塊”。在推理時(shí)通過候選組合的文本特征和當(dāng)前圖片特征計(jì)算損失然后讓圖片的輸入特征或中間特征沿?fù)p失下降的方向做少量修正讓后續(xù)打分對(duì)屬性更加敏感。如果只用一句話總結(jié)負(fù)傳播就是不是讓模型死記“紅色番茄”這個(gè)組合而是讓圖像特征在“番茄”這一物體條件下關(guān)注屬性和物體之間的一致性。這比強(qiáng)制模型記住更多組合標(biāo)簽要靈活得多。3.3 區(qū)域注釋局部特征解決全局信息的屬性丟失負(fù)傳播解決的是屬性權(quán)重偏低的問題而區(qū)域注釋解決的是屬性可能只出現(xiàn)在局部區(qū)域的問題。如果模型只看整張圖片的全局特征那么一個(gè)小區(qū)域的“銀色”或“破損”很可能被大面積背景淹沒。ReCLIP 的區(qū)域注釋會(huì)借助視覺 Transformer 內(nèi)部的注意力信息找到圖片中真正承載屬性判別的若干局部區(qū)域。常見做法是從 CLIP 視覺編碼器的某一層或多層提取注意力圖然后根據(jù)注意力圖對(duì) patch token 做加權(quán)得到一組區(qū)域特征。屬性分類打分時(shí)候選屬性文本可以與這些區(qū)域特征計(jì)算相似度物體分類打分時(shí)仍然可以使用全局特征。這樣一來圖片特征不再只有一個(gè)全局向量而是由“全局特征 區(qū)域特征”共同組成。屬性文本匹配區(qū)域特征物體文本匹配全局特征分工明確。需要說明的是不同開源倉庫在實(shí)現(xiàn)區(qū)域注釋時(shí)細(xì)節(jié)并不完全相同。有的直接使用最后一層多頭注意力的均值有的會(huì)綜合多層注意力有的還會(huì)加入一定空間平滑。實(shí)際使用時(shí)需要根據(jù)項(xiàng)目代碼和 CLIP 的骨干網(wǎng)絡(luò)進(jìn)行調(diào)整。3.4 推理流程整體串聯(lián)把前面幾個(gè)模塊串起來ReCLIP 的一次完整推理大致是下面這樣的流程讀取一張圖像使用 CLIP 預(yù)處理器轉(zhuǎn)為模型輸入。提取圖像全局特征并額外提取注意力圖或區(qū)域特征。使用多個(gè)文本模板構(gòu)造屬性-物體候選文本集。對(duì)候選文本集編碼得到文本特征。結(jié)合全局特征和區(qū)域特征計(jì)算每個(gè)候選組合的初始分?jǐn)?shù)。進(jìn)入負(fù)傳播優(yōu)化階段用正負(fù)組合差異構(gòu)造損失對(duì)圖片相關(guān)特征做少量更新。重新計(jì)算所有候選組合分?jǐn)?shù)輸出 Top-K 結(jié)果。這樣做的好處是整個(gè)過程不需要重新訓(xùn)練 CLIP不會(huì)引入大量額外參數(shù)。即使沒有大規(guī)模 GPU 集群也能在單卡環(huán)境下完成測(cè)試。這也是 ReCLIP 在生產(chǎn)或研究項(xiàng)目中受歡迎的原因。4. 環(huán)境準(zhǔn)備與數(shù)據(jù)說明4.1 基礎(chǔ)環(huán)境依賴ReCLIP 是基于 PyTorch 和 OpenAI CLIP 的視覺語言項(xiàng)目。環(huán)境準(zhǔn)備可以按下面的依賴關(guān)系來理解。運(yùn)行環(huán)境推薦使用 Linux 或 Windows 的 Python 環(huán)境Python 3.8 以上通常問題不大。深度學(xué)習(xí)框架方面PyTorch 是核心版本需要與 CUDA 驅(qū)動(dòng)匹配。由于 CLIP 是一個(gè)比較輕量的模型常見顯卡例如 1080Ti、2080Ti、3090、A100 都可以運(yùn)行只是測(cè)試速度差異較大。模型依賴方面至少需要安裝 OpenAI 開源的 CLIP 庫并配合 torchvision、Pillow、numpy 等常用庫。安裝命令可以參考如下pip install ftfy regex tqdm torch torchvision pip install githttps://github.com/openai/CLIP.git如果用戶只需要快速體驗(yàn) CLIP 本身也可以直接使用 Hugging Face Transformers 版本。但 ReCLIP 項(xiàng)目的很多代碼細(xì)節(jié)與 OpenAI CLIP 的原始實(shí)現(xiàn)有關(guān)特別是注意力圖獲取方式因此建議先按照 OpenAI CLIP 庫來復(fù)現(xiàn)。4.2 數(shù)據(jù)集如何選不同數(shù)據(jù)集對(duì)屬性、物體的定義差異很大準(zhǔn)備方式也不同。這里不打算給出一個(gè)統(tǒng)一的下載命令因?yàn)轫?xiàng)目版本變化很快更推薦先閱讀倉庫 README 中關(guān)于數(shù)據(jù)集的說明。MIT-States 是一個(gè)比較經(jīng)典的 CZSL 數(shù)據(jù)集包含大量日常屬性和物體圖像多為現(xiàn)實(shí)照片。數(shù)據(jù)集中需要重點(diǎn)關(guān)注訓(xùn)練、驗(yàn)證、測(cè)試劃分方式尤其是哪些組合屬于 seen哪些屬于 unseen。如果數(shù)據(jù)集劃分不統(tǒng)一復(fù)現(xiàn)結(jié)果會(huì)產(chǎn)生明顯偏差。UT-Zappos 主要由鞋子圖像構(gòu)成類別比 MIT-States 少但屬性更細(xì)膩適合調(diào)試屬性識(shí)別邏輯。C-GQA 規(guī)模較大組合標(biāo)簽覆蓋很廣對(duì) baseline 有更高要求也更適合評(píng)估模型的真實(shí)開放世界表現(xiàn)。下載數(shù)據(jù)集時(shí)需要注意版權(quán)和學(xué)術(shù)引用規(guī)范。不少視覺數(shù)據(jù)集只允許用于研究不能直接用于商業(yè)項(xiàng)目。在復(fù)現(xiàn)倉庫時(shí)最好保留原始數(shù)據(jù)文件的目錄結(jié)構(gòu)避免因?yàn)槁窂讲灰恢聦?dǎo)致數(shù)據(jù)加載失敗。4.3 CLIP 權(quán)重離線加載有些實(shí)驗(yàn)環(huán)境無法直接訪問外網(wǎng)下載 CLIP 預(yù)訓(xùn)練權(quán)重。OpenAI 提供的 CLIP 權(quán)重默認(rèn)會(huì)緩存在本地目錄。常見的緩存路徑是用戶的~/.cache/clip文件夾。如果離線環(huán)境已經(jīng)拿到了權(quán)重文件可以手動(dòng)把權(quán)重放到該目錄再執(zhí)行clip.load(ViT-B/32)。代碼里通常不需要修改模型名只需要保證緩存文件存在。如果離線環(huán)境沒有緩存目錄CLIP 庫會(huì)自動(dòng)創(chuàng)建目錄并嘗試下載。若下載失敗可以檢查路徑權(quán)限、磁盤空間和網(wǎng)絡(luò)連通性。# 查看權(quán)重緩存目錄的一般位置 ls -la ~/.cache/clip不同版本 CLIP 可能使用不同緩存策略。最穩(wěn)妥的做法是讓項(xiàng)目依賴固定版本的 OpenAI CLIP以保證推理結(jié)果可復(fù)現(xiàn)。5. 一個(gè)可運(yùn)行的 ReCLIP 推理框架5.1 構(gòu)造屬性與物體候選集為了讓文章不只停留在原理層面下面給出一個(gè)可以運(yùn)行的代碼示例。示例并不會(huì)完全復(fù)刻 ReCLIP 論文里的全部數(shù)學(xué)細(xì)節(jié)而是把推理鏈路中最關(guān)鍵的部分提取出來方便讀者理解每一步的輸入輸出。首先是定義候選標(biāo)簽和文本模板。假定屬性集合是[red, green, wooden]物體集合是[apple, tomato, bowl]。我們需要把它們兩兩組合。attributes [red, green, wooden] objects [apple, tomato, bowl] templates [ a photo of a {attr} {obj}, a {attr} {obj} in a photo, an {attr} {obj} ] labels [] texts [] for a in attributes: for o in objects: labels.append((a, o)) pair_texts [t.format(attra, objo) for t in templates] texts.extend(pair_texts) print(labels) print(texts)這段代碼會(huì)產(chǎn)生 9 個(gè)候選組合每個(gè)組合對(duì)應(yīng) 3 條文本提示。后面計(jì)算相似度時(shí)一種簡(jiǎn)單的做法是先求 3 條文本嵌入的平均再用平均嵌入與圖片特征比較。5.2 加載模型和圖片接下來加載 CLIP 模型和圖片。為了讓示例可以執(zhí)行需要準(zhǔn)備一張測(cè)試圖片比如一張番茄照片。import torch import clip from PIL import Image device cuda if torch.cuda.is_available() else cpu model, preprocess clip.load(ViT-B/32, devicedevice) image_path example_tomato.jpg image preprocess(Image.open(image_path)).unsqueeze(0).to(device) with torch.no_grad(): image_features model.encode_image(image) image_features image_features / image_features.norm(dim-1, keepdimTrue)這里使用ViT-B/32是因?yàn)樗陲@存占用和效果之間比較均衡。如果顯存有限可以換RN50如果追求更強(qiáng)的效果可以使用ViT-L/14。5.3 組合文本編碼與打分對(duì)候選文本編碼時(shí)需要注意 batch size。當(dāng)屬性和物體數(shù)量很大時(shí)候選文本可能達(dá)到幾十萬條一次性編碼容易導(dǎo)致顯存溢出。這里先演示批量編碼并打分的基本思路。def encode_prompts(prompts, batch_size256): features [] for i in range(0, len(prompts), batch_size): batch prompts[i: i batch_size] tokens clip.tokenize(batch).to(device) with torch.no_grad(): batch_feat model.encode_text(tokens) batch_feat batch_feat / batch_feat.norm(dim-1, keepdimTrue) features.append(batch_feat) return torch.cat(features, dim0) text_features encode_prompts(texts) text_features text_features.view(len(labels), len(templates), -1) # 簡(jiǎn)單起見先對(duì)同一組合的多模板特征取平均 text_features text_features.mean(dim1) text_features text_features / text_features.norm(dim-1, keepdimTrue) logit_scale model.logit_scale.exp() logits logit_scale * image_features text_features.t() probs logits.softmax(dim-1).cpu().squeeze(0) rank sorted(zip(labels, probs.tolist()), keylambda x: x[1], reverseTrue) for label, prob in rank[:5]: print(label, round(prob, 4))注意這里先對(duì)多模板取平均是一種簡(jiǎn)化策略。實(shí)際 ReCLIP 項(xiàng)目中可能使用更復(fù)雜的文本特征融合方式例如把屬性文本、物體文本和組合文本分別編碼后再做插值。但整體思想是一致的從不同提示角度打分再綜合排序。5.4 如何引入?yún)^(qū)域注釋在官方 CLIP 實(shí)現(xiàn)中如果想獲取注意力圖通常需要對(duì)模型代碼做少量修改。最直接的方式是給視覺 Transformer 的注意力層掛上一個(gè) hook 或修改 forward 函數(shù)把計(jì)算得到的注意力權(quán)重保存下來。下面是思路層面的示例并不保證在最新版 CLIP 中直接通過默認(rèn) API 運(yùn)行因?yàn)椴煌姹緦?duì)注意力層的封裝有所差異。attention_maps [] def save_attention(module, input, output): # 通常需要從 Attention 模塊內(nèi)部拿到注意力矩陣 # 在不同 CLIP 版本中實(shí)現(xiàn)位置不同 if hasattr(module, attn_weights): attention_maps.append(module.attn_weights.detach())實(shí)際運(yùn)行時(shí)更穩(wěn)妥的方法是修改 OpenAI CLIP 源碼中Attention.forward在_attn計(jì)算完成后把注意力權(quán)重保存下來。得到注意力圖后就可以對(duì) patch token 做加權(quán)池化。舉例來說如果最后一層注意力圖顯示圖的右下角與物體區(qū)域重合那么模型在識(shí)別“紅色”屬性時(shí)可以重點(diǎn)關(guān)注右下角對(duì)應(yīng)的 patch 特征而不是平均所有 patch 特征。區(qū)域注釋的具體權(quán)重計(jì)算在不同實(shí)現(xiàn)中存在差異。有的方法會(huì)把注意力圖 resize 到原圖大小再做空間加權(quán)有的方法直接對(duì) patch token 做 top-k 選擇。讀者在復(fù)現(xiàn)時(shí)應(yīng)該優(yōu)先閱讀倉庫源碼中的model_utils.py或clip_utils.py這類文件。5.5 負(fù)傳播的工程表達(dá)負(fù)傳播在工程實(shí)現(xiàn)上更像一個(gè)小型的可優(yōu)化模塊。它不是端到端訓(xùn)練而是在測(cè)試階段對(duì)某張圖像的特征進(jìn)行迭代更新。假設(shè)當(dāng)前圖片的全局特征為image_features候選組合文本特征為text_features。模型先計(jì)算出所有組合分?jǐn)?shù)。負(fù)傳播階段要構(gòu)造一個(gè)優(yōu)化目標(biāo)讓正樣本組合的分?jǐn)?shù)盡量高讓負(fù)樣本組合的分?jǐn)?shù)盡量低。這里的“正負(fù)”取決于某張圖片的候選物體。一個(gè)簡(jiǎn)化后的偽代碼如下target_text text_features[target_index].unsqueeze(0) negative_text text_features[negative_index].unsqueeze(0) # 用正負(fù)樣本差異約束當(dāng)前圖像特征 loss -torch.cosine_similarity(image_feature, target_text, dim-1).mean() loss loss torch.cosine_similarity(image_feature, negative_text, dim-1).mean() # 僅更新圖像特征不更新模型 optimizer torch.optim.SGD([image_feature], lr0.01) for _ in range(10): optimizer.zero_grad() loss.backward() optimizer.step() # 每次更新后重新歸一化可以保持?jǐn)?shù)值穩(wěn)定 image_feature.data image_feature.data / image_feature.data.norm(dim-1, keepdimTrue)這段代碼只用于表達(dá)負(fù)傳播的大致思想不能直接作為最終可運(yùn)行方案。因?yàn)檎鎸?shí)場(chǎng)景中負(fù)樣本的選擇、損失函數(shù)的具體形式、梯度更新層的位置都需要根據(jù)論文和倉庫實(shí)現(xiàn)調(diào)整。但它可以解釋為什么 ReCLIP 雖被稱為零樣本方法卻能做到比普通 CLIP 更強(qiáng)的組合區(qū)分能力它使用一小步測(cè)試時(shí)優(yōu)化把模型對(duì)物體顯著性的偏好推回到更均衡的狀態(tài)。5.6 輸出結(jié)果與可視化ReCLIP 項(xiàng)目最終通常會(huì)輸出一個(gè) JSON 或 CSV 文件記錄每張圖片的預(yù)測(cè)標(biāo)簽和置信度。除了標(biāo)準(zhǔn) Top-1 準(zhǔn)確率外還可以做錯(cuò)誤案例可視化。比如把預(yù)測(cè)錯(cuò)誤但置信度很高的圖片單獨(dú)保存可以幫助判斷是屬性識(shí)別錯(cuò)誤還是物體識(shí)別錯(cuò)誤。一個(gè)常見現(xiàn)象是模型識(shí)別物體的準(zhǔn)確率遠(yuǎn)高于屬性。遇到這種情況不必急著修改整個(gè)模型可以先檢查文本模板中屬性詞的語義是否容易被 CLIP 理解。例如有些屬性本身是“相對(duì)屬性”像“大”和“小”它們必須依賴物體尺寸才能判斷這類屬性在零樣本設(shè)置下會(huì)比顏色屬性更難識(shí)別。6. 評(píng)測(cè)指標(biāo)與實(shí)驗(yàn)配置建議6.1 評(píng)估指標(biāo)ReCLIP 這類 CZSL 項(xiàng)目中最常見的評(píng)估指標(biāo)是 Top-1 準(zhǔn)確率。在 closed-world 設(shè)置下候選集合已經(jīng)提前限制因此 Top-1 可以直接反映模型在受限組合空間的分類能力。在 open-world 設(shè)置下候選集合包含全部組合除 Top-1 外還會(huì)關(guān)注 Top-5、Top-10 等排序指標(biāo)。更嚴(yán)格地說CZSL 論文中通常還要求模型同時(shí)輸出準(zhǔn)確的屬性標(biāo)簽和物體標(biāo)簽。即使屬性識(shí)別錯(cuò)誤只要物體識(shí)別正確也會(huì)被算作整體失敗。因此看指標(biāo)時(shí)要把屬性準(zhǔn)確率和物體準(zhǔn)確率分開分析這對(duì)改進(jìn)模型很有幫助。6.2 對(duì)比實(shí)驗(yàn)怎么設(shè)計(jì)如果想做對(duì)比實(shí)驗(yàn)建議至少設(shè)置下面幾條基線原始 CLIP 提示分類直接把每個(gè)屬性-物體組合構(gòu)造成文本不做負(fù)傳播不做區(qū)域注釋。CLIP zero-shot 模板集成使用多條文本模板并集成觀察提示工程帶來的提升。ReCLIP 全局特征版本只使用負(fù)傳播不加入?yún)^(qū)域注釋。ReCLIP 完整版本同時(shí)使用負(fù)傳播和區(qū)域注釋。這樣拆分以后能夠更清楚地看到每個(gè)模塊帶來的增益。如果只看完整模型和原始 CLIP 的差異很難判斷到底是負(fù)傳播起了作用還是區(qū)域注釋起了作用。有一個(gè)容易被忽略