速遞解讀:Transformer視覺模型核心原理與復現(xiàn)實操指南)
1. 計算機視覺學術(shù)速遞到底在速遞什么第一次看到計算機視覺學術(shù)速遞[5.25]這個標題很多人會以為是一份簡單的論文列表。實際上這類速遞內(nèi)容的核心價值在于把當天或近期冒出來的新工作做一次快速篩選和歸類幫你在信息過載的環(huán)境里抓住真正值得花時間讀的東西。計算機視覺這個方向每天都有大量新論文上傳光靠刷列表根本看不過來所以速遞的本質(zhì)是降噪——把Transformer、擴散模型、多模態(tài)融合這些熱詞背后的實際進展挑出來告訴你哪些是真有新東西哪些只是換個名字重新包裝。我自己跟蹤這個方向有幾年了最大的感受是Transformer架構(gòu)從2020年之后幾乎滲透到了計算機視覺的每一個子任務(wù)里。從最早的ViT把圖像切成patch做分類到Swin Transformer引入窗口注意力解決高分辨率下的計算量問題再到各種針對特定場景改造的變體這條技術(shù)線已經(jīng)非常清晰。速遞里如果出現(xiàn)Transformer相關(guān)的工作我會優(yōu)先看它到底改了什么——是改了注意力機制的計算方式還是改了token的構(gòu)造方法還是純粹在訓練策略上做文章。這個判斷習慣幫我省了大量時間。這份速遞適合誰看如果你是剛進實驗室的研究生需要快速了解某個子方向的現(xiàn)狀速遞能幫你建立地圖感如果你是在做計算機視覺大作業(yè)的本科生速遞里的方法概述和代碼線索能讓你少走彎路如果你是已經(jīng)工作的算法工程師速遞能幫你判斷某個新技術(shù)值不值得跟進落地。不同基礎(chǔ)的人看同一份速遞收獲點不一樣但前提是你得知道怎么讀。2. Transformer在視覺任務(wù)里的核心邏輯拆解2.1 從自注意力到視覺token化Transformer最早是為自然語言處理設(shè)計的核心是自注意力機制。放到計算機視覺里第一個要解決的問題就是圖像是二維的像素網(wǎng)格怎么變成Transformer能吃的序列ViT的做法很直接把圖像切成固定大小的patch比如16x16每個patch拉平成一個向量再經(jīng)過線性映射變成token。這一步看起來簡單但patch大小的選擇直接影響模型能捕捉到的細節(jié)粒度。patch越小token越多計算量按平方增長patch越大token越少但每個token承載的信息更雜。我實際跑過ViT的幾種配置patch16在ImageNet上是個比較平衡的選擇patch32會明顯損失細粒度信息patch8則顯存吃不消。這個經(jīng)驗在速遞里讀論文時很有用——看到有人聲稱用極小的patch取得了好效果第一反應(yīng)應(yīng)該是去看他怎么解決計算量問題的通常要么是用了稀疏注意力要么是做了token合并。Swin Transformer的思路更巧妙它不搞全局注意力而是在局部窗口內(nèi)做自注意力然后通過移位窗口讓不同窗口之間產(chǎn)生信息交換。這個設(shè)計把計算復雜度從平方級降到了線性級讓Transformer能處理更高分辨率的輸入。速遞里如果出現(xiàn)Swin的變體我會重點關(guān)注它的窗口劃分策略和移位方式有沒有新意。2.2 視覺Transformer的幾種典型改造路線從速遞里讀多了會發(fā)現(xiàn)視覺Transformer的改造基本圍繞幾條路線走。第一條是注意力機制的稀疏化代表工作包括Swin、Twins、CSWin等核心思路都是減少需要計算注意力的token對數(shù)量。第二條是token的動態(tài)管理比如Token Merging、EViT這類工作在推理過程中逐步合并或丟棄不重要的token換取速度提升。第三條是引入卷積的先驗比如Conformer、CMT把卷積的局部歸納偏置和Transformer的全局建模能力結(jié)合起來。這幾條路線背后其實是在回答同一個問題視覺任務(wù)到底需要什么樣的注意力純?nèi)肿⒁饬τ嬎懔刻蠹兙植孔⒁饬τ謥G了長距離依賴所以大家都在找中間地帶。我個人的判斷是沒有一種改造能通吃所有任務(wù)。分類任務(wù)對全局信息需求高檢測和分割更依賴多尺度特征所以速遞里看到某個方法在分類上刷了新高不要急著往檢測任務(wù)上套先看它的token設(shè)計是否支持多尺度。2.3 速遞里怎么快速判斷一篇Transformer論文的含金量速遞通常只給標題和摘要怎么在幾分鐘內(nèi)判斷值不值得精讀我的做法是看三個點。第一看它改的是哪個環(huán)節(jié)——是tokenizer、注意力計算、還是訓練目標。改tokenizer的工作往往影響面最大因為下游所有任務(wù)都依賴token表示。第二看實驗對比的對象——如果只跟同量級的Transformer比說服力有限如果跟卷積網(wǎng)絡(luò)和Transformer都做了充分對比可信度更高。第三看有沒有開源代碼——速遞里如果標注了代碼鏈接我會優(yōu)先看代碼結(jié)構(gòu)因為很多論文的方法描述和實際實現(xiàn)之間有g(shù)ap讀代碼比讀論文快。注意速遞里的論文標題經(jīng)常用很花哨的縮寫比如PDFormer、MultiLevel等不要被名字唬住直接看它解決的是什么具體問題。很多工作只是把已有方法換個場景應(yīng)用創(chuàng)新度有限。3. 從速遞到實操Transformer模型復現(xiàn)的關(guān)鍵步驟3.1 環(huán)境準備與依賴選擇看到速遞里感興趣的工作下一步就是復現(xiàn)。我一般從環(huán)境開始PyTorch是首選版本建議1.12以上因為很多新的注意力實現(xiàn)依賴較新的算子。CUDA版本要和PyTorch匹配這個不用多說但有個坑是有些論文用了FlashAttention需要CUDA 11.6以上如果你的環(huán)境是11.3要么升級要么找替代實現(xiàn)。timm庫是個好東西里面集成了大量視覺Transformer的預(yù)訓練權(quán)重和實現(xiàn)速遞里很多工作的backbone都能在timm里找到對應(yīng)版本。我的習慣是先用timm里的現(xiàn)成模型跑通流程再根據(jù)論文細節(jié)做修改。這樣比從零寫快得多也不容易在基礎(chǔ)結(jié)構(gòu)上出錯。# 典型的環(huán)境安裝命令 conda create -n vit python3.9 conda activate vit pip install torch1.13.1cu117 torchvision0.14.1cu117 -f https://download.pytorch.org/whl/torch_stable.html pip install timm0.9.2 pip install einops # 很多Transformer實現(xiàn)用einops做張量操作einops這個庫值得單獨提一下它讓多頭注意力的維度變換寫起來非常清晰。比如把(batch, seq, dim)變成(batch, heads, seq, dim_per_head)用rearrange一行就搞定比permuteview的組合可讀性好太多。速遞里如果有論文的代碼用了einops讀起來會順暢很多。3.2 數(shù)據(jù)準備與預(yù)處理要點計算機視覺任務(wù)的數(shù)據(jù)預(yù)處理直接影響最終效果。以分類任務(wù)為例標準的流程是resize到固定尺寸、歸一化、可能加一些數(shù)據(jù)增強。但Transformer對輸入尺寸比較敏感因為位置編碼的維度跟序列長度綁定。如果你用預(yù)訓練權(quán)重輸入尺寸最好跟預(yù)訓練時一致否則位置編碼需要插值。我踩過的一個坑是用ViT的預(yù)訓練權(quán)重做遷移學習輸入尺寸從224改成384直接加載權(quán)重會報維度不匹配。解決辦法是對位置編碼做雙線性插值這個在timm里有現(xiàn)成的函數(shù)。速遞里如果論文聲稱支持任意輸入尺寸通常就是用了插值或者可學習的位置編碼。數(shù)據(jù)增強方面RandAugment和Mixup是Transformer訓練里的???。我實測下來RandAugment的強度參數(shù)需要根據(jù)數(shù)據(jù)集大小調(diào)小數(shù)據(jù)集用太強的增強反而掉點。Mixup的alpha值一般設(shè)0.8或1.0對分類任務(wù)比較穩(wěn)。3.3 模型搭建的核心代碼結(jié)構(gòu)以多頭自注意力為例核心代碼其實不復雜但細節(jié)決定成敗。下面是一個標準的實現(xiàn)框架import torch import torch.nn as nn from einops import rearrange class MultiHeadAttention(nn.Module): def __init__(self, dim, heads8, dropout0.1): super().__init__() self.heads heads self.scale (dim // heads) ** -0.5 self.qkv nn.Linear(dim, dim * 3) self.proj nn.Linear(dim, dim) self.dropout nn.Dropout(dropout) def forward(self, x): qkv self.qkv(x).chunk(3, dim-1) q, k, v map(lambda t: rearrange(t, b n (h d) - b h n d, hself.heads), qkv) attn torch.softmax(torch.einsum(b h i d, b h j d - b h i j, q, k) * self.scale, dim-1) attn self.dropout(attn) out torch.einsum(b h i j, b h j d - b h i d, attn, v) out rearrange(out, b h n d - b n (h d)) return self.proj(out)這段代碼里scale是縮放因子等于每個頭維度的平方根倒數(shù)。為什么要縮放因為點積的方差隨維度增長不縮放的話softmax會進入飽和區(qū)梯度消失。這個細節(jié)很多速遞里的論文不會提但實現(xiàn)時不能漏。位置編碼有兩種主流做法可學習的和正弦固定的。可學習的更靈活但需要足夠的數(shù)據(jù)才能學好正弦編碼不需要訓練外推性稍好。我一般分類任務(wù)用可學習的檢測任務(wù)用正弦的因為檢測的輸入尺寸變化多。3.4 訓練策略與調(diào)參經(jīng)驗Transformer的訓練比卷積網(wǎng)絡(luò)更吃數(shù)據(jù)和調(diào)參。學習率用AdamW初始值一般設(shè)1e-4到5e-4權(quán)重衰減0.05左右。warmup很重要前5到10個epoch線性升溫避免訓練初期不穩(wěn)定。batch size盡量大梯度累積可以模擬大batch。我實測下來ViT在小數(shù)據(jù)集上從頭訓練效果很差必須用預(yù)訓練權(quán)重。如果速遞里的論文聲稱在小數(shù)據(jù)集上從頭訓練取得了好效果要仔細看它是不是用了很強的正則化或者特殊的訓練技巧。常見的手段包括更強的數(shù)據(jù)增強、隨機深度、層縮放初始化。層縮放初始化這個技巧值得展開說——它把殘差分支的權(quán)重初始值設(shè)得很小讓網(wǎng)絡(luò)初始狀態(tài)接近恒等映射訓練更穩(wěn)定。這個在timm里是默認開啟的。提示如果你在復現(xiàn)速遞里的工作時發(fā)現(xiàn)loss不下降先檢查學習率和warmup再檢查位置編碼的加載方式最后檢查數(shù)據(jù)預(yù)處理是否跟論文一致。這三個地方是最常見的翻車點。4. 速遞里高頻出現(xiàn)的幾個方向與實操建議4.1 多模態(tài)融合Transformer的落地思路速遞里經(jīng)常出現(xiàn)多模態(tài)融合的工作比如遙感語義分割里的多層級多模態(tài)融合Transformer。這類工作的核心是把不同來源的數(shù)據(jù)比如光學圖像和SAR圖像用Transformer做特征交互。實操時的關(guān)鍵點是不同模態(tài)的特征維度和空間分辨率往往不一致需要先對齊再融合。我做過的一個項目里光學圖像是RGB三通道SAR是單通道分辨率也不一樣。做法是分別用兩個backbone提特征然后通過交叉注意力讓一個模態(tài)的token去查詢另一個模態(tài)的token。交叉注意力的計算量和token數(shù)量平方相關(guān)所以實際部署時要做token采樣或者窗口化。速遞里如果論文沒提計算量優(yōu)化落地時大概率要自己補。融合位置也有講究。早期融合在輸入層做簡單但靈活性差中期融合在特征層做最常用晚期融合在決策層做適合模態(tài)差異極大的情況。我的經(jīng)驗是遙感任務(wù)用中期融合比較多因為不同模態(tài)在特征層還有互補信息到了決策層信息已經(jīng)損失太多。4.2 動態(tài)長距離Transformer在時序相關(guān)任務(wù)中的應(yīng)用速遞里有一類工作專門處理時序相關(guān)的視覺任務(wù)比如交通流預(yù)測里的傳播延遲感知動態(tài)長距離Transformer。這類任務(wù)的特點是輸入不只是單幀圖像而是帶時間維度的序列。Transformer處理序列本來是強項但視覺序列的長度往往很大直接做全局注意力不現(xiàn)實。動態(tài)長距離注意力的思路是不是所有時間步之間都需要交互只對有關(guān)聯(lián)的時間步計算注意力。傳播延遲感知的意思是某個位置的交通狀態(tài)變化會延遲影響下游位置注意力機制要能捕捉這種延遲模式。實操時這類方法通常需要構(gòu)造一個延遲矩陣或者學習一個位置間的關(guān)聯(lián)圖。我在做類似任務(wù)時的體會是時間維度的下采樣比空間維度更敏感??臻g下采樣丟的是細節(jié)時間下采樣丟的是動態(tài)模式。所以如果速遞里的方法在時間維度做了激進的下采樣要警惕它是否損失了關(guān)鍵的時序信息。一個折中做法是用空洞卷積在時間維度擴大感受野同時保持分辨率。4.3 分類任務(wù)中Transformer的微調(diào)技巧分類是計算機視覺大作業(yè)里最常見的任務(wù)也是速遞里Transformer工作最集中的方向。用預(yù)訓練的ViT或Swin做微調(diào)有幾個實操技巧。第一分類頭要重新初始化backbone用較小的學習率分類頭用較大的學習率。第二如果目標數(shù)據(jù)集跟預(yù)訓練數(shù)據(jù)集差異大可以解凍最后幾個block一起微調(diào)差異小的話只調(diào)分類頭就夠了。第三測試時可以用多裁剪或者中心裁剪加翻轉(zhuǎn)做增強通常能漲0.5到1個點。我對比過幾種微調(diào)策略在小型數(shù)據(jù)集上的表現(xiàn)結(jié)果如下微調(diào)策略訓練時間準確率適用場景只調(diào)分類頭最短基準目標域與預(yù)訓練域接近調(diào)最后2個block分類頭中等1.5%目標域有中等差異全量微調(diào)最長2.5%數(shù)據(jù)量足夠差異大全量微調(diào)強增強最長3.0%數(shù)據(jù)量中等易過擬合這個表是我在幾個公開數(shù)據(jù)集上跑出來的經(jīng)驗值具體數(shù)字會隨數(shù)據(jù)集變化但趨勢是穩(wěn)定的。速遞里如果論文只報了全量微調(diào)的結(jié)果而你的數(shù)據(jù)量不夠不要硬套從只調(diào)分類頭開始試。5. 常見問題與排查技巧實錄5.1 訓練不收斂或loss震蕩這是復現(xiàn)Transformer時最常見的問題。排查順序我一般是這樣先看學習率是不是太大Transformer對學習率比卷積網(wǎng)絡(luò)敏感1e-3以上很容易震蕩再看warmup是不是太短前幾個epoch的梯度范數(shù)往往很大沒有warmup容易把預(yù)訓練權(quán)重帶偏然后看batch size和梯度累積的配置等效batch size太小會導致梯度噪聲大。還有一個容易被忽略的點是權(quán)重衰減的應(yīng)用范圍。LayerNorm的權(quán)重和偏置不應(yīng)該加權(quán)重衰減位置編碼也不應(yīng)該。如果統(tǒng)一加了訓練會不穩(wěn)定。這個細節(jié)在速遞里的論文中很少提但代碼里如果沒做區(qū)分效果會差。5.2 顯存不夠用的幾種解法Transformer的顯存占用主要來自注意力矩陣序列長度的平方級增長。顯存不夠時按優(yōu)先級嘗試以下方案第一減小batch size配合梯度累積第二用混合精度訓練torch.cuda.amp通常能省30%到40%顯存第三用梯度檢查點torch.utils.checkpoint用計算時間換顯存第四減小輸入分辨率或patch大小第五換用更高效的注意力實現(xiàn)比如FlashAttention。我實測下來混合精度加梯度檢查點能在單張24G卡上把ViT-Base的輸入分辨率從224推到384代價是訓練速度慢大概40%。如果速遞里的方法聲稱在單卡上訓練了高分辨率模型大概率用了這些技巧的組合。5.3 預(yù)訓練權(quán)重加載失敗的排查加載預(yù)訓練權(quán)重時報錯常見原因有幾個。鍵名不匹配是最多的比如預(yù)訓練模型用了backbone.blocks.0.attn.qkv你的模型用了encoder.layer.0.attention.query名字對不上。解決辦法是打印兩邊的state_dict鍵名寫個映射函數(shù)。維度不匹配通常出現(xiàn)在分類頭或者位置編碼上分類頭直接跳過加載位置編碼做插值。還有一個坑是DataParallel和DistributedDataParallel保存的權(quán)重鍵名會多一個module.前綴加載時要去掉。這個在單機多卡訓練后加載權(quán)重時經(jīng)常遇到。注意速遞里如果論文提供了預(yù)訓練權(quán)重先看它的加載腳本通常作者會處理這些細節(jié)。如果沒有腳本就按上面的順序排查。5.4 推理速度慢的優(yōu)化方向訓練完了要部署推理速度是下一個問題。Transformer的推理瓶頸通常在注意力計算和內(nèi)存訪問。優(yōu)化方向包括用ONNX或TensorRT導出做圖優(yōu)化把注意力換成FlashAttention的實現(xiàn)對token做剪枝或合并用知識蒸餾換小模型。我做過一個對比同一個Swin-T模型PyTorch原生推理、ONNX Runtime、TensorRT三種方式的延遲大概是1:0.7:0.4的關(guān)系。如果速遞里的方法強調(diào)實時性先看它有沒有做這些工程優(yōu)化沒有的話落地時自己補。6. 速遞閱讀與項目落地的銜接經(jīng)驗速遞看多了容易陷入一種狀態(tài)每天都在讀新論文但手上的項目沒什么進展。我的經(jīng)驗是速遞要帶著問題讀。比如你正在做分割任務(wù)就重點看分割相關(guān)的Transformer工作正在調(diào)分類模型就關(guān)注分類的微調(diào)技巧。沒有問題導向的閱讀信息留存率很低。另外速遞里的工作從論文到可用代碼通常有幾個月的時間差。如果某個方法你很感興趣但找不到代碼可以先去Papers with Code或者GitHub搜一下很多時候有第三方復現(xiàn)。第三方復現(xiàn)的質(zhì)量參差不齊但至少能幫你快速驗證想法。我自己在復現(xiàn)速遞里的工作時大概有三分之一的情況是直接用了第三方代碼省了大量時間。最后分享一個我自己的習慣每讀一篇速遞里的論文我會在筆記里記三行——它解決什么問題、核心方法是什么、我能不能用上。這個習慣堅持下來半年后回頭看能清楚看到自己的知識增長軌跡也能快速定位到之前讀過但當時沒用上的方法。計算機視覺這個方向變化快但核心問題的變化沒那么快抓住核心問題速遞里的新工作就只是不同的解法而已。