timm documentation

脚本

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

脚本

包含在 github 根文件夹中的训练、验证、推理和检查点清理脚本。目前这些脚本未包含在 pip 发布包中。

训练和验证脚本源自 PyTorch Imagenet Examples 的早期版本。随着时间推移,我添加了大量功能,其中包括基于 NVIDIA’s APEX Examples 的 CUDA 特定性能优化。

训练脚本

训练参数的种类很多,并非所有选项的组合(甚至某些选项本身)都经过了充分测试。对于训练数据集文件夹,请指定包含 train 和 validation 文件夹的根目录。

对于单节点运行,请使用 torchrun,每个 GPU 分配一个进程。例如,在将 MobileNetV4 配置 保存为 mobilenetv4.yaml 之后:

torchrun --standalone --nproc_per_node=2 train.py \
  --config mobilenetv4.yaml --data-dir /data/imagenet --experiment mobilenetv4-cm

./distributed_train.sh 2 ... 是 torchrun 的便捷封装。 对于单 GPU,请使用 python train.py ...,并按照 HParams 中的说明调整批大小和学习率。

`--amp` uses PyTorch native mixed precision, with float16 by default. Use `--amp-dtype bfloat16` on supported hardware. The examples below use native PyTorch AMP and DDP; Apex is not required.

配置文件

任何训练参数都可以通过 --config 在 YAML 文件中指定,键名为带下划线的参数名(--weight-decay 变为 weight_decay)。命令行参数会覆盖文件中的设置。每次运行都会将完整的生效参数集写入其输出文件夹中的 args.yaml,该文件本身也是一个有效的 --config,因此可以使用 python train.py --config output/train/my-run/args.yaml --experiment my-run-2 来复现某次运行。该文件还会记录 output、experiment 和 resume,因此如果不提供新的实验名称,命令会写入原始文件夹;而使用 --resume auto 则会继续原始运行,而不是重复它。配置键会针对脚本的参数进行验证:未知键会发出警告,而无效选项或数值参数的非数值则会报错。

恢复和里程碑检查点

每次运行都会写入 last.pth.tar(始终为最新 epoch,包含模型、优化器、EMA 和 AMP scaler 状态)、model_best.pth.tar,以及由 --checkpoint-hist 限制数量的 checkpoint-N.pth.tar 文件排名历史。

  • --resume PATH 会恢复该状态,并从检查点的 epoch 继续执行训练计划。这是从现有检查点启动新实验文件夹的常用方式。
  • --resume auto 支持原地恢复:当设置了 --output 和 --experiment 时,如果该实验文件夹中存在 last.pth.tar,则从中继续训练,否则启动一次全新的运行。中断后可以使用相同的命令重新运行。检查点历史、最佳指标跟踪以及 summary.csv 都会保持一致地延续,因此 --checkpoint-hist 的淘汰机制和 model_best 在重启后依然正确。
  • --stop-epoch N 会在完成 N 个 epoch 后停止,但不会更改由 --epochs 设置的计划。最后一个 epoch 始终会被评估并保存检查点,因此可以分段进行训练。
  • --save-epochs N [N ...] 会在排名历史之外保留不可变的 milestone-N.pth.tar 快照(N 为已完成的 epoch 数)。在文件系统允许的情况下,它们通过硬链接从 last.pth.tar 创建,因此不占用额外空间,并且会在这些 epoch 强制进行一次评估。

这些功能共同使得手动运行 warmup-stable-decay (WSD) 实验变得轻而易举:只需训练一次稳定的主干,然后即可基于其里程碑,利用完整的优化器状态分支出独立的冷却阶段。

# stable trunk through 30 completed epochs, keeping milestones at 18, 24 and 30. The 1 epoch decay is never reached.
python train.py --config configs/vit.yaml --sched wsd --sched-on-updates --epochs 31 --decay-epochs 1 \
    --stop-epoch 30 --save-epochs 18 24 30 --output output/wsd --experiment stable --resume auto

# a 6 epoch 1-sqrt cooldown branched from epoch 24, i.e. a 30 epoch run that shares the first 24 epochs with the trunk
python train.py --config configs/vit.yaml --sched wsd --sched-on-updates --epochs 30 --decay-epochs 6 --lr-decay-fn 1-sqrt \
    --resume output/wsd/stable/milestone-24.pth.tar --output output/wsd --experiment decay-p24-d6

