ViT微调实战指南:pytorch-image-models 中 Vision Transformer 小数据集微调的完整调参清单
ViT微调实战指南pytorch-image-models 中 Vision Transformer 小数据集微调的完整调参清单【免费下载链接】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先说一个很多新手都会撞上的场面你把 ImageNet 上预训练好的 ViT 直接换成自己的分类头拿去跑自己的数据集验证集准确率稳稳卡在某个数字上——再跑几轮纹丝不动。训练 loss 一路往下掉验证 loss 却开始爬曲线像两个人在吵架。问题通常不在模型而在微调的配套动作没做。pytorch-image-models也就是 timm里的 Vision Transformer 实现位于 timm/models/vision_transformer.py它给了你完整的模型骨架而学习率怎么退、数据怎么搅、权重怎么稳仓库里也都有现成工具——只是没人把它们串成一条线。这篇指南就干这件事给你一套可直接落地的 ViT 微调决策流程从先判断该动多少层到怎么算调好了一次讲完。学完能拿到手的东西一眼判断自己的数据量该走哪种微调档位一套不会崩的小学习率 预热 余弦衰减组合配置数据增强和随机擦除的开关取舍以及归一化这个最容易忽略的坑EMA、标签平滑、DropPath 三件套各自救什么火什么时候该上一个最小可跑的训练循环加上什么时候该停的判断标准先判断——微调的三选一⚠️ 先别急着调参。打开训练脚本之前先回答一个问题你的数据有多少张数据量决定了你该动多少层。ViT 的编码器是叠了很多层的注意力块实现在 timm/models/vision_transformer.py层与层之间学到的东西差别很大——浅层偏通用纹理深层偏语义。动得多学得快但也容易把预训练权重搅坏动得少稳但上限低。按下面的档位选你的数据量建议策略理由几百到一两千张只微调分类头 最后 1~2 个 Transformer 块数据撑不起全模型先让头学会说什么再慢慢放开身体几千到几万张全参数微调配 DropPath 和更强正则数据够多了放开全模型收益最大大规模接近预训练规模从头训练或全参微调 强增强这时预训练权重只是个好起点不是拐杖一个常见误区数据少却把全模型都打开调学习率还给得偏大——结果预训练权重前 100 步就被冲掉了。所以先判断动多少层比任何超参都优先。学习率这条线——小学习率 预热 余弦怎么配成一套微调预训练 ViT 的第一铁律学习率要比从头训练小一到两个数量级。从头训练 ViT 常用 1e-3 左右微调时你从 5e-5 到 1e-4 这个区间起手就够了。给大了预训练知识会像被橡皮擦掉一样几个 epoch 就白搭。调度器这边timm/scheduler/scheduler_factory.py 里的create_scheduler_v2支持余弦、tanh、阶梯等多种曲线。微调推荐余弦这一套原因是它把两件事合成了一条线开头有一段低学习率的热身让新换上的分类头先稳下来之后按余弦曲线慢慢降到地板。from timm.scheduler import create_scheduler_v2 # 30 轮总长前 3 轮热身热身后从 1e-5 爬到峰值再按余弦回落到 1e-6 sched, total_epochs create_scheduler_v2( optimizer, schedcosine, # 余弦衰减曲线 num_epochs30, warmup_epochs3, # 热身轮数头几轮小步慢走防止新头被大梯度掀翻 warmup_lr1e-5, # 热身起点 min_lr1e-6, # 余弦回落的地板别设成 0收尾阶段还能微调 )三个数字的记忆法warmup_epochs约为总轮数的 10%warmup_lr约为峰值学习率的 1/5min_lr约为峰值的 1/50。改数据量和模型规模时按这个比例缩放基本不会出错。数据这一端——增强、随机擦除、归一化的取舍数据侧三件事几何颜色增强、随机擦除、归一化。前三件里归一化最容易翻车。归一化要匹配预训练。ImageNet 预训练的 ViT 在训练时见过的是均值/标准差归一化后的图timm 的create_transform默认就按 ImageNet 统计量处理见 timm/data/transforms_factory.py。如果你自己的流水线里换了别的均值或者干脆没归一化模型等于戴着一副错配的老花镜看新图准确率会莫名偏低且难排查。增强强度按数据量反着来数据越少增强越要狠一点数据多就收敛些。from timm.data import create_transform # 训练用的变换随机裁剪翻转打底auto_augment 做几何/颜色扰动 # re_prob0.25 是随机擦除随机抹掉一块区域逼模型别靠单点特征认东西 train_tf create_transform( input_size(3, 224, 224), is_trainingTrue, auto_augmentrand-m9-mstd0.5-inc1, # RandAugment 配置串可换其他策略 interpolationbicubic, re_prob0.25, # 四分之一概率擦除一块 re_modepixel, # 用随机像素填比填灰度值更难猜 re_count1, )验证集这边原则相反只缩放、只居中裁剪不做任何随机化。增强只做在训练侧验证侧一沾随机你的指标就不可信了。稳定器——EMA、标签平滑、DropPath 各自救的是哪个问题三个常被混用的正则手段其实各管一摊EMA权重指数滑动平均训练中每一步都留一份历史平均版权重验证和部署用它。它救的是震荡——小数据微调时单步梯度噪声大EMA 把毛刺磨平通常能白捡 0.5~1 个点。工具在 timm/utils/model_ema.py。标签平滑把100% 是猫的标签软化成99% 是猫1% 摊给其他类。它救的是过度自信让模型输出别贴死泛化更稳。DropPath前向时按概率整条随机丢弃残差分支。它救的是过拟合层数深的 ViT 尤其需要因为它限制模型对单条通路的依赖。from timm.utils import ModelEmaV3 from timm.loss import LabelSmoothingCrossEntropy ema ModelEmaV3( model, decay0.9999, # 训练总步数少就调低如 0.999步数多保持 0.9999 devicecuda, foreachTrue, # 批量更新更快 ) # 平滑系数 0.1 是常用值100 类任务里1% 的不确定度摊到 99 个其他类上 loss_fn LabelSmoothingCrossEntropy(smoothing0.1)DropPath 则在建模时就指定不用训练期干预import timm model timm.create_model( vit_base_patch16_224, pretrainedTrue, num_classes10, drop_path_rate0.1, # 数据量小调 0.1 起步过拟合明显再加到 0.2~0.3 )一个顺序上的坑DropPath、标签平滑在建模/建 loss 时就定了EMA 是训练循环里持续更新的。三者互相独立别指望调 EMA 衰减系数去补 DropPath 没设够。跑起来——最小可运行流程 怎么算调好了把前面几段拼成最小闭环。优化器用 AdamW权重衰减 0.05bias 和归一化层参数不衰减create_optimizer_v2默认就会这么分组见 timm/optim/_optim_factory.pyfrom timm.optim import create_optimizer_v2 from torch.nn import functional as F optimizer create_optimizer_v2( model, optadamw, lr1e-4, # 微调峰值学习率 weight_decay0.05, ) for epoch in range(total_epochs): model.train() for x, y in train_loader: x, y x.cuda(non_blockingTrue), y.cuda(non_blockingTrue) logit model(x) loss loss_fn(logit, y) # 标签平滑已包含在 loss_fn 里 optimizer.zero_grad(set_to_noneTrue) loss.backward() optimizer.step() sched.step_update(num_examplesx.shape[0]) # 按样本推进调度 ema.update(model) # 每步刷新 EMA 权重怎么算调好了别看训练 loss只看验证集。两个信号验证 top-1 连续 5 轮不再涨 → 停取 EMA 权重的最近最优。训练 loss 和验证 loss 的差距每轮都在拉大 → 过拟合进行中进下一节的急救表。另外提醒一句验证和导出权重时用ema.module不是model——EMA 那份才是你真正打磨出来的模型。完整工程化流程分布式、断点续训、日志可参考 train.py。翻车急救表症状可能的原因直接能用的对策过拟合训练好、验证差数据少而模型全放开①drop_path_rate提到 0.2~0.3② 换只调头尾部块档位③ 增强再狠一档不收敛loss 不动或乱跳学习率失配① 峰值 LR 降到 3e-5② 确认预热段存在且warmup_lr不是 0③ 加梯度裁剪torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)准确率莫名偏低且稳定归一化不匹配① 确认用了 ImageNet 均值/标准差② 确认输入通道顺序是 RGB 而不是 BGR推理慢精度和编译没开① 半精度推理torch.amp.autocast②torch.compile(model)③ 换更小的变体如 patch32/384 以下的尺寸 排查顺序建议先归一化再学习率最后才动正则。多数玄学掉点都出在前两步。还能往哪走更大更强的变体仓库里从 tiny 到 large、patch16 到 patch32 的 ViT 系列都有注册数据够就多试试尺寸上限。混合精度训练torch.amp包住训练循环显存和速度都赚微调场景几乎无损。层衰减create_optimizer_v2支持layer_decay参数给深层更低的学习率长序列模型上效果不错。蒸馏用大模型输出当软标签带小模型小数据场景收益明显timm/task/ 里有现成的蒸馏组件。微调 ViT 没有银弹但上面这套先定档位、再配调度、后上稳定器的顺序能帮你把大多数掉点场景挡在门外。按清单走完一遍你的验证曲线会诚实得多。【免费下载链接】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),仅供参考