ViT微调只调对3个参数:timm里从90%爬到98%的完整路径
【免费下载链接】pytorch-image-modelsThe largest collection of PyTorch image encoders / backbones. Including train, eval, inference, export scripts, and pretrained weights -- ResNet, ResNeXT, EfficientNet, NFNet, Vision Transformer (ViT), MobileNetV4, MobileNet-V3 & V2, RegNet, DPN, CSPNet, Swin Transformer, MaxViT, CoAtNet, ConvNeXt, and more项目地址: https://gitcode.com/GitHub_Trending/py/pytorch-image-models
预训练ViT换个数据集,准确率直接从95%掉到85%?问题通常不在模型,而在微调时学习率、增强和正则化没配合好。本文基于 pytorch-image-models(timm)讲清楚微调的三个核心杠杆,帮你把掉下去的准确率重新拉回来。读完你将能够:
- 给ViT微调配出一套不冲掉预训练知识的学习率和余弦调度
- 用AutoAugment与随机擦除搭出适配下游任务的增强管线
- 通过EMA、DropPath和标签平滑压住过拟合
快速上手:环境与数据管线一次配齐
先把仓库拉下来装好依赖,timm自带从ResNet到ViT、Swin、ConvNeXt的完整骨干库,微调脚本和数据工具都在仓库根目录:
git clone https://gitcode.com/GitHub_Trending/py/pytorch-image-models cd pytorch-image-models pip install -r requirements.txt数据侧不用手写Dataset,create_dataset加create_loader两行就能产出带增强的训练批:
from timm.data import create_dataset, create_loader dataset = create_dataset(root='path/to/data', split='train', class_map='path/to/class_map.txt') loader = create_loader(dataset, input_size=(3, 224, 224), batch_size=32, is_training=True, augment=True)⚠️ 注意ViT默认用ImageNet的均值/标准差归一化,自定义数据若颜色分布差异大,建议单独核算这两个值,否则第一步就白跑。
杠杆一:学习率与余弦调度怎么定
现象:训练头几个epoch损失曲线剧烈震荡,甚至直接发散。原因:微调学习率开大了,梯度把预训练权重"冲"掉;同时缺少预热,第一步的更新量对随机初始化的分类头来说过于激进。
建议顺序:
- 学习率取5e-5到1e-4区间,越小越保守,分类头随机初始化时别一上来就用1e-4
- 权重衰减0.05左右,create_optimizer_v2会自动把bias和BN参数排除在衰减之外
- 余弦退火总轮数30轮左右,预热5轮,学习率最低衰减到1e-6
from timm.optim import create_optimizer_v2 from timm.scheduler import create_scheduler_v2 opt = create_optimizer_v2(model, opt='adamw', lr=5e-5, # 建议5e-5~1e-4 weight_decay=0.05) sched = create_scheduler_v2(opt, sched='cosine', num_epochs=30, warmup_epochs=5, min_lr=1e-6, warmup_lr=1e-6)📌 预热线性爬升、后半程余弦平滑下降的组合,是多数大规模视觉模型收敛最稳的形态,实现见timm/scheduler/scheduler_factory.py。
杠杆二:数据增强管线怎么搭
现象:验证集精度上不去、换几张相似图就翻车。原因:模型对背景、光照、遮挡过于敏感,训练时见的世界太"干净"。
增强策略不必从零调,直接选被反复验证过的预设即可:
rand-m9-mstd0.5-inc1:RandAugment,强度9、均值0.5,多数分类任务的首选- 颜色抖动0.4:轻微扰动即可,过大反而伤精度
- 随机擦除(Random Erasing):概率0.25、模式pixel,模拟前景被遮挡的情况,对ViT这类注意力模型尤其有效
- 插值用bicubic,与ViT预训练阶段保持一致
from timm.data import create_transform t = create_transform(input_size=(3, 224, 224), is_training=True, auto_augment='rand-m9-mstd0.5-inc1', color_jitter=0.4, re_prob=0.25, re_mode='pixel', interpolation='bicubic')若下游数据本身有强领域偏移(如医学影像、卫星图),建议再叠加领域内常用的几何变换,而不是继续堆强度。
杠杆三:正则化与模型EMA
现象:训练精度98%,验证精度只有92%。原因:模型死记了训练样本,泛化部分没练出来。
三层防线建议全开:
- DropPath(随机深度,训练时随机丢弃整个残差分支):在create_model里传
drop_path_rate=0.1~0.2,比全连接层Dropout更适配Transformer结构 - 标签平滑:0.1即可,阻止模型把置信度打到1.0
- 模型EMA:维护一份权重的指数滑动平均副本,验证和导出都用EMA权重,能显著平滑后期抖动
from timm.utils import ModelEmaV3 from timm.loss import LabelSmoothingCrossEntropy ema = ModelEmaV3(model, decay=0.9998) # decay建议0.9998~0.9999 criterion = LabelSmoothingCrossEntropy(smoothing=0.1) # 训练循环中每个batch后: ema.update(model)EMA实现见timm/utils/model_ema.py,完整训练流程可参考仓库根目录的train.py,其中梯度裁剪、AMP、EMA验证都是现成的。
避坑指南:微调路上最常踩的4个坑
| 问题现象 | 可能原因 | 可执行对策 |
|---|---|---|
| 过拟合,训练/验证精度差距越拉越大 | 正则化不足或数据太少 | drop_path_rate提到0.2;加增强;权重衰减上调到0.1;配早停(patience 5~10轮) |
| 损失曲线前期锯齿状抖动 | 学习率偏大或缺预热 | 学习率降到3e-5;warmup_epochs加到5~10;加clip_grad_norm_(model.parameters(), 1.0) |
| 精度长期平台期不动 | 学习率下限太高或轮数不够 | min_lr压到1e-6以下;总轮数延长1.5倍再观察 |
| 推理/验证太慢 | 全精度前向、未编译 | 用torch.cuda.amp.autocast()半精度推理;model = torch.compile(model);或换更小变体 |
小结与下一步
微调ViT本质上就是三件事:学习率调得稳(小lr+余弦+预热)、增强见得杂(RandAugment+随机擦除)、正则压得住(DropPath+标签平滑+EMA)。参数都有推荐区间,照着仓库脚本起步再微调即可。
想继续深挖,可以看这三个方向:
- 数据量充足时放开全部层微调,或给backbone与分类头分配不同学习率
- 用
torch.compile配合AMP把训练吞吐再提一档 - 尝试更大变体(如vit_large_patch16_224)或知识蒸馏压缩
你在微调中踩过哪个坑?欢迎在留言区说说你的配置和结果,互相参考。
【免费下载链接】pytorch-image-modelsThe largest collection of PyTorch image encoders / backbones. Including train, eval, inference, export scripts, and pretrained weights -- ResNet, ResNeXT, EfficientNet, NFNet, Vision Transformer (ViT), MobileNetV4, MobileNet-V3 & V2, RegNet, DPN, CSPNet, Swin Transformer, MaxViT, CoAtNet, ConvNeXt, and more项目地址: https://gitcode.com/GitHub_Trending/py/pytorch-image-models
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考