衰减阶段占据调度计划的最后 --decay-epochs 个 epoch,因此从已完成的 P 个 epoch 开始进行 D 个 epoch 的冷却,对应参数为 --epochs P+D --decay-epochs D(当使用 --warmup-prefix 时,需从 --epochs 中减去 --warmup-epochs)。下方的 sweep.py 脚本可自动完成此操作。

超参数扫描

sweep.py(PyTorch 2.5 或更高版本)针对任意 train.py 参数规划并执行扫描,可选地支持 WSD 分支。它为每个任务写入一个完整的 train.py --config 文件,外加一个包含任务依赖图的 plan.json,然后在本地 GPU 池上运行就绪的任务。在 worker 运行期间,该计划保持不变。每个任务都是一次普通的 train.py 调用,拥有独立的实验文件夹,且每个生成的 run.sh 都可以手动运行或交给其他调度器处理。

快速扫描无需配置文件。搜索轴来自--sweep,基础配置来自--之后的尾部train.py参数:

python sweep.py run --name lr-wd --sweep lr=1e-4,3e-4,1e-3 --sweep weight_decay=0.05,0.1 --gpus 0,1,2,3 \
    -- --model vit_small_patch16_224 --data-dir /data/imagenet --sched cosine --epochs 100 --amp

--gpus 列出要运行的 GPU,当 CUDA_VISIBLE_DEVICES 被设置时(例如在 Slurm 分配中),它作为 CUDA_VISIBLE_DEVICES 的索引。

WSD 扫描在多个冷却阶段之间共享每个超参数组合的一个稳定主干。对于以下每个学习率,主干将运行至 30 个 epoch,并在 18、24 和 30 处设置里程碑,从每个里程碑分支出一个 6 个 epoch 的冷却阶段,总共 4 个主干和 12 个冷却阶段,而非 12 次完整运行。一旦其里程碑存在,冷却阶段便会立即开始,同时主干继续运行。需要多于一块 GPU 的任务使用 torchrun 启动:

python sweep.py run --name vit-wsd --sweep lr=1e-3,5e-4,2e-4,1e-4 \
    --wsd-points 18 24 30 --wsd-decay-epochs 6 --wsd-decay-fn 1-sqrt --gpus-per-job 2 --gpus 0,1 \
    -- --model vit_small_patch16_224 --data-dir /data/imagenet --warmup-epochs 3 --warmup-prefix --amp

规划器拥有以下标志,因此无法在命令行中指定或通过扫描获取。

在每次扫描中:

  • --output
  • --experiment
  • --resume
  • --stop-epoch
  • --save-epochs

此外,在 WSD 扫描中:

  • --sched(也可以指定为 wsd,规划器无论如何都会将其设置为该值)
  • --epochs
  • --decay-epochs
  • --lr-decay-fn

YAML 规范支持带分布的随机搜索、成对(zipped)轴、跨种子的重复以及基础配置文件,有关模式请参见 sweep.py 顶部的文档字符串。python sweep.py plan spec.yaml 会写入配置和 graph.dot,而不会运行任何内容。

扫描结果保存在 output/sweeps/<name>/ 中,相对于 spec 文件(对于命令行扫描,则相对于工作目录),每个试验对应一个文件夹,文件夹名称基于扫描值(trial-000-lr0.001),每个文件夹包含该任务的实验文件夹。每个保留的检查点都是包含优化器状态的完整副本,因此扫描任务除了 last.pth.tar 和 model_best.pth.tar 外,还会保留一个带排名的检查点(--checkpoint-hist 1),并且 WSD 扫描会在每次更新时推进调度(--sched-on-updates)。在基础配置中设置任一选项都会覆盖默认行为。在运行期间或运行结束后:

python sweep.py status output/sweeps/vit-wsd    # job states and progress
python sweep.py results output/sweeps/vit-wsd   # ranked endpoint metrics, written to results.csv

