timm documentation
脚本
脚本
包含在 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保持默认值不变。 - 嵌套字段路径使用
/,例如针对 TFDSbee_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 .016MixNet-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 reduceSE-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 .064MobileNetV3-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.9ResNeXt-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