JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

視覺Transformer

如果不再把影像當作給卷積用的網格,而是把它當作一句由「圖塊」組成的句子,會發生什麼?你會得到視覺 Transformer——再加上對圖文配對的巧妙運用,就有了像 CLIP 這樣把影像和文字連起來的模型。

從網格到一句「圖塊」組成的句子

在這架學習階梯的前面,你已經掌握了兩個重要思想。在電腦視覺裡,卷積神經網路靠在像素網格上滑動小小的濾波器來讀圖,一條邊一條邊、一塊區域一塊區域地堆疊出特徵。在語言相關的幾階裡,Transformer透過自注意力讓每個詞都去看其它所有詞,從而讀懂一句話。視覺 Transformer 提出了一個看似簡單的問題:如果我們像餵一句話那樣,把一張影像餵給 Transformer,會怎麼樣?

問題在於,Transformer 想要的是一小串詞元(token),可是一張 224×224 的影像就有超過 15 萬個像素——多得無法讓每個像素都去關注其它所有像素。訣竅是把影像切成由小方塊組成的網格,每個方塊叫一個圖塊(patch),比如各 16×16 像素。這樣一張 224×224 的影像就變成整齊的 14×14 網格,只有 196 個圖塊。每個圖塊被展平成一個向量,再經過一個小小的線性層,變成一個嵌入向量——正是 Transformer 愛吃的那種稠密向量。一個圖塊,就這樣變成了一個「詞」。

走進視覺 Transformer 內部

視覺 Transformer(ViT)把這些零件組裝起來,方式應該會讓你想起語言那一側的做法。首先,每個圖塊嵌入都會加上一個位置編碼——一個可學習的向量,告訴網路「這是第 5 個圖塊,在第 1 行、第 5 列」——好讓網路找回它在做成列表時丟掉的佈局。然後整串序列流過一摞標準的 Transformer 塊,每一塊先做多頭自注意力,再接一個小小的前饋網路。

正是在這裡,ViT 與卷積網路分道揚鑣。CNN 在它早期的層裡只會把鄰近的像素組合起來;要經過很多層堆疊,某個濾波器的感受野才夠寬,才能把影像的一個角和它的中心聯繫起來。自注意力沒有這種限制。在最最開始的那一塊裡,覆蓋狗耳朵的圖塊就可以直接去關注覆蓋狗尾巴的圖塊,無論它們隔得多遠。從第一層起,整張圖就已經「盡收眼底」。

為了給整張圖給出一個單一的答案——比如一個類別標籤——ViT 又從語言模型那裡借來一招:它在最前面額外加上一個可學習的詞元,常叫做 [CLS] 詞元,它不屬於任何圖塊。隨著注意力運轉,這個詞元會從所有真實圖塊那裡匯聚資訊,它最終的向量被送進一個小小的分類頭。它就是一個專職的記錄員,唯一的任務就是把這張圖總結出來。

patches  = split_image(img, patch=16)      # 196 patches of 16x16
tokens   = linear_project(flatten(patches))# each patch -> embedding vector
tokens   = [CLS] + tokens                  # prepend the summary token
tokens   = tokens + positional_encoding    # add back the 'where'
z        = transformer_blocks(tokens)       # attention all the way down
label    = classifier_head(z[CLS])          # read the answer off [CLS]
六行程式碼看懂視覺 Transformer:切塊、嵌入、加位置、做注意力、讀出答案。

為什麼 CNN 沒有就此退場

把卷積宣布為「已死」很誘人,但誠實的故事要有意思得多。CNN 在搭建時就內建了很強的歸納偏置:它假設鄰近的像素彼此相關(局部性),也假設一隻貓無論出現在畫面哪個位置都還是一隻貓(平移等變性)。這些假設是禮物——它們讓 CNN 能從規模不大的資料集裡學到東西。ViT 幾乎不做這些假設;注意力把所有圖塊都看作同樣可以相互連接。這份自由,恰恰就是它在小資料上的弱點。

2020 年最初那篇 ViT 論文把這一點講得毫不客氣。在 ImageNet(約一百萬張影像)上從零訓練時,ViT 實際上輸給了規模相當的 ResNet。只有當它先在一個大得多、含數億張影像的資料集上做預訓練、再在較小的目標任務上微調之後,它才反超。資料足夠多時,Transformer 會自己學到 CNN 被白白贈予的那種局部性,然後繼續往前跑。這個教訓在本領域反覆出現:一個靈活的模型加上海量資料,能夠擊敗精心手工設計的先驗,但前提是越過某個規模閾值。

CLIP:教影像和文字共享同一個空間

一旦影像和文字都以詞元序列的形式存在,一種誘人的可能性就打開了:能不能讓一個模型同時理解兩者?CLIP(對比式語言—影像預訓練,2021)就是這個突破性的答案。它用兩個編碼器——一個影像編碼器(通常是 ViT)和一個文字編碼器(一個 Transformer)——並訓練它們把一張圖和它的配文放到同一個共享嵌入空間裡的同一個位置上。不需要任何人工標註的類別;監督訊號是免費來的,來自從網上抓取的數億對「影像—配文」。

訓練目標是對比學習,它的想法美在簡單。取一批,比如 256 對「影像—配文」。把每張圖和每段配文都編碼成向量。現在把全部 256×256 種可能的圖文組合擺給模型看,並告訴它:那 256 對真實配對應該得高分(把它們拉到一起),而所有錯配的組合應該得低分(把它們推開)。它從不去學一份固定的標籤清單。它學到的是一種豐富得多的本領:判斷任意一段配文與任意一張圖有多匹配。

回報是驚人的:CLIP 能對它從未被明確訓練過的類別做零樣本影像分類。要問「這是不是一張柯基的照片?」,你只需把文字「一張柯基的照片」和其它幾個候選句子都編碼,再把影像編碼,然後挑出在共享空間裡離這張圖最近的那句配文。你可以在測試時只靠寫新句子就發明出新類別——不必重新訓練,不需要帶標籤的樣本。

它解鎖了什麼——以及它真正做不到什麼

CLIP 的圖文共享空間,最後悄悄成了許多現代 AI 之下的地基。它是許多多模態模型內部的那座橋,讓模型能描述一張照片或回答關於它的問題;而它的文字編碼器,正是讓文生圖系統能用一句文字提示來引導影像生成的關鍵——這正是下一篇關於擴散模型的指南的主題。把圖塊當作詞元,給我們的不只是一個新的分類器;它讓視覺和文字擁有了一種共同的語言。

現在說說誠實的侷限。CLIP 會辨識,但不會定位。它會樂呵呵地告訴你圖裡有個消防栓,但靠它自己,畫不出一個框把消防栓框起來——那仍然需要專門的偵測方法。它在數數上也弱得出人意料(在它眼裡「三隻貓」常常和「兩隻貓」差不多),在細緻的空間關係上同樣如此(「盤子左邊的杯子」)。而且,因為它的訓練配文是從開放網路上抓來的,CLIP 也吸收了網路的偏見與盲點——它了解的是網際網路選擇去拍攝、去配文的那個視覺世界,而不是世界本來的樣子。

還有一件事要擺正分寸。「零樣本」聽起來像魔法,但它只對那些在那數億條訓練配文裡某處被充分呈現過的概念才奏效。去問 CLIP 一種罕見的醫學病症,或一個它從未見過被描述的小眾工業零件,魔法就蒸發了。模型並不是在從第一性原理出發對全新類別進行推理;它是在檢索、重組它在某種瀰散意義上「已經見過」的模式。這確確實實很強大——也確確實實不等於「理解」。