结果在相同预算下比较各次试验。WSD 扫描中,每行对应一次试验,每列对应一个冷却期(p24-d6 表示从 24 个 epoch 开始进行 6 个 epoch 的冷却),展示的是多次重复的平均最终指标,并标记了每列中的最佳值。普通扫描则根据每个 epoch 预算内的最终指标进行排名。results.csv 包含所有任务(包括主干段),并记录了每个任务的最佳 epoch。在没有验证集的情况下,排名将回退到使用训练损失,并且可以使用 validate.py 对端点检查点进行评估。

在已中断的 sweep 上再次运行 sweep.py run 即可恢复:已完成的作业会被跳过,而部分完成的作业将从其自身的 last.pth.tar 继续。多台机器上共享 sweep 文件夹的 worker 可以各自运行它。它们通过 state/locks 下的 flock 锁进行协调,每个作业的每个训练进程也会持有这些锁,因此,只要某个作业中仍有进程未退出,该作业既不会被重新启动,也不会被重新规划。由多台机器共享的 sweep 需要一个在所有机器上都能正常工作的 flock 文件系统,例如以 -o flock 选项挂载的 NFSv4 或 Lustre。仅支持本地锁定的挂载无法在机器间进行协调,因此请从每个客户端检查锁定情况。停止 worker(Ctrl-C,或来自 scancel 的 SIGTERM)会停止其作业,而手动运行某个作业的 run.sh 则会绕过协调机制。

state/locks 下的锁文件是永久性的:切勿通过删除或替换它们来清除繁忙的 sweep。请改为停止或等待其 worker 和训练进程结束。running (gone) 状态表示训练锁已释放,但尝试尚未完成协调;请运行一个 worker 以解决该问题并恢复未完成的工作。status 和 results 不会修复作业状态。

Worker 在启动时读取一次计划。若要更改 sweep,请停止其所有 worker 和训练进程,使用 --force 重新制定计划,然后再次启动它们。在任何作业开始之前,计划中的任何内容都可以更改。之后,其训练作业只能被扩展:在现有作业之后添加更多试验、冷却期或 WSD 点,其中每个 trunk 都从其停止的位置继续。对现有训练作业的更改需要一个新的 sweep。生成的路径在计划写入时即被固定,因此请在新位置重新制定计划,而不是移动 sweep 文件夹。

如果规划过程被中断,工作进程会检测到来自不完整规划写入的配置或启动器,并拒绝启动。请使用 --force 重新运行原始的规划命令以完成或修复规划,然后重新启动工作进程。每次成功的规划写入都会在 plan.json 中发布一个对应的生成版本,包括配置和启动器;如果规划未发生变化且完整,则不会写入任何内容。

例如,要将上述 CLI WSD 扫描扩展到 36 个稳定 epoch,请停止其 worker 和 job,然后重复原始的规划参数,并在末尾追加后续的点:

python sweep.py plan --force --name vit-wsd --sweep lr=1e-3,5e-4,2e-4,1e-4 \
    --wsd-points 18 24 30 36 --wsd-decay-epochs 6 --wsd-decay-fn 1-sqrt --gpus-per-job 2 \
    -- --model vit_small_patch16_224 --data-dir /data/imagenet --warmup-epochs 3 --warmup-prefix --amp
python sweep.py run output/sweeps/vit-wsd --gpus 0,1

对于 YAML 扫描,请在原始规范中追加该点,并在重启前运行 python sweep.py plan spec.yaml --force。请显式保留 wsd.decay_epochs 且保持不变(本例中为 [6]):其默认值为最终点的 20%,因此延长扫描范围可能会改变现有的冷却期。请保留现有的试验 ID;重新排序或扩展网格轴可能会导致试验重新编号。如果使用 lr_noise,主干的调度取决于其扫描范围,因此为已启动的扫描添加后续点需要创建新的扫描。

训练设置应包含在计划中:使用规范中的 train 块,或在创建 CLI 扫描时 -- 之后的参数。不存在运行时训练覆盖。报告设置(例如排名指标)和输出设置(checkpoint_hist、log_wandb、wandb_project、wandb_tags)可以在离线状态下通过 --force 进行修改,而无需重置任务状态或更改训练标识。输出设置适用于未来的尝试;已完成的任务不会被重新运行。

