timm documentation
Scripts
Scripts
Un script d'entraînement, de validation, d'inférence et de nettoyage des points de contrôle, inclus dans le dossier racine de GitHub. Les scripts ne sont actuellement pas inclus dans la publication pip.
Les scripts d’entraînement et de validation ont évolué à partir des premières versions des PyTorch Imagenet Examples. J’y ai ajouté des fonctionnalités importantes au fil du temps, notamment des améliorations de performances spécifiques à CUDA basées sur les NVIDIA’s APEX Examples.
Script d'entraînement
La variété des arguments d’entraînement est importante et toutes les combinaisons d’options (ou même certaines options) n’ont pas été entièrement testées. Pour le dossier du jeu de données d’entraînement, spécifiez le dossier de base contenant un dossier train et un dossier validation.
Pour une exécution sur un seul nœud, utilisez torchrun avec un processus par GPU. Par exemple, après avoir enregistré la configuration MobileNetV4 sous le nom mobilenetv4.yaml :
torchrun --standalone --nproc_per_node=2 train.py \ --config mobilenetv4.yaml --data-dir /data/imagenet --experiment mobilenetv4-cm
./distributed_train.sh 2 ... est un wrapper pratique autour de torchrun.
Pour une seule GPU, utilisez python train.py ... et ajustez la taille du lot et le taux d’apprentissage comme décrit dans 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.
Fichiers de configuration
Tout argument d’entraînement peut être fourni dans un fichier YAML via --config, en utilisant le nom de l’argument avec des tirets bas comme clé (--weight-decay devient weight_decay). Les arguments de la ligne de commande prennent le pas sur le fichier. Chaque exécution écrit l’ensemble des arguments effectifs dans args.yaml dans son dossier de sortie, et ce fichier est lui-même un --config valide, de sorte qu’une exécution peut être reproduite avec python train.py --config output/train/my-run/args.yaml --experiment my-run-2. Le fichier enregistre également output, experiment et resume, de sorte qu’en l’absence d’un nouveau nom d’expérience, la commande écrit dans le dossier d’origine, et avec --resume auto elle reprend l’exécution d’origine plutôt que de la répéter. Les clés de configuration sont validées par rapport aux arguments du script : les clés inconnues déclenchent un avertissement, tandis que les choix invalides ou les valeurs non numériques pour des arguments numériques provoquent une erreur.
Reprise et points de contrôle des jalons
Chaque exécution écrit last.pth.tar (toujours l'époque la plus récente, avec l'état du modèle, de l'optimiseur, de l'EMA et de l'échelleur AMP), model_best.pth.tar, et un historique classé de fichiers checkpoint-N.pth.tar limité par --checkpoint-hist.
--resume PATHrestaure cet état et reprend le planning à partir de l’époque du point de contrôle. C’est la méthode habituelle pour démarrer un nouveau dossier d’expérience à partir d’un point de contrôle existant.--resume autoreprend sur place : avec--outputet--experimentdéfinis, il continue depuislast.pth.tardans ce dossier d’expérience s’il existe, et démarre sinon une nouvelle exécution. La même commande peut être relancée après une interruption. L’historique des points de contrôle, le suivi de la meilleure métrique etsummary.csvse poursuivent de manière cohérente, de sorte que l’éviction de--checkpoint-histetmodel_bestrestent corrects après le redémarrage.--stop-epoch Narrête l’entraînement aprèsNépoques complétées sans modifier le plan défini par--epochs. La dernière époque est toujours évaluée et sauvegardée, ce qui permet d’entraîner un modèle par segments.--save-epochs N [N ...]conserve des instantanés immuablesmilestone-N.pth.tar(N étant le nombre d’époques terminées) en dehors de l’historique classé. Ils sont liés de manière dure àlast.pth.tarlorsque le système de fichiers le permet, ce qui ne génère aucun espace supplémentaire, et une évaluation est forcée à ces époques.
Ensemble, ces éléments facilitent la réalisation manuelle d’expériences de type warmup-stable-decay (WSD) : entraînez une fois un tronc stable, puis dérivez des cooldowns indépendants à partir de ses jalons, en conservant l’état complet de l’optimiseur.
# 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-d6La décroissance occupe les --decay-epochs derniers de l’horaire, donc un refroidissement de D époques à partir de P époques complétées correspond à --epochs P+D --decay-epochs D (soustraire --warmup-epochs de --epochs lorsque --warmup-prefix est utilisé). sweep.py ci-dessous automatise cette opération.
Balayages d'hyperparamètres
sweep.py (PyTorch 2.5 ou version ultérieure) planifie et exécute des balayages sur n’importe quels arguments de train.py, éventuellement avec un branchement WSD. Il génère un fichier train.py --config complet par tâche, ainsi qu’un plan.json contenant le graphe de dépendances des tâches, puis exécute les tâches prêtes sur un pool de GPU locaux. Le plan reste fixe pendant l’exécution des workers. Chaque tâche est une invocation ordinaire de train.py avec son propre dossier d’expérience, et chaque run.sh généré peut être exécuté manuellement ou confié à un autre planificateur.
Un balayage rapide ne nécessite pas de fichier de spécification. Les axes de recherche proviennent de --sweep, la configuration de base des arguments de train.py qui suivent -- :
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 liste les GPU sur lesquels exécuter la tâche, en tant qu’indices dans CUDA_VISIBLE_DEVICES lorsque celui-ci est défini (par exemple, dans une allocation Slurm).
Un balayage WSD partage un tronc stable par combinaison d'hyperparamètres sur de nombreux cooldowns. Pour chaque taux d'apprentissage ci-dessous, le tronc s'exécute jusqu'à 30 époques avec des jalons à 18, 24 et 30, et un cooldown de 6 époques est dérivé de chaque jalon, soit 4 troncs et 12 cooldowns au total au lieu de 12 exécutions complètes. Les cooldowns démarrent dès que leur jalon existe, tandis que le tronc continue. Les tâches nécessitant plus d'une GPU sont lancées avec 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 --ampLe planificateur possède les drapeaux suivants, ils ne peuvent donc pas être fournis sur la ligne de commande ni balayés.
À chaque balayage :
--output--experiment--resume--stop-epoch--save-epochs
De plus, dans un balayage WSD :
--sched(peut être fourni sous la formewsd, ce que le planificateur définit de toute façon)--epochs--decay-epochs--lr-decay-fn
Une spécification YAML ajoute la recherche aléatoire avec des distributions, des axes appariés (zippés), des répétitions sur des graines et un fichier de configuration de base, voir la docstring en haut de sweep.py pour le schéma. python sweep.py plan spec.yaml écrit les configurations et graph.dot sans rien exécuter.
Le balayage est enregistré dans output/sweeps/<name>/, par rapport au fichier de spécification (ou au répertoire de travail pour un balayage en ligne de commande), avec un dossier par essai, nommé d’après les valeurs balayées (trial-000-lr0.001), chacun contenant les dossiers d’expériences du job. Chaque point de contrôle conservé est une copie complète incluant l’état de l’optimiseur, de sorte que les jobs de balayage conservent un point de contrôle classé en plus de last.pth.tar et model_best.pth.tar (--checkpoint-hist 1), et les balayages WSD font avancer le planning à chaque mise à jour (--sched-on-updates). Définir l’un ou l’autre dans la configuration de base l’annule. Pendant son exécution, ou par la suite :
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.csvLes résultats comparent les essais à budgets égaux. Un balayage WSD affiche une ligne par essai et une colonne par cooldown (p24-d6 correspond à un cooldown de 6 époques à partir de 24 époques) avec la métrique finale, moyennée sur les répétitions, et le meilleur de chaque colonne est marqué. Un balayage simple est classé selon sa métrique finale au sein de chaque budget d'époques. results.csv contient tous les jobs, segments de tronc inclus, avec la meilleure époque de chacun. En l'absence d'un ensemble de validation, le classement repose sur la perte d'entraînement, et les points de contrôle de fin peuvent être évalués avec validate.py.
L’exécution de sweep.py run à nouveau sur un balayage interrompu le reprend : les tâches terminées sont ignorées et une tâche avec une exécution partielle reprend à partir de son propre last.pth.tar. Les travailleurs sur plusieurs machines partageant le dossier de balayage peuvent chacun l’exécuter. Ils se coordonnent via des verrous flock sous state/locks, que chaque processus d’entraînement d’une tâche détient également, de sorte qu’une tâche dont le travailleur est mort n’est ni relancée ni replanifiée tant que son dernier processus n’a pas quitté. Un balayage partagé par plusieurs machines nécessite un système de fichiers dont le flock fonctionne entre toutes, tel que NFSv4 ou Lustre monté avec -o flock. Les montages avec un verrouillage uniquement local ne se coordonnent pas entre les machines, il faut donc vérifier le verrouillage depuis chaque client. L’arrêt d’un travailleur (Ctrl-C, ou SIGTERM de scancel) arrête ses tâches, et l’exécution manuelle du run.sh d’une tâche contourne la coordination.
Les fichiers de verrou sous state/locks sont permanents : ne les supprimez ni ne les remplacez jamais pour effacer un balayage occupé. Arrêtez ou attendez plutôt que ses workers et processus d’entraînement se terminent. Un statut running (gone) signifie que le verrou d’entraînement est libre mais que la tentative n’a pas été réconciliée ; exécutez un worker pour le résoudre et reprendre le travail inachevé. status et results ne réparent pas l’état du job.
Un travailleur lit le plan une seule fois au démarrage. Pour modifier un balayage, arrêtez tous ses travailleurs et processus d’entraînement, planifiez à nouveau avec --force, puis relancez-les. Avant le démarrage de tout travail, tout élément du plan peut être modifié. Par la suite, ses travaux d’entraînement ne peuvent être qu’étendus : plus d’essais, de périodes de refroidissement ou de points WSD après les existants, chaque tronc reprenant là où il s’était arrêté. Les modifications des travaux d’entraînement existants nécessitent un nouveau balayage. Les chemins générés sont figés lors de l’écriture du plan ; planifiez donc à nouveau sous un nouvel emplacement plutôt que de déplacer le dossier du balayage.
Si la planification est interrompue, les workers détectent les configurations ou les launchers issus d’une écriture de plan incomplète et refusent de démarrer. Relancez la commande de planification d’origine avec --force pour terminer ou réparer le plan, puis redémarrez les workers. Chaque écriture de plan réussie publie une génération correspondante dans plan.json, ainsi que les configurations et les launchers ; un plan inchangé et complet n’écrit rien.
Par exemple, pour étendre le balayage WSD de l’interface en ligne de commande ci-dessus à 36 époques stables, arrêtez ses travailleurs et ses tâches, puis répétez les arguments de planification d’origine avec le point ultérieur ajouté :
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,1Pour un balayage YAML, ajoutez le point à la spécification d’origine et exécutez python sweep.py plan spec.yaml --force avant de redémarrer. Gardez wsd.decay_epochs explicite et inchangé ([6] dans cet exemple) : sa valeur par défaut est de 20 % du point final, de sorte que l’extension de l’horizon peut modifier les périodes de refroidissement existantes. Conservez les identifiants des essais existants ; le réordonnancement ou l’élargissement des axes de la grille peut renuméroter les essais. Avec lr_noise, le calendrier du tronc dépend de son horizon, de sorte que l’ajout d’un point ultérieur à un balayage déjà démarré nécessite un nouveau balayage.
Les paramètres d’entraînement appartiennent au plan : utilisez le bloc train de la spécification, ou les arguments après -- lors de la création d’un balayage CLI. Il n’existe pas de substitutions d’entraînement à l’exécution. Les paramètres de rapport, tels que la métrique de classement, et les paramètres de sortie (checkpoint_hist, log_wandb, wandb_project, wandb_tags) peuvent être modifiés hors ligne avec --force sans réinitialiser l’état du travail ni modifier l’identité de l’entraînement. Les paramètres de sortie s’appliquent aux tentatives futures ; les travaux terminés ne sont pas relancés.
sweep.py nécessite flock de type Unix : testé sur Linux, censé fonctionner mais non testé sur macOS. Windows natif n’est pas pris en charge ; utilisez WSL2. Les verrous ne survivent pas à une coupure réseau qui dure plus longtemps qu’un bail NFS : un processus déconnecté peut continuer à entraîner après avoir perdu ses verrous, ce qui permet à une autre machine de lancer une tentative en double.
Scripts de validation / inférence
Les scripts de validation et d'inférence sont similaires dans leur utilisation. L'un affiche des métriques sur un ensemble de validation, tandis que l'autre affiche les identifiants des classes topk dans un fichier csv. Spécifiez le dossier contenant les images de validation, et non le dossier de base comme dans le script d'entraînement.
Pour valider avec les poids pré-entraînés du modèle (s’ils existent) :
python validate.py --data-dir /imagenet/validation/ --model seresnext26_32x4d --pretrained
Pour exécuter une inférence à partir d'un point de contrôle :
python inference.py --data-dir /imagenet/validation/ --model mobilenetv3_large_100 --checkpoint ./output/train/model_best.pth.tar
Exemples d'entraînement
Recettes d'entraînement ImageNet
Ces commandes correspondent aux recettes HParams sélectionnées, où vous trouverez des configurations YAML copiables, des gists source et des résultats de points de contrôle publiés. Elles supposent des données ImageFolder sous /data/imagenet/train/ et /data/imagenet/validation/. --batch-size est par GPU.
Les taux d'apprentissage explicites dans les exemples MobileNetV4 et ConvNeXt s'appliquent aux tailles de lot globales indiquées ;
ils ne sont pas ajustés automatiquement si le nombre de GPU change.
MobileNetV4 Conv Medium, ImageNet-1k
Depuis mnv4_cm_r256_e500_gpu2.yaml : 2 GPU, lot global de 1024, entraînement à 256 px, et 20 époques de montée en charge + 500 époques cosinus. Les poids correspondants sont 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-cmUtilisez --amp-dtype float16 si votre GPU ne prend pas en charge bfloat16 ; --torchcompile inductor est facultatif.
ViT Medium avec registres, ImageNet-1k
Depuis train-vit_medium_reg4-4gpu-in1k.yaml : 4 GPU, lot global de 1024 et 600 époques incluant le réchauffement + 10 époques de refroidissement. Les poids correspondants sont 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-sbbCette exécution utilise AdamW sans EMA. Son LR maximal est d'environ 0.001131 au lot global 1024.
ConvNeXt Tiny, fine-tuning d’ImageNet-12k à ImageNet-1k
Depuis hparams_84_00-convnext_tiny.in12k-args.yaml :
8 GPU, lot global de 4096 et 75 époques incluant le warmup + 10 époques de cooldown.
Chargez les poids ImageNet-12k et définissez --num-classes 1000 pour remplacer le classifieur en vue du fine-tuning.
La famille de points de contrôle résultante est 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-ftClassification multi-étiquettes
Utilisez --task multilabel pour les images avec plusieurs étiquettes indépendantes.
--num-classesdéfinit la taille du vocabulaire.--target-format indices(par défaut) lit la colonne cible comme une liste d’identifiants de classes positifs, à base zéro. Les étiquettes sont converties en cibles multi-hot flottantes avant le groupement par lots, et les listes vides représentent des images sans étiquettes positives.--target-format multihotlit un vecteur multi-hot dense de longueur--num-classes(valeurs bool, int ou float dans[0, 1]). Le vecteur est utilisé tel quel, de sorte que les valeurs douces entraînent directement avec BCE et sont binarisées à 0,5 pour les métriques d’évaluation. Les cartes de classes pour les cibles multi-hot doivent être indexées par l’indice de classe source.
Sans ce drapeau, chaque liste est lue comme des indices de classes, car un vecteur multi-hot d'entiers est indistinguable d'une liste d'indices.
Le jeu de données de pathologie végétale fournit ce format : une colonne image et une colonne labels contenant une séquence de valeurs ClassLabel. Ses six classes sont complex, frog_eye_leaf_spot, healthy, powdery_mildew, rust et scab. Par exemple, [5, 1, 0] devient [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 prend en charge le streaming avec le même format cible. Prise en charge des lecteurs :
- Hugging Face
hfdsethfidsprennent en charge les cibles multi-étiquettes. - WebDataset (
wds) prend en charge les listes d’identifiants de classes stockés dans le fichier annexe.jsonde chaque échantillon, sous le champ nommé par--target-key. En l’absence de--target-key, le fichier.clsfournit un seul index de classe. - Lecteurs de dossiers et de fichiers tar renvoient des indices de classe uniques.
Les jeux de données qui stockent un champ binaire par étiquette, comme Wake Vision, utilisent ces paramètres :
--target-key person,depiction,body_partsélectionne une liste de champs séparés par des virgules. Chaque champ devient une classe dans l’ordre indiqué, et les valeurs supérieures à zéro sont comptées comme positives. Cela fonctionne avec les lecteurshfds,hfidsettfds, ainsi qu’avec WebDataset lorsque les champs sont dans le fichier annexe.json.--num-classesdoit être égal au nombre de champs.--target-formatreste à sa valeur par défaut, car les clés multi-champs définissent leur propre format.- Les chemins d’accès aux champs imbriqués utilisent
/, par exemple--input-key input --target-key output/pollen_output,output/wasps_outputpour le jeu de données TFDSbee_dataset. Les clés cibles uniques acceptent les mêmes chemins. Un nom de champ littéral contenant/(tel queimage/filenamedans TFDS) a la priorité sur un chemin.
Les chargeurs Standard et NaFlex prennent en charge les cibles multi-étiquettes, y compris mixup et cutmix ; l'entraînement NaFlex nécessite actuellement un jeu de données de type map tel que hfds.
La tâche s’entraîne avec l’entropie croisée binaire avec logits. Le lissage est par défaut nul pour l’entraînement multi-étiquettes ; définir --smoothing s déplace chaque cible binaire vers target * (1 - s) + 0.5 * s, appliqué par Mixup/CutMix lorsqu’ils sont actifs et par la fonction de perte dans le cas contraire. Les options existantes --bce-sum et --bce-target-thresh s’appliquent également. La distillation et la perte JSD ne sont pas prises en charge par cette tâche.
--loss sélectionne d’autres pertes (bce est la valeur par défaut pour les étiquettes multiples) :
asl: Asymmetric Loss. Elle suit le même comportement de lissage et de Mixup/CutMix que BCE et est calculée en float32, ce qui la rend compatible avec--amp.--asl-gamma-negdéfinit le paramètre de focalisation pour les cibles négatives (valeur par défaut : 4).--asl-gamma-posdéfinit le paramètre de focalisation pour les cibles positives (valeur par défaut : 1).--asl-clipdéfinit la marge de probabilité pour les négatifs (valeur par défaut 0,05).--asl-reductiona par défaut la valeurbatchmean, qui somme la perte sur les classes et fait la moyenne sur le lot.sumrestaure la réduction ASL d'origine, qui somme également sur le lot, de sorte que le taux d'apprentissage effectif est mis à l'échelle en fonction de la taille du lot.
twoway: Two-way Multi-Label Loss, qui contraste les logits positifs et négatifs entre les classes de chaque échantillon et les échantillons de chaque classe. Ses logits sont des scores de classement, la métrique mAP est donc la plus pertinente ; le F1 à un seuil sigmoïde n'est pas calibré.--twoway-tpdéfinit la température des logits positifs (valeur par défaut : 4).--twoway-tndéfinit la température du logit négatif (valeur par défaut 1).
zlpr: ZLPR, une extension multi-étiquettes de l'entropie croisée softmax, sans hyperparamètre, avec 0 comme seuil de logit intégré.db: Distribution-Balanced Loss pour les données multi-étiquettes à longue traîne. BCE avec des poids de rééquilibrage par exemple qui tiennent compte de la co-occurrence des étiquettes, une régularisation tolérante aux négatifs des logits, et un terme focal. Il prend en charge Mixup/CutMix et le lissage, avec des valeurs par défaut issues de la configuration de référence DB :--db-neg-scaledéfinit l'échelle des logits négatifs (2 par défaut).--db-init-biasdéfinit le facteur de décalage des logits a priori de la classe (valeur par défaut 0.05).--db-focal-gammadéfinit le focal focusing (valeur par défaut : 2).--class-statsfournit les nombres de labels d’entraînement requis sous forme de fichier de statistiques de classes (ci-dessous).
twoway et zlpr nécessitent des cibles binaires, ils ne prennent donc pas en charge Mixup/CutMix ni --smoothing.
Pour les distributions de labels déséquilibrées, bce et asl prennent en charge deux drapeaux de pondération :
--loss-pos-weightpondère le terme positif de chaque classe, équilibrant les positifs par rapport aux négatifs au sein d'une classe. Cela déplace également les prédictions vers le positif (rappel plus élevé à un seuil fixe, probabilités moins calibrées).--loss-class-weightpondère la perte globale de chaque classe, équilibrant ainsi les classes entre elles tout en maintenant la calibration.
Chaque drapeau accepte des poids explicites (une valeur unique, une liste séparée par des virgules avec une valeur par classe, ou un fichier) ou le nom d’une méthode qui dérive les poids à partir des compteurs d’étiquettes d’entraînement fournis avec --class-stats :
--loss-pos-weight neg_pos: négatifs / positifs par classe.--loss-class-weight inv_freq: fréquence inverse de classe, normalisée pour une moyenne de 1.--loss-class-weight effective_num: poids class-balanced issus du nombre effectif d'échantillons, normalisés pour une moyenne de 1.
Options de poids dérivés :
--loss-weight-powerdéfinit l'exposant pourneg_posetinv_freq(valeur par défaut 1), avec 0,5 pour un ré-pondération plus douce par racine carrée.--loss-weight-betadéfinit beta pour les poids deeffective_num(valeur par défaut 0.999).--loss-weight-maxlimite les poids dérivés.
Les deux drapeaux de pondération peuvent utiliser les mêmes statistiques. class_weights.py compte les étiquettes d’un split, avec les mêmes arguments de jeu de données que train.py, et écrit le fichier de statistiques des classes (--method prévisualise les poids d’une méthode) :
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 ...Drapeaux obsolètes :
| Ancien drapeau | Remplacement |
|---|---|
--bce-loss | --loss bce |
--jsd-loss | --loss jsd |
--bce-pos-weight | --loss-pos-weight |
Les rapports de validation affichent la perte BCE, map (précision moyenne moyenne), micro_f1, macro_f1 et sample_f1. Les métriques sont exprimées en pourcentage et utilisent l’ensemble de validation complet, y compris les prédictions collectées sur les rangs distribués. Le bourrage du sampler distribué ordonné est exclu. Le mAP exact conserve les prédictions sur le CPU jusqu’à la fin de l’évaluation, si bien que son utilisation mémoire augmente avec le nombre d’exemples et de classes. Les classes sans exemples positifs contribuent à un AP nul ; les valeurs F1 avec un dénominateur nul sont nulles.
--eval-metric map est la valeur par défaut pour la sélection des points de contrôle et la planification. F1 utilise un seuil de probabilité sigmoïde de 0,5, configurable avec --multilabel-threshold ; mAP est indépendant de ce seuil. Les sorties du modèle restent des logits, il convient donc d’appliquer une sigmoïde pour obtenir des probabilités de classes indépendantes lors de l’utilisation du modèle entraîné.
Recettes ImageNet historiques
Ces exécutions antérieures restent des références utiles pour l’entraînement avec RMSProp, SGD et AugMix/JSD. Le matériel et les métriques rapportées décrivent les exécutions d’origine. Pour les recettes AdamW plus récentes, commencez par les exemples ci-dessus ou les collections de gists.
EfficientNet-B2 avec RandAugment - 80,4 top-1, 95,1 top-5
L'exécution d'origine utilisait des cartes Titan RTX doubles avec NVIDIA Apex ; l'option --amp actuelle utilise l'AMP natif de PyTorch :
./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 avec RandAugment - 80,5 top-1, 94,9 top-5
L'exécution d'origine utilisait des cartes Titan RTX doubles avec NVIDIA Apex ; l'option --amp actuelle utilise l'AMP natif de PyTorch :
./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 et SE-ResNeXt-26-T
Ces hparams (ou similaires) fonctionnent bien pour une large gamme d’architectures ResNet. Il est généralement judicieux d’augmenter le nombre d’époques à mesure que la taille du modèle augmente… soit environ 180-200 pour ResNe(X)t50, et 220+ pour les modèles plus grands. Augmentez la taille du lot et le LR proportionnellement pour de meilleures GPU ou avec AMP activé. Ces paramètres étaient destinés à 2 cartes 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 112EfficientNet-B3 avec RandAugment - 81,5 top-1, 95,7 top-5
L’entraînement de ce modèle a démarré avec la même ligne de commande que pour EfficientNet-B2 w/ RA ci-dessus. Après près de trois semaines d’entraînement, le processus a planté. Les résultats n’étaient pas exceptionnels, j’ai donc repris l’entraînement à plusieurs reprises en ajustant quelques paramètres (augmentation de la probabilité RE, diminution de rand-aug, augmentation de ema-decay). Rien ne semblait concluant. J’ai fini par faire la moyenne des meilleurs checkpoints de toutes les reprises. Le résultat est médiocre avec la résolution/crop par défaut, mais surprenamment bien meilleur avec un crop de test sur l’image complète de 1.0.
EfficientNet-B0 avec RandAugment - 77,7 top-1, 95,3 top-5
Michael Klachko a obtenu ces résultats avec la ligne de commande pour B2 adaptée à une taille de lot plus grande, avec le taux de dropout B0 recommandé de 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 .048ResNet50 avec la perte JSD et RandAugment (propre + 2x RA augs) - 79,04 top-1, 94,39 top-5
Entraîné sur deux cartes 1080Ti plus anciennes, ce processus a pris un certain temps. Le résultat de validation sur ImageNet n’est que légèrement, et non statistiquement, meilleur que mon premier bon entraînement AugMix à 78,99. Cependant, ces poids sont plus robustes lors des tests sur ImageNetV2, ImageNet-Sketch, etc. Contrairement à mes premières exécutions AugMix, j’ai activé SplitBatchNorm, désactivé l’effacement aléatoire sur le split propre et augmenté la probabilité d’effacement aléatoire sur les 2 chemins augmentés.
./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 reduceEfficientNet-ES (EdgeTPU-Small) avec RandAugment - 78,066 top-1, 93,926 top-5
Entraîné par Andrew Lavin avec 8 cartes V100. L’EMA du modèle n’a pas été utilisé ; le point de contrôle final est la moyenne des 8 meilleurs points de contrôle obtenus pendant l’entraînement.
./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 avec RandAugment - 79.762 top-1, 94.60 top-5
Ces paramètres fonctionneront également bien avec SE-ResNeXt-50 et SK-ResNeXt-50, et probablement 101. Je les ai utilisés pour le SK-ResNeXt-50 32x4d que j'ai entraîné avec 2 GPU en utilisant un LR légèrement plus élevé par taille de lot effective (lr=0.18, b=192 par GPU). La ligne de commande ci-dessous est ajustée pour un entraînement sur 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