
BEiT 图像分类实战指南在 unilm/beit 中用 ImageNet-22k 预训练权重微调 ImageNet-1k 并完成评估与线性探测【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm本篇指南完整梳理 BEiTBERT Pre-Training of Image Transformers在 ImageNet-1k 图像分类任务上的落地流程从环境与数据准备、基于 ImageNet-22k 预训练权重的微调含梯度累积、层衰减、DeepSpeed 混合精度等关键配置、微调后模型的多分辨率评估到冻结主干特征的 Linear Probe 评测。读完本文你将能够复现 BEiT-base/large 在 224/384/512 分辨率下的微调与评测流程并理解 run_class_finetuning.py 与 run_linear_eval.py 的底层实现原理。一、背景为什么推荐预训练 22k 中间微调的权重路线BEiT 的官方代码与预训练模型位于仓库的 beit 目录。BEiT 采用类似 BERT 的掩码图像建模Masked Image Modeling预训练方式其预训练权重分为两类微调路线也因此不同pt22k系列仅在 ImageNet-22k 上做自监督预训练未经过任何监督微调pt22k_ft22k系列在 ImageNet-22k 自监督预训练之后又进行了 ImageNet-22k 上的中间监督微调。官方明确建议优先使用pt22k_ft22k系列权重进行 ImageNet-1k 微调这类权重在迁移到 1k 任务时精度更高详见 beit/README.md 中的权重对照表在 224 分辨率下base 从 83.7 提升到 85.2large 从 86.0 提升到 87.4。同时 README 提供了模型规格BEiT-base 为 12 层、hidden 768、12 头、patch 16×16约 86M 参数BEiT-large 为 24 层、hidden 1024、16 头、patch 16×16约 304M 参数。所有预训练权重均以 224×224 分辨率预训练微调到更高分辨率时由代码自动进行位置编码插值。二、Setup环境安装与 ImageNet-1k 数据准备2.1 环境安装进入beit目录安装依赖pip install -r beit/requirements.txtbeit/requirements.txt 中锁定的核心版本如下包版本torch1.7.1torchvision0.8.2timm0.3.2deepspeed0.4.0scipy用于位置编码插值tensorboardX、einops、blobfile、numpy、requests 等未锁版本若启用 DeepSpeed 混合精度训练还需按 beit/README.md 中的说明从源码安装 NVIDIA Apex--cpp_ext --cuda_ext。run_class_finetuning.py在启用--enable_deepspeed时会动态引入 DeepSpeed 配置参数并调用deepspeed.initialize见 run_class_finetuning.py若未安装会提示pip install deepspeed0.4.0并退出。2.2 数据目录结构从 image-net.org 下载并解压 ImageNet-1k 后目录结构必须符合 torchvisiondatasets.ImageFolder的标准布局——每个类别一个子目录训练集与验证集分别放在train/与val/下/path/to/imagenet/ train/ class1/ img1.jpeg class2/ img2.jpeg val/ class1/ img3.jpeg class/2 img4.jpeg在源码层面datasets.py 的build_dataset对data_set IMNET会自动拼接args.data_path/train与args.data_path/val并用torchvision.datasets.ImageFolder加载类别数固定为 1000。默认的数据增强管线datasets.py训练侧使用 timm 的create_transformAutoAugment 默认rand-m9-mstd0.5-inc1、Random Erase 概率 0.25、bicubic 插值验证侧则按crop_pct224 以下取 224/256384 及以上取 1.0先 Resize 再 CenterCrop。三、Fine-tuningImageNet-1k 微调实战3.1 推荐路线使用pt22k_ft22k权重8×V100-16GB 示例以下命令使用 8 张 V100-16GB 微调 BEiT-large。文中的权重文件均以--finetune指向本地路径具体下载地址见 beit/README.md 的权重列表beit_large_patch16_224_pt22k_ft22k.pth等OMP_NUM_THREADS1 python -m torch.distributed.launch --nproc_per_node8 beit/run_class_finetuning.py \ --model beit_large_patch16_224 --data_path /path/to/imagenet \ --finetune /path/to/beit_large_patch16_224_pt22k_ft22k.pth \ --output_dir /path/to/save_result --batch_size 32 --lr 2e-5 --update_freq 2 \ --warmup_epochs 5 --epochs 30 --layer_decay 0.9 --drop_path 0.4 \ --weight_decay 1e-8 --enable_deepspeed关键参数含义--batch_size单张 GPU 上的 batch size--update_freq梯度累积步数有效 batch size GPU 数量 ×--batch_size×--update_freq。上例为8×32×2 512。三个参数需要联动调整以保持总 batch size 不变——例如显存不足OOM时可以减小--batch_size并增大--update_freq用梯度累积换取相同有效 batch size--enable_deepspeed开启 DeepSpeed 微调内部使用 Apex O2 混合精度。不带该参数时代码走torch.cuda.amp.autocast()NativeScaler的常规 AMP 路径对比见 run_class_finetuning.py 与 engine_for_finetuning.py更高分辨率微调设--input_size 384并把--model改为beit_large_patch16_384OOM 时同样用梯度累积缓解。BEiT-base 微调只需把--layer_decay与--drop_path分别改为 0.85 与 0.1其余参数保持不变OMP_NUM_THREADS1 python -m torch.distributed.launch --nproc_per_node8 beit/run_class_finetuning.py \ --model beit_base_patch16_224 --data_path /path/to/imagenet \ --finetune /path/to/beit_base_patch16_224_pt22k_ft22k.pth \ --output_dir /path/to/save_result --batch_size 64 --lr 2e-5 --update_freq 1 \ --warmup_epochs 5 --epochs 30 --layer_decay 0.85 --drop_path 0.1 \ --weight_decay 1e-8 --enable_deepspeed3.2 纯自监督权重路线pt22k权重需要 mixup/cutmix若使用未经过 22k 中间微调的pt22k系列权重beit_*_patch16_224_pt22k.pth官方建议在微调阶段开启 mixup 与 cutmix以弥补监督信号的缺失# BEiT-large OMP_NUM_THREADS1 python -m torch.distributed.launch --nproc_per_node8 beit/run_class_finetuning.py \ --model beit_large_patch16_224 --data_path /path/to/imagenet \ --finetune /path/to/beit_large_patch16_224_pt22k.pth \ --output_dir /path/to/save_result --batch_size 64 --lr 1e-3 --update_freq 2 \ --warmup_epochs 5 --epochs 50 --layer_decay 0.75 --drop_path 0.2 \ --weight_decay 0.05 --mixup 0.8 --cutmix 1.0 --enable_deepspeed # BEiT-base OMP_NUM_THREADS1 python -m torch.distributed.launch --nproc_per_node8 beit/run_class_finetuning.py \ --model beit_base_patch16_224 --data_path /path/to/imagenet \ --finetune /path/to/beit_base_patch16_224_pt22k.pth \ --output_dir /path/to/save_result --batch_size 128 --lr 4e-3 --update_freq 1 \ --warmup_epochs 20 --epochs 100 --layer_decay 0.65 --drop_path 0.1 \ --weight_decay 0.05 --mixup 0.8 --cutmix 1.0 --enable_deepspeed这条路线需要更长的训练large 50 epochs、base 100 epochs与更高的学习率同时配合--mixup 0.8 --cutmix 1.0和更大的--weight_decay 0.05。3.3 源码级解析微调脚本的关键机制理解了命令后再来看 run_class_finetuning.py 内部做了什么预训练权重加载与适配L315-L437--finetune支持本地路径或 HTTPS URL自动走torch.hub.load_state_dict_from_url。加载时先删除与目标分类头尺寸不匹配的head.weight/head.bias随后对相对位置偏置表与pos_embed做插值若预训练分辨率与微调分辨率不一致如 224→384代码会将共享的相对位置偏置展开到每个 Transformer Block并利用scipy.interpolate.interp2d按几何级数分布对位置编码进行 bicubic 插值从而支持任意分辨率微调。层衰减Layer DecayL465-L469 与 optim_factory.py--layer_decay小于 1.0 时用LayerDecayValueAssigner为不同层分配指数衰减的lr_scale浅层学习率小、深层学习率大。这就是--layer_decay 0.9/0.85/0.65差异的本质——模型越深越需要精细的学习率分层。损失函数自动选择L513-L519开启 mixup/cutmix 时用SoftTargetCrossEntropy软标签--smoothing 0时用LabelSmoothingCrossEntropy否则用普通CrossEntropyLoss。梯度累积与学习率调度engine_for_finetuning.pytrain_one_epoch中 loss 先除以update_freq再反传每累积update_freq步才更新一次参数学习率与权重衰减均按 step 级的 cosine 调度utils.cosine_scheduler并支持warmup_epochs/warmup_steps两种预热方式。训练主循环L532-L586每个 epoch 结束在验证集上评估跟踪max_accuracy并以best命名保存最优 checkpoint日志写入output_dir/log.txt。四、Evaluate评估微调后的 checkpoint微调完成后可用--eval模式在单张 GPU 上直接评测官方或自训的微调权重。--eval分支会加载--resume指定的 checkpoint 后调用engine_for_finetuning.evaluate见 run_class_finetuning.py评估函数在torch.cuda.amp.autocast()下输出 Acc1、Acc5 与 loss见 engine_for_finetuning.py。官方微调权重beit_*_pt22k_ft22kto1k.pth下载见 beit/README.md 表格在 ImageNet val 上的预期结果如下1. BEiT-large224 分辨率python beit/run_class_finetuning.py \ --eval --model beit_large_patch16_224 --data_path /path/to/imagenet \ --resume /path/to/beit_large_patch16_224_pt22k_ft22kto1k.pth预期输出* Acc1 87.396 Acc5 98.282 loss 0.5152. BEiT-base384 分辨率python beit/run_class_finetuning.py \ --eval --model beit_base_patch16_384 --input_size 384 --data_path /path/to/imagenet \ --resume /path/to/beit_base_patch16_384_pt22k_ft22kto1k.pth预期输出* Acc1 86.820 Acc5 98.124 loss 0.5653. BEiT-large384 分辨率python beit/run_class_finetuning.py \ --eval --model beit_large_patch16_384 --input_size 384 --data_path /path/to/imagenet \ --resume /path/to/beit_large_patch16_384_pt22k_ft22kto1k.pth预期输出* Acc1 88.408 Acc5 98.602 loss 0.4794. BEiT-large512 分辨率python beit/run_class_finetuning.py \ --eval --model beit_large_patch16_512 --input_size 512 --data_path /path/to/imagenet \ --resume /path/to/beit_large_patch16_512_pt22k_ft22kto1k.pth预期输出* Acc1 88.600 Acc5 98.658 loss 0.474这组结果清晰展示了 BEiT 的缩放特性从 224→384→512BEiT-large 的 Top-1 精度从 87.396 一路提升到 88.600验证了高分辨率微调 位置编码插值路线的有效性。--model中的分辨率后缀必须与--input_size保持一致因为run_class_finetuning.py会按input_size // patch_size计算 Transformer 的window_sizeL310-L313。五、Example在 ImageNet 上做 Linear ProbeLinear Probe 用于评测预训练特征的质量冻结 BEiT 主干参数仅在顶部训练一层线性分类器。在单节点 8 卡上执行python -m torch.distributed.launch --nproc_per_node8 beit/run_linear_eval.py \ --model beit_base_patch16_224 \ --pretrained_weights /path/to/beit_base_patch16_224_pt22k.pth \ --data_path /path/to/imagenet \ --lr 4e-3 \ --output_dir /path/to/saverun_linear_eval.py 的实现要点冻结主干model.eval()后在训练与验证的 forward 中均以torch.no_grad()调用model.get_intermediate_layers(inp)提取每一层特征L189-L202特征拼接对每层特征同时取[CLS]token 与 patch token 的全局平均池化并拼接avgpool_patchtokens默认开启维度变为embed_dim × 2逐层分类器LinearClassifier为每一层各建一个nn.LinearL283-L300因此可以同时观察不同深度的特征质量优化器与调度默认 AdamW也可用--optimizer sgd学习率按 batch 线性缩放base_lr × batch/256余弦退火调度并支持--checkpoint_key指定从预训练 checkpoint 的model|module|teacher键中取权重L317-L356。注意run_linear_eval.py的默认均值/标准差是 Inception 风格的(0.5, 0.5, 0.5)若预训练阶段使用了 ImageNet 默认统计量需显式加--imagenet_default_mean_and_stdL351-L353以保证与预训练数据分布一致。六、常见问题与调参建议OOM显存不足首选方案是保持有效 batch size 不变——减小--batch_size、增大--update_freq升级到 384/512 分辨率时同理因为input_size增大会同时放大激活显存与注意力矩阵开销。精度不达标先确认权重类型与命令匹配——pt22k_ft22k权重用小学习率短训练2e-5、30 epochspt22k权重必须开 mixup/cutmix 并延长训练50~100 epochs。--layer_decay与--drop_path是 base/large 的关键差异参数base 0.85/0.1large 0.9/0.4纯自监督路线 0.65~0.75/0.1~0.2。分布式训练统一通过torch.distributed.launch --nproc_per_nodeN启动update_freq由 DeepSpeed 的gradient_accumulation_steps校验run_class_finetuning.py两者必须一致。复现与日志固定--seed 0默认训练与评估日志以 JSON 逐行追加到output_dir/log.txt最优权重自动保存为best版本便于回溯实验。若需在语义分割任务上复用同一套预训练权重可参考 semantic_segmentation/README.md 中基于 UPerNet 的 ADE20K 微调配置本文聚焦的 ImageNet-1k 分类流程与之一脉相承共享同样的权重下载与位置编码插值机制。【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考