sweep.py 需要 Unix flock:已在 Linux 上测试,预期在 macOS 上可用但未经测试。不支持原生 Windows;请使用 WSL2。如果网络分区持续时间超过 NFS 租约,锁将失效:失去锁的断开进程可能继续训练,因此另一台机器可以启动一个重叠的尝试。

验证 / 推理脚本

验证和推理脚本的用法相似。一个在验证集上输出指标,另一个在 csv 中输出 topk 类别 id。请指定包含验证图像的文件夹,而不是像训练脚本那样指定基础文件夹。

使用模型的预训练权重(如果存在)进行验证:

python validate.py --data-dir /imagenet/validation/ --model seresnext26_32x4d --pretrained

要从检查点运行推理:

python inference.py --data-dir /imagenet/validation/ --model mobilenetv3_large_100 --checkpoint ./output/train/model_best.pth.tar

训练示例

ImageNet 训练配方

这些命令对应于选定的 HParams 配方,您可以在其中找到可复制的 YAML 配置、源代码 gist 以及已发布的检查点结果。它们假设 ImageFolder 数据位于 /data/imagenet/train/ 和 /data/imagenet/validation/ 下。--batch-size 是每个 GPU 的批大小。 MobileNetV4 和 ConvNeXt 示例中明确指定的学习率适用于所声明的全局批大小; 如果 GPU 数量发生变化,它们不会自动缩放。

MobileNetV4 Conv Medium,ImageNet-1k

来自 mnv4_cm_r256_e500_gpu2.yaml: 2 个 GPU,全局批大小 1024,256px 训练,以及 20 个预热 + 500 个余弦退火 epoch。 对应的权重为 mobilenetv4_conv_medium.e500_r256_in1k。

torchrun --standalone --nproc_per_node=2 train.py --data-dir /data/imagenet \
  --model mobilenetv4_conv_medium.e500_r256_in1k --img-size 256 --crop-pct 0.95 --batch-size 512 \
  --opt adamw --lr 0.002 --weight-decay 0.1 --clip-grad 5.0 \
  --sched cosine --sched-on-updates --epochs 500 --warmup-epochs 20 --warmup-prefix \
  --warmup-lr 0 --min-lr 0 --cooldown-epochs 0 \
  --aa rand-m8-inc1-mstd1.0 --mixup 0.2 --mixup-prob 0.8 --smoothing 0.1 \
  --reprob 0.25 --remode pixel --drop 0.2 --drop-path 0.1 \
  --model-ema --model-ema-decay 0.9998 --model-ema-warmup --dist-bn reduce \
  --amp --amp-dtype bfloat16 --torchcompile inductor --experiment mobilenetv4-cm

如果 GPU 不支持 bfloat16,请使用 --amp-dtype float16;--torchcompile inductor 是可选的。

带寄存器(registers)的 ViT Medium,ImageNet-1k

来自 train-vit_medium_reg4-4gpu-in1k.yaml: 4 个 GPU,全局批大小 1024,共 600 个 epoch,包括预热和 10 个冷却 epoch。 对应的权重为 vit_medium_patch16_reg4_gap_256.sbb_in1k。

torchrun --standalone --nproc_per_node=4 train.py --data-dir /data/imagenet \
  --model vit_medium_patch16_reg4_gap_256.sbb_in1k --model-kwargs fix_init=True --head-init-scale 0 \
  --img-size 256 --crop-pct 0.95 --batch-size 256 \
  --opt adamw --opt-eps 1e-8 --lr-base 0.0008 --lr-base-size 512 --lr-base-scale sqrt \
  --weight-decay 0.07 --clip-grad 5.0 --sched cosine --sched-on-updates \
  --epochs 600 --warmup-epochs 20 --warmup-lr 5e-7 --min-lr 5e-7 --cooldown-epochs 10 \
  --aa rand-m7-inc1-mstd1.0-n3 --aug-repeats 3 --color-jitter 0 \
  --mixup 0.8 --cutmix 1.0 --smoothing 0.1 --reprob 0.2 --remode pixel --drop-path 0.2 \
  --seed 0 --amp --amp-dtype float16 --torchcompile inductor --experiment vit-medium-sbb

