實(shí)戰(zhàn):PyTorch預(yù)訓(xùn)練模型微調(diào)與避坑指南)
簡(jiǎn)介這是一份基于 PyTorch 的 Vision TransformerViT實(shí)現(xiàn)面向深度學(xué)習(xí)研究者與工程師提供從原始 JAX/Flax 權(quán)重轉(zhuǎn)換而來(lái)的預(yù)訓(xùn)練模型可直接用于圖像分類(lèi)、特征提取以及下游任務(wù)微調(diào)。壓縮包約 173KB共 35 個(gè)文件其中以 22 個(gè) Python 源碼為主涵蓋模型定義、訓(xùn)練、評(píng)估、數(shù)據(jù)加載與配置管理另有 README、Markdown 說(shuō)明、requirements 環(huán)境文件、YAML 配置及 Notebook 示例等目錄結(jié)構(gòu)清晰便于二次開(kāi)發(fā)。資源描述了與原始模型相當(dāng)?shù)慕Y(jié)果支持 ImageNet2012 等數(shù)據(jù)集并附帶微調(diào)與評(píng)估腳本適合有一定 PyTorch 基礎(chǔ)、希望快速?gòu)?fù)現(xiàn) ViT 論文或?qū)⑵鋺?yīng)用于自身視覺(jué)任務(wù)的開(kāi)發(fā)者。已有 7800 余人瀏覽學(xué)習(xí)是入門(mén) Vision Transformer 并獲取可用預(yù)訓(xùn)練權(quán)重的實(shí)用參考。 我做視覺(jué)這兩年最常用的框架就是PyTorch而ViT相關(guān)的項(xiàng)目里vision-transformer-pytorch這個(gè)庫(kù)我?guī)缀跏欠磸?fù)在用。很多朋友第一次接觸Vision TransformerViT時(shí)被論文里一堆概念唬住總覺(jué)得這是個(gè)很復(fù)雜的模型。但如果你上手跑一遍這個(gè)庫(kù)會(huì)發(fā)現(xiàn)ViT的思路其實(shí)非常直接把圖像切成小塊當(dāng)成一串“視覺(jué)單詞”送給Transformer去處理。而且這個(gè)項(xiàng)目坐標(biāo)很明確——Pytorch 預(yù)訓(xùn)練模型正好是現(xiàn)在視覺(jué)任務(wù)落地最常用的一套組合。這個(gè)項(xiàng)目解決的核心問(wèn)題就是讓大家不用重復(fù)造輪子。它提供了完整的ViT模型實(shí)現(xiàn)結(jié)構(gòu)清晰、參數(shù)可調(diào)并且可以配合預(yù)訓(xùn)練權(quán)重直接使用。對(duì)我個(gè)人來(lái)說(shuō)它最大的價(jià)值在于既能幫新手理解ViT內(nèi)部到底發(fā)生了什么也能讓有經(jīng)驗(yàn)的工程師在幾行代碼內(nèi)完成模型搭建和遷移學(xué)習(xí)。無(wú)論你是打算做圖像分類(lèi)還是把ViT當(dāng)作骨干網(wǎng)絡(luò)接進(jìn)檢測(cè)分割框架這篇文章都適用。1. ViT模型為什么值得關(guān)注從CNN到Transformer的范式轉(zhuǎn)移1.1 圖像能否直接當(dāng)序列處理在ViT出現(xiàn)之前視覺(jué)模型幾乎被卷積神經(jīng)網(wǎng)絡(luò)CNN統(tǒng)治。CNN的核心假設(shè)是局部性和平移不變性相鄰像素關(guān)系更密切同一個(gè)卷積核在整張圖上滑動(dòng)。這個(gè)假設(shè)在ImageNet這類(lèi)中大規(guī)模數(shù)據(jù)集上非常好用因?yàn)榫矸e天然帶有先驗(yàn)不需要太多數(shù)據(jù)就能學(xué)會(huì)。但Transformer的想法完全不同。它最初在NLP里證明了一件事只要數(shù)據(jù)足夠多你不給模型任何結(jié)構(gòu)先驗(yàn)讓注意力機(jī)制自己去找全局關(guān)系效果反而可能更好。于是就有了一個(gè)自然的問(wèn)題圖像能不能也當(dāng)成一個(gè)token序列來(lái)處理ViT回答這個(gè)問(wèn)題的方式很直接——把圖像切成固定大小的patch每個(gè)patch線性映射成一個(gè)向量再按順序拼起來(lái)當(dāng)作一個(gè)“句子”來(lái)處理。我最早看到這個(gè)思路的時(shí)候也挺驚訝整個(gè)ViT居然沒(méi)有一個(gè)卷積層全靠自注意力在建模。也正是這種極簡(jiǎn)讓它在超大數(shù)據(jù)集上表現(xiàn)驚人。論文里用JFT-300M這種量級(jí)的數(shù)據(jù)集做完預(yù)訓(xùn)練之后ViT在ImageNet上的精度能超過(guò)同等規(guī)模的ResNet和EfficientNet。所以它不是換了個(gè)結(jié)構(gòu)而是換了一種視覺(jué)建模的范式。1.2 vision-transformer-pytorch解決的三個(gè)實(shí)際問(wèn)題用這個(gè)庫(kù)一年多我感受到的突出價(jià)值有三點(diǎn)。第一實(shí)現(xiàn)與論文高度對(duì)齊可讀性強(qiáng)。它不是把ViT封裝成黑盒而是把patch embedding、transformer encoder、分類(lèi)頭拆成模塊改哪里都一目了然。我在對(duì)比不同層數(shù)、不同head數(shù)量對(duì)精度影響的時(shí)候基本就是改幾個(gè)參數(shù)的事。第二原生PyTorch生態(tài)無(wú)縫銜接。庫(kù)本身不依賴(lài)timm或者更上層的框架直接就能和你自己的訓(xùn)練管線集成。我經(jīng)常需要把ViT輸出的特征接給檢測(cè)頭或者分割頭這個(gè)庫(kù)的數(shù)據(jù)流非常透明改起來(lái)很順手。第三社區(qū)認(rèn)可度高坑少。這個(gè)項(xiàng)目在GitHub上star量很大用的人多意味著踩坑經(jīng)驗(yàn)多。比如位置編碼的維度問(wèn)題、patch size選擇問(wèn)題網(wǎng)上一搜就有很多討論遇到bug不至于孤立無(wú)援。對(duì)做工程和做研究的人來(lái)說(shuō)這種成熟度很重要。2. 核心架構(gòu)拆解ViT到底在做什么2.1 Patch Embedding圖像是如何變成Token序列的ViT最核心的一個(gè)操作就是Patch Embedding。以最常見(jiàn)的ViT-B/16為例輸入是224x224的RGB圖像patch_size設(shè)為16那么圖像會(huì)被劃分成(224/16)(224/16)1414196個(gè)patch。每個(gè)patch大小為16x16x3把它展平成長(zhǎng)度為768的向量再經(jīng)過(guò)一個(gè)線性投影層映射到768維的embedding空間。很多人第一次看會(huì)疑惑為什么不直接展平再用全連接其實(shí)這里的線性投影本質(zhì)就是一個(gè)1x1卷積或者一個(gè)reshape加Linear它的作用是讓每個(gè)patch的原始像素映射到更適合Transformer處理的語(yǔ)義空間。實(shí)際操作中很多實(shí)現(xiàn)直接用nn.Conv2d(in_channels3, out_channelsdim, kernel_sizepatch_size, stridepatch_size)來(lái)一步完成切patch和投影效率更高。這也是為什么你會(huì)看到有些代碼里Patch Embedding層長(zhǎng)得像卷積層但它做的事情其實(shí)就是“切塊線性變換”。這里我想強(qiáng)調(diào)一個(gè)點(diǎn)patch size的選擇直接影響序列長(zhǎng)度。patch越小序列越長(zhǎng)計(jì)算量越大但細(xì)節(jié)保留越多。ViT-B/32用32的patch序列長(zhǎng)度只有491個(gè)token速度快很多但精度略降。實(shí)際工程里如果顯存有限又不想掉太多精度可以考慮用大patch或者保持patch不變減少層數(shù)。2.2 位置編碼、CLS Token與Transformer Encoderpatch被映射成token之后接下來(lái)的問(wèn)題很關(guān)鍵Transformer本身是順序無(wú)關(guān)的它不知道哪個(gè)token在圖像的哪個(gè)位置。ViT的做法是加一個(gè)1D可學(xué)習(xí)的位置編碼向量直接加到所有token的embedding上。這里沒(méi)有用NLP里常見(jiàn)的2D位置編碼因?yàn)檎撐膶?shí)驗(yàn)發(fā)現(xiàn)1D可學(xué)習(xí)編碼對(duì)效果影響不大但實(shí)現(xiàn)更簡(jiǎn)單。ViT還在序列最前面插入了一個(gè)特殊的CLS token它的作用和BERT里的CLS一樣用于匯聚全局信息。在Transformer編碼若干層之后模型拿出CLS token對(duì)應(yīng)的輸出向量接一個(gè)分類(lèi)頭完成最終分類(lèi)。我實(shí)際中還見(jiàn)過(guò)一些改造方案比如直接對(duì)所有token做全局平均池化再分類(lèi)效果有時(shí)也不差但標(biāo)準(zhǔn)ViT用的是CLS token方案。接下來(lái)是Transformer Encoder。以ViT-Base為例包含12層Encoder每層由多頭自注意力12個(gè)head、MLPhidden size從768擴(kuò)展到3072再降回來(lái)、LayerNorm和殘差連接組成。值得注意的是ViT用的是Pre-LayerNorm結(jié)構(gòu)也就是每個(gè)子層注意力或MLP之前先做歸一化。這個(gè)細(xì)節(jié)影響穩(wěn)定性訓(xùn)練大模型時(shí)尤其明顯。我自己的經(jīng)驗(yàn)是這種設(shè)計(jì)配合較大的學(xué)習(xí)率也能保持穩(wěn)定微調(diào)時(shí)不容易崩。2.3 模型規(guī)格怎么選Base、Large與HugeViT官方發(fā)布了幾個(gè)規(guī)格Base86M參數(shù)、Large307M參數(shù)、Huge632M參數(shù)。視覺(jué)任務(wù)里用最多的就是Base它和ResNet50規(guī)模差不多但效果更好。如果資源充足、任務(wù)復(fù)雜Large往往能帶來(lái)明顯提升Huge則適合在超大數(shù)據(jù)集上從頭訓(xùn)練一般做遷移學(xué)習(xí)的用不起。我選型時(shí)通常會(huì)先想清楚數(shù)據(jù)集規(guī)模。數(shù)據(jù)集只有幾千張圖直接用Base甚至Small版本配合在ImageNet上預(yù)訓(xùn)練的權(quán)重效果往往比從零訓(xùn)練要穩(wěn)得多。所以這里就引出了下一部分的重點(diǎn)預(yù)訓(xùn)練模型到底怎么選、怎么用。3. 預(yù)訓(xùn)練模型的選擇與微調(diào)實(shí)戰(zhàn)思路3.1 三種獲取預(yù)訓(xùn)練權(quán)重的方式對(duì)比標(biāo)題里特別提到了“帶有預(yù)訓(xùn)練模型”這一點(diǎn)其實(shí)是很多人最關(guān)心的。vision-transformer-pytorch庫(kù)本身側(cè)重于提供模型結(jié)構(gòu)而預(yù)訓(xùn)練權(quán)重通常可以從下面三個(gè)渠道獲取獲取渠道是否攜帶官方預(yù)訓(xùn)練權(quán)重適用場(chǎng)景vit-pytorch庫(kù)否只提供模型結(jié)構(gòu)學(xué)習(xí)結(jié)構(gòu)、自定義改造timm是ImageNet預(yù)訓(xùn)練權(quán)重日常分類(lèi)、工程落地HuggingFace transformers是Google官方權(quán)重研究復(fù)現(xiàn)、需要官方預(yù)處理我個(gè)人的建議是追求簡(jiǎn)單就直接用timm一行代碼搞定下載和加載追求跟原論文對(duì)齊就去HuggingFace。用timm加載預(yù)訓(xùn)練權(quán)重的方法非常直接import timm model timm.create_model(vit_base_patch16_224, pretrainedTrue, num_classes1000) model.eval()如果你要做的分類(lèi)任務(wù)類(lèi)別數(shù)不是1000可以直接在create_model時(shí)指定num_classestimm會(huì)自動(dòng)把最后的分類(lèi)頭替換成對(duì)應(yīng)數(shù)量微調(diào)時(shí)非常省事。另外timm還提供了豐富的數(shù)據(jù)增強(qiáng)策略、EMA等訓(xùn)練工具對(duì)訓(xùn)練精度的提升很友好。如果你更希望復(fù)現(xiàn)原論文的預(yù)處理流程可以用HuggingFace的transformersfrom transformers import ViTForImageClassification, ViTImageProcessor model ViTForImageClassification.from_pretrained(google/vit-base-patch16-224) processor ViTImageProcessor.from_pretrained(google/vit-base-patch16-224)這里的processor封裝了標(biāo)準(zhǔn)化和尺寸調(diào)整邏輯拿過(guò)來(lái)就能用不用自己糾結(jié)normalize參數(shù)。不過(guò)要注意transformers加載這種大權(quán)重時(shí)會(huì)從HuggingFace服務(wù)器下載雖然大部分時(shí)候沒(méi)問(wèn)題但偶爾會(huì)卡住這時(shí)候可以設(shè)置環(huán)境變量HF_ENDPOINThttps://hf-mirror.com用國(guó)內(nèi)鏡像加速下載。注意預(yù)訓(xùn)練權(quán)重的下載只是第一步真正決定模型效果的是后續(xù)微調(diào)策略。3.2 微調(diào)策略?xún)鼋Y(jié)層、學(xué)習(xí)率與數(shù)據(jù)規(guī)模拿到預(yù)訓(xùn)練模型后第一個(gè)選擇就是凍結(jié)還是不凍結(jié)。如果數(shù)據(jù)集比較小、只有幾千張我建議凍結(jié)前11層Encoder只微調(diào)最后一層和分類(lèi)頭。實(shí)操中Encoder底層學(xué)習(xí)到的都是一些基礎(chǔ)紋理、邊緣特征這些對(duì)于任何視覺(jué)任務(wù)都是通用的不需要重新學(xué)。凍結(jié)之后可以大幅減少顯存占用和訓(xùn)練時(shí)間加快收斂。如果數(shù)據(jù)集中等幾萬(wàn)張或者目標(biāo)域和ImageNet差異很大比如醫(yī)學(xué)影像、衛(wèi)星圖我建議全部微調(diào)但把學(xué)習(xí)率調(diào)低一些。常規(guī)的做法是整體學(xué)習(xí)率設(shè)0.0001左右分類(lèi)頭學(xué)習(xí)率可以稍微放大到0.001。ViT對(duì)學(xué)習(xí)率比較敏感一開(kāi)始就用太大學(xué)習(xí)率很容易出現(xiàn)loss震蕩甚至不收斂。另外一個(gè)小技巧是如果顯存允許可以先把模型在較大分辨率如384x384上微調(diào)幾輪效果通常會(huì)比224更好。因?yàn)閂iT沒(méi)有卷積的局部先驗(yàn)更大分辨率意味著更多patch更多細(xì)節(jié)。代價(jià)就是序列長(zhǎng)度變長(zhǎng)顯存和速度都翻幾倍。我自己做細(xì)粒度分類(lèi)時(shí)這個(gè)技巧帶來(lái)的精度提升很明顯。4. 實(shí)操記錄從安裝到自定義數(shù)據(jù)集微調(diào)4.1 環(huán)境準(zhǔn)備和安裝先說(shuō)我實(shí)測(cè)過(guò)的環(huán)境組合Python 3.10PyTorch 2.1以上CUDA 11.8顯卡是RTX 3090。PyTorch的安裝直接用官方命令就行如果下載慢可以把pip源換成清華源或者阿里源。裝完之后裝依賴(lài)pip install torch torchvision timm pip install vit-pytorch后面這個(gè)vit_pytorch就是lucidrains的版本也是很多博客里提到的vision-transformer-pytorch的PyTorch實(shí)現(xiàn)。不過(guò)我想特別提醒一句vit_pytorch這個(gè)包默認(rèn)不攜帶預(yù)訓(xùn)練權(quán)重它的作用是快速構(gòu)建模型結(jié)構(gòu)你想直接跑預(yù)訓(xùn)練推理還是要配合timm或者transformers。很多人一開(kāi)始沒(méi)搞清楚這點(diǎn)裝了個(gè)vit-pytorch然后發(fā)現(xiàn)模型是隨機(jī)初始化的以為庫(kù)有問(wèn)題。4.2 快速推理用預(yù)訓(xùn)練權(quán)重分類(lèi)一張圖下面這段代碼是我在項(xiàng)目里驗(yàn)證一張新圖時(shí)常用的模板基于timm實(shí)現(xiàn)簡(jiǎn)單可靠import torch import timm from PIL import Image from torchvision import transforms device torch.device(cuda if torch.cuda.is_available() else cpu) model timm.create_model(vit_base_patch16_224, pretrainedTrue) model model.to(device) model.eval() transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ]) img Image.open(test.jpg).convert(RGB) x transform(img).unsqueeze(0).to(device) with torch.no_grad(): out model(x) prob torch.softmax(out, dim1) top5 torch.topk(prob, 5)輸出top5之后去查一下ImageNet的類(lèi)別索引表就能知道模型預(yù)測(cè)的是什么類(lèi)。這里最常踩的坑有兩個(gè)一是忘了convert(RGB)導(dǎo)致灰度圖或RGBA圖報(bào)錯(cuò)二是忘了加batch維度unsqueeze(0)少寫(xiě)就報(bào)維度錯(cuò)誤。我剛開(kāi)始跑的時(shí)候就在這兩處浪費(fèi)過(guò)時(shí)間。4.3 自定義數(shù)據(jù)集微調(diào)假設(shè)現(xiàn)在你有一個(gè)10類(lèi)的自定義數(shù)據(jù)集目錄結(jié)構(gòu)大概是train/class1、train/class2這樣。用torchvision的ImageFolder讀進(jìn)來(lái)然后替換最后的分類(lèi)頭就可以開(kāi)始微調(diào)import torch import torch.nn as nn import timm from torchvision import datasets, transforms from torch.utils.data import DataLoader model timm.create_model(vit_base_patch16_224, pretrainedTrue, num_classes10) model.to(device) train_transform transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]), ]) train_ds datasets.ImageFolder(train, transformtrain_transform) train_loader DataLoader(train_ds, batch_size32, shuffleTrue, num_workers4) optimizer torch.optim.AdamW(model.parameters(), lr1e-4, weight_decay0.05) criterion nn.CrossEntropyLoss() for epoch in range(10): model.train() for x, y in train_loader: x, y x.to(device), y.to(device) loss criterion(model(x), y) optimizer.zero_grad() loss.backward() optimizer.step() print(fepoch {epoch}, loss {loss.item():.4f})這段代碼只是最基礎(chǔ)的訓(xùn)練循環(huán)。實(shí)際項(xiàng)目里我還會(huì)加warmup、余弦退火、Mixup和數(shù)據(jù)增強(qiáng)。ViT在中小數(shù)據(jù)集上容易過(guò)擬合所以增強(qiáng)策略比CNN時(shí)代更講究。還有一個(gè)細(xì)節(jié)AdamW的weight_decay我習(xí)慣設(shè)0.05這是從DeiT論文里來(lái)的經(jīng)驗(yàn)值實(shí)測(cè)比0.01穩(wěn)定。5. 避坑指南使用ViT時(shí)最容易踩的坑5.1 輸入尺寸和歸一化必須匹配ViT模型對(duì)輸入尺寸非常敏感這一點(diǎn)比CNN嚴(yán)格得多。timm里的vit_base_patch16_224要求輸入224x224如果你給它喂512x512的圖patch數(shù)量就變了位置編碼的維度對(duì)不上通常運(yùn)行到模型內(nèi)部就會(huì)直接報(bào)維度不匹配的錯(cuò)誤。我的建議是把預(yù)處理統(tǒng)一封裝成一個(gè)函數(shù)Resize到224歸一化參數(shù)就用ImageNet默認(rèn)的mean和std不要自己隨便改。另外一旦換了數(shù)據(jù)集別忘了重新檢查normalize參數(shù)是否匹配——尤其是醫(yī)學(xué)圖像或者紅外圖像它們的像素分布和自然圖像差別很大。5.2 預(yù)訓(xùn)練權(quán)重下載失敗怎么辦這個(gè)問(wèn)題在HuggingFace的權(quán)重上尤其常見(jiàn)。下載到一半斷掉、網(wǎng)絡(luò)超時(shí)、緩存損壞都會(huì)導(dǎo)致無(wú)法加載。我遇到這種情況一般分兩步排查先看報(bào)錯(cuò)是不是SSL或者超時(shí)如果是就說(shuō)明是網(wǎng)絡(luò)問(wèn)題可以設(shè)置HF_ENDPOINThttps://hf-mirror.com再重新拉取如果報(bào)錯(cuò)是鍵名不匹配那大概率是模型結(jié)構(gòu)定義和權(quán)重來(lái)源版本不一致比如用了patch16的定義去加載patch32的權(quán)重。權(quán)重和模型結(jié)構(gòu)的匹配相當(dāng)重要。提示HuggingFace的緩存目錄通常在~/.cache/huggingface刪掉對(duì)應(yīng)模型的緩存再重新下載可以解決很多奇怪的加載問(wèn)題。下載慢但沒(méi)報(bào)錯(cuò)時(shí)多試幾次或者手動(dòng)下載后放到緩存目錄也行。5.3 顯存不夠用先別急著換顯卡ViT雖然參數(shù)不算特別多但自注意力的計(jì)算復(fù)雜度是序列長(zhǎng)度的平方。224分辨率下197個(gè)token還好一旦輸入到448x448token數(shù)變成(448/16)^21785計(jì)算量增長(zhǎng)非常明顯。如果顯存爆了最直接的思路是減小batch size或者把patch_size從16改成32。還有一個(gè)實(shí)用技巧是開(kāi)啟梯度累積用多個(gè)小batch累加梯度模擬大batch效果能接近但省顯存。訓(xùn)練速度慢的話優(yōu)先檢查是不是數(shù)據(jù)加載瓶頸。num_workers調(diào)大或者用pin_memoryTrue經(jīng)常能把GPU利用率拉滿。我見(jiàn)過(guò)很多新人把num_workers默認(rèn)0跑GPU利用率低得可憐改到4或8之后速度立竿見(jiàn)影。相比一上來(lái)就換卡這招劃算得多。5.4 位置編碼與輸入分辨率不匹配如果你想在384x384或更大的分辨率上微調(diào)直接用vit_base_patch16_224的權(quán)重會(huì)報(bào)位置編碼維度不匹配。因?yàn)轭A(yù)訓(xùn)練權(quán)重的position embedding是1x197x768而384x384對(duì)應(yīng)的是1x577x768。解決辦法是插值調(diào)整位置編碼的尺寸。timm里有些版本支持img_size參數(shù)或者在create_model時(shí)指定img_size384但不是所有實(shí)現(xiàn)都自動(dòng)處理。如果要手動(dòng)插值可以這樣import torch from vit_pytorch import ViT model ViT(...) pos_embed model.pos_embedding # 形狀 [1, 197, 768] new_pos_embed torch.nn.functional.interpolate( pos_embed.permute(0, 2, 1).unsqueeze(0), size(577,), modelinear, align_cornersFalse, ).squeeze(0).permute(0, 2, 1) model.pos_embedding torch.nn.Parameter(new_pos_embed)不過(guò)說(shuō)實(shí)話如果只是做普通分類(lèi)任務(wù)我不建議手動(dòng)插值直接用timm里帶384后綴的模型比如vit_base_patch16_384會(huì)省心很多位置編碼部分timm已經(jīng)處理好了。把上面這些坑都踩過(guò)一遍之后我對(duì)ViT的理解反而更深了。說(shuō)實(shí)話ViT的門(mén)檻并不在模型本身而在于各種細(xì)節(jié)patch怎么切、位置編碼怎么處理、預(yù)訓(xùn)練權(quán)重怎么融合、微調(diào)參數(shù)怎么調(diào)。把這些細(xì)節(jié)弄明白它就是非常趁手的視覺(jué)骨干網(wǎng)絡(luò)。如果你剛開(kāi)始接觸ViT我的建議是先按著代碼把模型結(jié)構(gòu)打印出來(lái)一個(gè)個(gè)模塊核對(duì)再跑通預(yù)訓(xùn)練推理最后再上自己的數(shù)據(jù)。這個(gè)過(guò)程走一遍比干啃論文有用得多。最后分享一個(gè)我自己的習(xí)慣任何新項(xiàng)目要采用ViT我都會(huì)先用Base模型加ImageNet預(yù)訓(xùn)練跑一個(gè)baseline確認(rèn)任務(wù)可行之后再根據(jù)顯存和精度需求決定要不要換Large或者調(diào)分辨率。不要一開(kāi)始就上大模型否則調(diào)參和排錯(cuò)的成本會(huì)高到讓你懷疑人生。希望這篇內(nèi)容對(duì)你有幫助有問(wèn)題歡迎留言交流。本文還有配套的精品資源點(diǎn)擊獲取