本次运行使用 AdamW,未启用 EMA。其峰值学习率约为 0.001131,出现在全局批次 1024。

ConvNeXt Tiny,从 ImageNet-12k 到 ImageNet-1k 的微调

来自 hparams_84_00-convnext_tiny.in12k-args.yaml: 8 个 GPU,全局批大小 4096,共 75 个 epoch,包括预热和 10 个冷却 epoch。 加载 ImageNet-12k 权重,并设置 --num-classes 1000 以替换分类器进行微调。 生成的检查点系列为 convnext_tiny.in12k_ft_in1k。

torchrun --standalone --nproc_per_node=8 train.py --data-dir /data/imagenet \
  --model convnext_tiny.in12k --pretrained --num-classes 1000 \
  --img-size 224 --crop-pct 1.0 --batch-size 512 --grad-checkpointing \
  --opt adamw --lr 1e-4 --weight-decay 0.05 --layer-decay 0.75 --clip-grad 3.0 \
  --sched cosine --epochs 75 --warmup-epochs 10 --warmup-lr 1e-6 --min-lr 5e-7 \
  --cooldown-epochs 10 --lr-noise 0.1 1.0 \
  --aa rand-m8-inc1-mstd101 --mixup 0.8 --cutmix 1.0 --smoothing 0.1 \
  --reprob 0.3 --remode pixel --drop-path 0.1 --model-ema --model-ema-decay 0.9998 \
  --amp --amp-dtype float16 --experiment convnext-tiny-ft

多标签分类

对于具有多个独立标签的图像,请使用 --task multilabel。

  • --num-classes 用于设置词汇表大小。
  • --target-format indices(默认值)将目标列读取为正数、从零开始的类别 ID 列表。 在批处理之前,标签会被转换为浮点数多热目标,空列表表示没有正标签的图像。
  • --target-format multihot 读取长度为 --num-classes 的稠密多热向量(取值为 [0, 1] 区间内的 bool、int 或 float 值)。该向量将按原样使用,因此软标签值可直接用于 BCE 训练,并在评估指标中按 0.5 进行二值化。多热目标的类别映射必须以源类别索引作为键。

如果没有该标志,每个列表都会被读取为类别索引,因为整数多热向量与索引列表无法区分。

植物病理学数据集提供了这种格式:一个 image 列和一个包含 ClassLabel 值序列的 labels 列。它的六个类别是 complex、frog_eye_leaf_spot、healthy、powdery_mildew、rust 和 scab。例如,[5, 1, 0] 会变成 [1, 1, 0, 0, 0, 1]。

python train.py --dataset hfds/timm/plant-pathology-2021 \
  --task multilabel --target-key labels --num-classes 6 \
  --model resnet50 --pretrained --batch-size 32 --epochs 30 \
  --opt adamw --lr 1e-4 --weight-decay 0.01 --amp

python validate.py --dataset hfds/timm/plant-pathology-2021 \
  --task multilabel --target-key labels --num-classes 6 \
  --model resnet50 --checkpoint ./output/train/<experiment>/model_best.pth.tar

hfids/timm/plant-pathology-2021 支持以相同的目标格式进行流式处理。读取器支持:

  • Hugging Face hfds 和 hfids 支持多标签目标。
  • WebDataset (wds) 支持在每个样本的 .json 伴随文件中存储的类别 ID 列表,该列表位于由 --target-key 指定的字段下。如果不使用 --target-key,则 .cls 文件提供单个类别索引。
  • 文件夹和 tar 读取器返回单个类别索引。

存储每个标签一个二进制字体的数据集(例如 Wake Vision)使用以下设置:

  • --target-key person,depiction,body_part 用于选择以逗号分隔的字段列表。每个字段按列出的顺序成为一个类别,大于零的值计为正样本。此功能适用于 hfds、hfids 和 tfds 读取器,以及当字段位于 .json 伴随文件中时的 WebDataset。
  • --num-classes 必须等于字段数量。
  • 由于多字段键会定义其自身的格式,因此 --target-format 保持默认值不变。
  • 嵌套字段路径使用 /,例如针对 TFDS bee_dataset 的 --input-key input --target-key output/pollen_output,output/wasps_output。单个目标键也接受相同的路径。包含 / 的字面字段名(例如 TFDS 的 image/filename)优先于路径。

Standard 和 NaFlex 加载器支持多标签目标,包括 mixup 和 cutmix;NaFlex 训练目前需要一个 map 风格的数据集,例如 hfds。

该任务使用带 logits 的二元交叉熵进行训练。多标签训练的平滑默认值为零;设置 --smoothing s 会将每个二元目标调整为 target * (1 - s) + 0.5 * s,当 Mixup/CutMix 激活时由它们应用,否则由损失函数应用。现有的 --bce-sum 和 --bce-target-thresh 选项同样适用。此任务不支持蒸馏和 JSD 损失。

--loss 用于选择其他损失函数(bce 是多标签的默认值):

  • asl:Asymmetric Loss。它与 BCE 具有相同的平滑和 Mixup/CutMix 行为,并且以 float32 计算,因此与 --amp 配合使用是安全的。

    • --asl-gamma-neg 设置负样本目标的聚焦参数(默认值为 4)。
    • --asl-gamma-pos 设置正样本目标的聚焦参数(默认值为 1)。
    • --asl-clip 设置负样本的概率间隔(默认值为 0.05)。
    • --asl-reduction 的默认值为 batchmean,即对类别求和,并对批次求平均。sum 会恢复原始的 ASL 归约方式,该方式同时对批次求和,因此有效学习率会随批次大小缩放。
  • twoway:双向多标签损失, 在每个样本的类别之间以及每个类别的样本之间,对正负 logits 进行对比。 其 logits 是排序分数,因此 mAP 是有意义的指标;在 sigmoid 阈值下的 F1 未经过校准。

    • --twoway-tp 设置正对数几率温度(默认值为 4)。
    • --twoway-tn 设置负对数温度(默认值为 1)。
  • zlpr:ZLPR,一种无需超参数的多标签扩展,基于 softmax 交叉熵,内置的 logit 阈值为 0。

  • db:用于长尾多标签数据的Distribution-Balanced Loss。BCE 配合针对每个样本的重新平衡权重,该权重考虑了标签共现情况、对 logits 进行负容忍正则化,并包含一个 focal 项。它支持 Mixup/CutMix 和 smoothing,默认值来自参考 DB 配置:

    • --db-neg-scale 设置负 logit 的缩放系数(默认值为 2)。
    • --db-init-bias 设置类别先验 logit 偏移因子(默认值为 0.05)。
    • --db-focal-gamma 设置 focal focusing(默认值为 2)。
    • --class-stats 以类别统计文件(见下文)的形式提供所需的训练标签数量。

twoway 和 zlpr 需要二分类目标,因此不支持 Mixup/CutMix 或 --smoothing。

对于偏斜的标签分布,bce 和 asl 支持两个加权标志:

  • --loss-pos-weight 用于对每个类别的正样本项进行加权,以平衡类别内正样本与负样本的比例。这还会使预测结果偏向正样本(在固定阈值下召回率更高,但概率的校准程度更低)。
  • --loss-class-weight 用于对每个类别的整体损失进行加权,从而平衡各类别之间的关系并保持校准。

每个标志都接受显式权重(单个值、每个类别一个值的逗号分隔列表,或一个文件)或一个方法名称,该方法根据通过 --class-stats 提供的训练标签计数来推导权重:

  • --loss-pos-weight neg_pos:每个类别的负样本/正样本数量。
  • --loss-class-weight inv_freq:逆类别频率,归一化至均值为 1。
  • --loss-class-weight effective_num:根据样本有效数量计算的class-balanced权重,并归一化至均值为 1。

派生权重选项:

  • --loss-weight-power 用于设置 neg_pos 和 inv_freq 的指数(默认值为 1),设为 0.5 可实现更柔和的平方根重新加权。
  • --loss-weight-beta 为 effective_num 权重设置 beta(默认值为 0.999)。
  • --loss-weight-max 用于限制派生的权重。

两个权重标志可以使用相同的统计数据。class_weights.py 会统计某个数据集中的标签,其数据集参数与 train.py 相同,并写入类别统计文件(--method 可预览某个方法的权重):

python class_weights.py --dataset hfds/timm/plant-pathology-2021 --split train \
  --task multilabel --target-key labels --num-classes 6 --output stats.json

python train.py --dataset hfds/timm/plant-pathology-2021 \
  --task multilabel --target-key labels --num-classes 6 \
  --class-stats stats.json --loss-pos-weight neg_pos --loss-weight-power 0.5 ...

已弃用的标志:

旧标志替换
--bce-loss--loss bce
--jsd-loss--loss jsd
--bce-pos-weight--loss-pos-weight

验证报告包含 BCE 损失、map(平均精度均值)、micro_f1、macro_f1 和 sample_f1。指标以百分比表示,并使用完整的验证集进行计算,包括从分布式 rank 收集的预测结果。有序分布式采样器的填充部分会被排除。精确 mAP 会在评估完成前将预测结果保留在 CPU 上,因此其内存占用随示例数和类别数增加而增长。没有正样本的类别其 AP 贡献为零;分母为零的 F1 值也为零。

--eval-metric map 是检查点选择和调度的默认设置。F1 使用 0.5 的 sigmoid 概率阈值,可通过 --multilabel-threshold 进行配置;mAP 与此阈值无关。模型输出仍为 logits,因此在使用训练好的模型时,请应用 sigmoid 以获得独立的类别概率。

历史 ImageNet 训练方案

这些早期运行结果仍然是 RMSProp、SGD 以及 AugMix/JSD 训练的有用参考。硬件和报告的指标描述的是原始运行。对于较新的 AdamW 配方,请从上述示例或 gist 集合 开始。

使用 RandAugment 的 EfficientNet-B2 - 80.4 top-1,95.1 top-5

原始运行使用了双 Titan RTX 显卡和 NVIDIA Apex;当前的 --amp 使用原生 PyTorch AMP:

./distributed_train.sh 2 --data-dir /imagenet/ --model efficientnet_b2 -b 128 --sched step --epochs 450 --decay-epochs 2.4 --decay-rate .97 --opt rmsproptf --opt-eps .001 -j 8 --warmup-lr 1e-6 --weight-decay 1e-5 --drop 0.3 --drop-path 0.2 --model-ema --model-ema-decay 0.9999 --aa rand-m9-mstd0.5 --remode pixel --reprob 0.2 --amp --lr .016

MixNet-XL 配合 RandAugment - 80.5 top-1,94.9 top-5

原始运行使用了双 Titan RTX 显卡和 NVIDIA Apex;当前的 --amp 使用原生 PyTorch AMP:

./distributed_train.sh 2 --data-dir /imagenet/ --model mixnet_xl -b 128 --sched step --epochs 450 --decay-epochs 2.4 --decay-rate .969 --opt rmsproptf --opt-eps .001 -j 8 --warmup-lr 1e-6 --weight-decay 1e-5 --drop 0.3 --drop-path 0.2 --model-ema --model-ema-decay 0.9999 --aa rand-m9-mstd0.5 --remode pixel --reprob 0.3 --amp --lr .016 --dist-bn reduce

SE-ResNeXt-26-D 和 SE-ResNeXt-26-T

这些超参数(或类似参数)在多种 ResNet 架构上表现良好,通常建议随着模型规模的增大而增加训练轮数(epoch)……例如,ResNe(X)t50 大约需要 180-200 轮,更大的模型则需要 220 轮以上。如果使用更好的 GPU 或启用了 AMP,请按比例增加批大小(batch size)和学习率(LR)。这些参数是针对 2 张 1080Ti 显卡设置的:

./distributed_train.sh 2 --data-dir /imagenet/ --model seresnext26t_32x4d --lr 0.1 --warmup-epochs 5 --epochs 160 --weight-decay 1e-4 --sched cosine --reprob 0.4 --remode pixel -b 112

使用 RandAugment 的 EfficientNet-B3 - 81.5 top-1,95.7 top-5

该模型的训练始于与上文 EfficientNet-B2 w/ RA 相同的命令行。在训练了将近三周后,进程崩溃了。由于结果并不理想,我多次恢复训练并调整了几个参数(提高 RE 概率、降低 rand-aug、增加 ema-decay)。但效果依然不佳。最终,我对所有重启过程中表现最好的检查点进行了平均。在默认的分辨率/裁剪下,结果平平无奇,但奇怪的是,在使用 1.0 的全图像测试裁剪时,性能却好得多。

使用 RandAugment 的 EfficientNet-B0 - 77.7 top-1,95.3 top-5

Michael Klachko 使用针对更大 batch size 适配的 B2 命令行,并采用推荐的 B0 dropout rate 0.2,取得了这些结果。

./distributed_train.sh 2 --data-dir /imagenet/ --model efficientnet_b0 -b 384 --sched step --epochs 450 --decay-epochs 2.4 --decay-rate .97 --opt rmsproptf --opt-eps .001 -j 8 --warmup-lr 1e-6 --weight-decay 1e-5 --drop 0.2 --drop-path 0.2 --model-ema --model-ema-decay 0.9999 --aa rand-m9-mstd0.5 --remode pixel --reprob 0.2 --amp --lr .048

使用 JSD 损失和 RandAugment(clean + 2x RA augs)的 ResNet50 - 79.04 top-1,94.39 top-5

在两张较旧的 1080Ti 显卡上训练,这花费了相当长的时间。与我第一次效果较好的 AugMix 训练(78.99)相比,ImageNet 验证结果仅略有提升,且不具备统计显著性。然而,这些权重在 ImageNetV2、ImageNet-Sketch 等测试中表现出更强的鲁棒性。与最初的 AugMix 运行不同,我启用了 SplitBatchNorm,在干净数据分支上禁用了随机擦除,并提高了两条增强路径上的随机擦除概率。

./distributed_train.sh 2 --data-dir /imagenet -b 64 --model resnet50 --sched cosine --epochs 200 --lr 0.05 --amp --remode pixel --reprob 0.6 --aug-splits 3 --aa rand-m9-mstd0.5-inc1 --resplit --split-bn --loss jsd --dist-bn reduce

使用 RandAugment 的 EfficientNet-ES (EdgeTPU-Small) - 78.066 top-1,93.926 top-5

由 Andrew Lavin 使用 8 张 V100 显卡训练。未使用模型 EMA,最终检查点是训练过程中 8 个最佳检查点的平均值。

./distributed_train.sh 8 --data-dir /imagenet --model efficientnet_es -b 128 --sched step --epochs 450 --decay-epochs 2.4 --decay-rate .97 --opt rmsproptf --opt-eps .001 -j 8 --warmup-lr 1e-6 --weight-decay 1e-5 --drop 0.2 --drop-path 0.2  --aa rand-m9-mstd0.5 --remode pixel --reprob 0.2 --amp --lr .064

MobileNetV3-Large-100 - 75.766 top-1,92.542 top-5

./distributed_train.sh 2 --data-dir /imagenet/ --model mobilenetv3_large_100 -b 512 --sched step --epochs 600 --decay-epochs 2.4 --decay-rate .973 --opt rmsproptf --opt-eps .001 -j 7 --warmup-lr 1e-6 --weight-decay 1e-5 --drop 0.2 --drop-path 0.2 --model-ema --model-ema-decay 0.9999 --aa rand-m9-mstd0.5 --remode pixel --reprob 0.2 --amp --lr .064 --lr-noise 0.42 0.9

ResNeXt-50 32x4d w/ RandAugment - 79.762 top-1, 94.60 top-5

这些参数同样适用于 SE-ResNeXt-50 和 SK-ResNeXt-50,并且很可能也适用于 101 层版本。我在训练 SK-ResNeXt-50 32x4d 时使用了这些参数,该训练使用 2 个 GPU,并根据有效批量大小采用了略高的学习率(lr=0.18,每个 GPU 的 b=192)。下面的命令行是为 8 GPU 训练调优的。

./distributed_train.sh 8 --data-dir /imagenet --model resnext50_32x4d --lr 0.6 --warmup-epochs 5 --epochs 240 --weight-decay 1e-4 --sched cosine --reprob 0.4 --recount 3 --remode pixel --aa rand-m7-mstd0.5-inc1 -b 192 -j 6 --amp --dist-bn reduce
Update on GitHub