timm documentation
Planificateurs de taux d'apprentissage
Planificateurs de taux d'apprentissage
Cette page contient la documentation de référence de l’API des planificateurs de taux d’apprentissage inclus dans timm, ainsi qu’un aperçu de leur création et de leur progression.
Utilisation
Les planificateurs sont créés par leur nom à l'aide de create_scheduler_v2, qui renvoie le planificateur et le nombre total d'époques d'entraînement (y compris tout préfixe de montée en charge, cycles et refroidissement, voir ci-dessous). Contrairement à torch.optim.lr_scheduler, les planificateurs de timm ne comptent pas eux-mêmes les étapes. Ils sont conçus pour être sans état : le taux d'apprentissage est une fonction de la configuration du planificateur et d'un nombre explicite d'époques ou de mises à jour, de sorte que la reprise d'une exécution n'a besoin que de l'époque, et aucun état de planificateur n'est stocké dans les points de contrôle. La boucle d'entraînement transmet explicitement l'époque ou le nombre de mises à jour :
scheduler.step(epoch)à la fin de chaque époque, avec l'index de l'époque suivante (epoch + 1)scheduler.step_update(num_updates)après chaque mise à jour de l’optimiseur, avec le nombre de mises à jour effectuées jusqu’à présent
Un planificateur est incrémenté par époque ou par mise à jour (step_on_epochs) ; l'autre appel est un no-op, de sorte qu'une boucle d'entraînement peut effectuer les deux appels et prendre en charge les deux modes.
import timm
from timm.optim import create_optimizer_v2
from timm.scheduler import create_scheduler_v2
model = timm.create_model('resnet50')
optimizer = create_optimizer_v2(model, opt='adamw', lr=1e-3, weight_decay=0.05)
updates_per_epoch = len(loader) # optimizer updates per epoch
# Cosine decay w/ 5 epochs of linear warmup, stepped per update for a smooth schedule.
scheduler, num_epochs = create_scheduler_v2(
optimizer,
sched='cosine',
num_epochs=100,
warmup_epochs=5,
min_lr=1e-6,
step_on_epochs=False,
updates_per_epoch=updates_per_epoch,
)
num_updates = 0
for epoch in range(num_epochs):
for batch in loader:
... # forward, backward, optimizer.step()
num_updates += 1
scheduler.step_update(num_updates=num_updates)
scheduler.step(epoch + 1) # pass the eval metric too for 'plateau', scheduler.step(epoch + 1, metric)Les durées (num_epochs, warmup_epochs, decay_epochs, …) sont toujours exprimées en époques ; la fabrique les convertit en mises à jour lorsque step_on_epochs=False. Les planificateurs peuvent également être construits directement à partir de leurs classes, les durées étant alors exprimées dans l’unité dans laquelle ils sont incrémentés (t_in_epochs).
Le script d’entraînement (train.py) expose les arguments de la fabrique via ces drapeaux :
--schedsélectionne le planning.--epochsdéfinit la durée du planning.--sched-on-updatesétapes par mise à jour au lieu de par époque.--warmup-epochsdéfinit la durée du warmup.--warmup-lrdéfinit le taux d'apprentissage initial de la phase de montée en charge.--warmup-prefixajoute un échauffement avant le planning au lieu de superposer son début.--min-lrdéfinit le taux d'apprentissage minimal.--decay-epochsdéfinit l'intervalle de décroissance par étape ou la durée finale de la décroissance pour WSD / rsqrt.--decay-milestonesdéfinit les époques de décroissance pour le planning multistep.--decay-ratedéfinit le facteur d'atténuation, ou l'exposant pour le plan polynomial.--cooldown-epochsajoute des époques au taux d'apprentissage minimal après la fin du planning.--patience-epochsdéfinit la patience du planificateur plateau.--lr-noisesélectionne la partie du calendrier avec du bruit sur le taux d'apprentissage.--lr-noise-pctlimite l'amplitude du bruit.--lr-noise-stddéfinit l'écart-type du bruit.--lr-cycle-muldéfinit le multiplicateur de la longueur du cycle.--lr-cycle-decaydéfinit le multiplicateur du taux d'apprentissage de pointe entre les cycles.--lr-cycle-limitdéfinit le nombre de cycles.--lr-k-decaydéfinit le k-decay pour les calendriers cosinus / polynomiaux.--lr-decay-fnsélectionne la fonction de décroissance finale pour WSD / rsqrt.--lr-stable-timescaledéfinit l'échelle de temps de la phase stable rsqrt.
Planifications
sched | Classe | Planification |
|---|---|---|
cosine | CosineLRScheduler | Recuit cosinus depuis le lr de base jusqu'à min_lr (SGDR), redémarrages facultatifs (cycles) et k-decay |
tanh | TanhLRScheduler | Décroissance par tangente hyperbolique (article), redémarrages optionnels |
poly | PolyLRScheduler | Décroissance polynomiale vers min_lr, la puissance est donnée par decay_rate, redémarrages facultatifs et k-décroissance |
step | StepLRScheduler | lr multipliée par decay_rate toutes les decay_epochs |
multistep | MultiStepLRScheduler | lr multiplié par decay_rate à chacun des epochs decay_milestones |
plateau | PlateauLRScheduler | Déprécié. lr multiplié par decay_rate lorsque la métrique d’évaluation n’a pas progressé depuis patience_epochs, uniquement par pas d’époque |
wsd | WSDLRScheduler | Warmup-stable-decay (MiniCPM), lr constant puis une décroissance vers min_lr sur les decay_epochs finaux, décroissance 1-sqrt par défaut (paper) |
rsqrt | WSDLRScheduler | Décroissance de l'inverse de la racine carrée avec un refroidissement linéaire sur les decay_epochs derniers (Big Vision) |
Options courantes
- Warmup.
warmup_epochsde réchauffement linéaire depuiswarmup_lrjusqu'au taux d'apprentissage de base, pris en charge par tous les plans de progression.warmup_prefix: par défaut, le warmup chevauche le début du planning (le planning est calculé à partir de l'époque 0, le warmup remplace ses premières époques), de sorte quenum_epochsest la longueur totale. Avecwarmup_prefix=True, le planning commence après le warmup et le warmup est ajouté au total.- Pour
wsdetrsqrt, la phase stable commence toujours après le warmup, sanswarmup_prefixles phases stable et de décroissance sont ajustées surnum_epochs - warmup_epochsde sorte quenum_epochsreste le total.
min_lr: le taux d'apprentissage auquel les calendriers de décroissance (cosine,tanh,poly,wsd,rsqrt) parviennent à la fin, et une borne inférieure pourplateau.
Le planificateur plateau est obsolète et sera supprimé dans une future version. Il ne correspondait jamais à la conception sans état décrite ci-dessus : son lr dépend de l’historique de la métrique d’évaluation plutôt que de l’époque, et cet historique (meilleure métrique, compteurs de patience et de refroidissement) n’est pas sauvegardé dans les points de contrôle, si bien qu’une exécution reprise redémarre la logique de plateau. La prise en charge des points de contrôle ne sera pas ajoutée. Un plateau de validation est également un signal faible pour déterminer quand effectuer l’annealing ; un planificateur fixe tel que cosine ou wsd est reproductible et se reprend exactement, et un balayage WSD (voir Balayages d’hyperparamètres) compare les périodes de refroidissement à plusieurs budgets à partir d’une seule exécution stable.
cooldown_epochs: nombre d’époques maintenues àmin_lraprès la fin du planning (cosine,tanh,poly,wsd,rsqrt), ajouté aunum_epochsretourné. Comme le planning atteintmin_lrune étape après sa dernière étape, une époque de refroidissement est également un moyen d’entraîner àmin_lrlors d’un pas par époque.- Cycles (
cosine,tanh,poly) :cycle_limit > 1redémarre le planning, chaque cycle étantcycle_mulfois plus long et son pic de lr étant multiplié parcycle_decaypar rapport au précédent. Lenum_epochsretourné couvre tous les cycles. k_decay(cosine,poly) : k-decay modifie la forme du déclin (t ** k),k > 1maintient le taux d'apprentissage élevé plus longtemps.- Bruit :
noiseajoute un bruit multiplicatif aléatoire au taux d'apprentissage sur une plage du planning, définie par des fractions denum_epochs(un début, ou un début et une fin), limitée parnoise_pct.
WSD et rsqrt
Le WSDLRScheduler comporte trois phases : un réchauffement linéaire, une phase stable et
un déclin jusqu'à min_lr.
decay_epochsdéfinit la durée finale du déclin. Une valeur comprise entre 0 et 1 représente une fraction de la longueur stable + déclin, 20 % par défaut.decay_fn(--lr-decay-fn) sélectionne1-sqrt(par défaut pourwsd),linear(par défaut pourrsqrt),cosine,powerouexp.stable_timescale(--lr-stable-timescale, en époques) contrôle la phase stablersqrt, qui décroît selon(1 + t / timescale) ** -0.5à partir de la fin du warmup. Sa valeur par défaut est la durée du warmup et elle doit être définie lorsqu'il n'y a pas de warmup.
La classe prend également en charge une phase stable power généralisée et des fonctions de décroissance personnalisées.
L’anneal final est l’étape où les calendriers WSD tirent le plus de bénéfice. Utilisez donc un pas par mise à jour (--sched-on-updates) ou ajoutez une époque de refroidissement lorsque la phase de décroissance ne dure que quelques époques. Avec un pas par époque, la dernière époque d’une courte décroissance est nettement supérieure à min_lr (environ 10 % du taux d’apprentissage de base pour la dernière des 5 époques de décroissance avec 1-sqrt).
# 300 epochs, 5 epoch warmup, constant lr, then a 1-sqrt decay over the final 20%
scheduler, num_epochs = create_scheduler_v2(
optimizer, sched='wsd', num_epochs=300, warmup_epochs=5, decay_epochs=0.2,
step_on_epochs=False, updates_per_epoch=updates_per_epoch,
)Échelles de lr des groupes de paramètres
Les groupes de paramètres avec un champ lr_scale (par exemple, les groupes de décroissance du taux d'apprentissage par couche issus de param_groups_layer_decay) voient leur taux d'apprentissage planifié multiplié par leur échelle. Le taux d'apprentissage de base de chaque groupe est enregistré en tant que initial_lr dans le groupe lors de la création du planificateur.
Reprise
À mesure que les nombres d’étapes sont transmis, un planificateur pour une exécution reprise est mis en place en le créant comme pour l’exécution d’origine puis en l’avançant jusqu’au point de reprise, scheduler.step(start_epoch) ou scheduler.step_update(start_epoch * updates_per_epoch). state_dict() / load_state_dict() sauvegardent et restaurent les attributs du planificateur.
API
Fonctions d'usine
timm.scheduler.create_scheduler_v2
< source >( optimizer: Optimizersched: str = 'cosine'num_epochs: int = 300decay_epochs: typing.Optional[float] = Nonedecay_milestones: typing.List[int] = (90, 180, 270)cooldown_epochs: int = 0patience_epochs: int = 10decay_rate: float = 0.1min_lr: float = 0.0warmup_lr: float = 1e-05warmup_epochs: int = 0warmup_prefix: bool = Falsenoise: typing.Union[float, typing.List[float]] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42cycle_mul: float = 1.0cycle_decay: float = 0.1cycle_limit: int = 1k_decay: float = 1.0decay_fn: typing.Optional[str] = Nonestable_timescale: typing.Optional[float] = Noneplateau_mode: str = 'max'step_on_epochs: bool = Trueupdates_per_epoch: int = 0 )
Paramètres
- optimizer — optimiseur à planifier
- sched — nom du planificateur, l’un des éléments suivants : ‘cosine’, ‘tanh’, ‘step’, ‘multistep’, ‘poly’, ‘wsd’, ‘rsqrt’, ‘constant’, ‘plateau’ (obsolète) ou ‘none’ pour aucun planificateur (renvoie None, le lr de l’optimiseur est laissé inchangé). ‘constant’ maintient le lr après le warmup avec l’application de lr_scale du groupe de paramètres (décroissance du lr par couche).
- num_epochs — nombre d'époques dans le planning (excluant le warmup si warmup_prefix, excluant le cooldown)
- decay_epochs — interval de décroissance du taux d'apprentissage (étape), ou longueur de la phase de décroissance (wsd / rsqrt) en époques, une valeur dans (0, 1) est une fraction de la longueur du planning. None = 90 (étape), 0.2 (wsd / rsqrt)
- decay_milestones — époques à laquelle diminuer le lr (multistep)
- cooldown_epochs — nombre d'époques pendant lesquelles le taux d'apprentissage est maintenu à min_lr après la fin du planning
- patience_epochs — nombre d'époques sans amélioration avant de réduire le taux d'apprentissage (plateau, obsolète)
- decay_rate — taux de décroissance du taux d'apprentissage (step, multistep, plateau), puissance polynomiale (poly)
- min_lr — borne inférieure du taux d'apprentissage pour les planificateurs qui y convergent
- warmup_lr — lr au début du warmup
- warmup_epochs — époques de réchauffage linéaire
- warmup_prefix — exclut la période de warmup de num_epochs (ajoutée au total), wsd / rsqrt sont toujours préfixés par warmup, avec warmup_prefix=False leurs phases stable + decay s'insèrent dans num_epochs
- noise — points d’activation/désactivation du bruit de lr, exprimés en fractions de la longueur du planning
- noise_pct — pourcentage de la limite de bruit du taux d'apprentissage
- noise_std — écart-type du bruit du taux d'apprentissage
- noise_seed — graine de bruit pour lr
- cycle_mul — multiplicateur de la longueur du cycle (cosine, tanh, poly)
- cycle_decay — décroissance du taux d'apprentissage par cycle (cosinus, tanh, poly)
- cycle_limit — nombre de cycles (cosine, tanh, poly)
- k_decay — k-décroissance (cosinus, poly)
- decay_fn — fonction de phase de décroissance (wsd / rsqrt), None = ‘1-sqrt’ pour wsd, ‘linear’ pour rsqrt
- stable_timescale — échelle temporelle rsqrt en époques (rsqrt), None = warmup_epochs
- plateau_mode — « max » ou « min », la direction de la métrique (plateau)
- step_on_epochs — faire avancer le planning par époque, sinon par mise à jour (nécessite updates_per_epoch)
- updates_per_epoch — nombre de mises à jour de l'optimiseur par époque (step_on_epochs=False)
Créer un planificateur de taux d'apprentissage par nom.
Classes de planificateur
classe timm.scheduler.CosineLRScheduler
< source >( optimizer: Optimizert_initial: intlr_min: float = 0.0cycle_mul: float = 1.0cycle_decay: float = 1.0cycle_limit: int = 1warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Falset_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42k_decay: float = 1.0initialize: bool = True )
Décroissance cosinus avec redémarrages. Cela est décrit dans l'article https://arxiv.org/abs/1608.03983.
Inspiré de https://github.com/allenai/allennlp/blob/master/allennlp/training/learning_rate_schedulers/cosine.py
option k-decay basée sur k-decay: A New Method For Learning Rate Schedule - https://arxiv.org/abs/2004.05909
classe timm.scheduler.MultiStepLRScheduler
< source >( optimizer: Optimizerdecay_t: typing.List[int]decay_rate: float = 1.0warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Truet_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )
Planification du taux d'apprentissage multi-étapes avec échauffement et bruit.
En dehors de la phase de montée en charge, les jalons de décroissance sont comparés à t + 1, où t exclut la montée en charge lorsque warmup_prefix=True. Par exemple, sans montée en charge, un jalon de 10 s’applique à l’indice 9 du planning.
Cette convention de longue date diffère de MultiStepLR de PyTorch et est conservée pour assurer la compatibilité avec les calendriers d’entraînement existants.
classe timm.scheduler.PlateauLRScheduler
< source >( optimizer: Optimizerdecay_rate: float = 0.1patience_t: int = 10threshold: float = 0.0001cooldown_t: int = 0warmup_t: int = 0warmup_lr_init: float = 0.0lr_min: float = 0.0mode: str = 'max'noise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_type: str = 'normal'noise_pct: float = 0.67noise_std: float = 1.0noise_seed: typing.Optional[int] = Noneinitialize: bool = True )
Faites décroître le taux d'apprentissage d'un facteur chaque fois que la perte de validation stagne.
Obsolète : ce planificateur sera supprimé dans une future version. Les planificateurs timm sont conçus comme des fonctions sans état de l'époque ou du nombre de mises à jour, ce que ce planificateur piloté par métriques n'a jamais été. Son état (meilleure métrique, compteurs de patience et de refroidissement) n'est pas enregistré dans les points de contrôle d'entraînement, de sorte qu'une exécution reprise redémarre la logique de plateau, et le support des points de contrôle ne sera pas ajouté. Préférez un planificateur fixe tel que cosine ou wsd, la branche de refroidissement WSD dans sweep.py compare l'annealing à plusieurs budgets avec des planificateurs reproductibles.
classe timm.scheduler.PolyLRScheduler
< source >( optimizer: Optimizert_initial: intpower: float = 0.5lr_min: float = 0.0cycle_mul: float = 1.0cycle_decay: float = 1.0cycle_limit: int = 1warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Falset_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42k_decay: float = 1.0initialize: bool = True )
Planificateur de taux d'apprentissage polynomial avec échauffement, bruit et décroissance k
option k-decay basée sur k-decay: A New Method For Learning Rate Schedule - https://arxiv.org/abs/2004.05909
classe timm.scheduler.StepLRScheduler
< source >( optimizer: Optimizerdecay_t: floatdecay_rate: float = 1.0warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Truet_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )
classe timm.scheduler.TanhLRScheduler
< source >( optimizer: Optimizert_initial: intlb: float = -7.0ub: float = 3.0lr_min: float = 0.0cycle_mul: float = 1.0cycle_decay: float = 1.0cycle_limit: int = 1warmup_t: int = 0warmup_lr_init: float = 0.0warmup_prefix: bool = Falset_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )
Décroissance hyperbolique avec redémarrages. Cela est décrit dans l'article https://arxiv.org/abs/1806.01593
classe timm.scheduler.WSDLRScheduler
< source >( optimizer: Optimizert_initial: intdecay_t: intlr_min: float = 0.0stable_fn: str = 'constant'stable_timescale: typing.Optional[float] = Nonestable_power: float = 0.5decay_fn: typing.Union[str, typing.Callable[[float], float]] = '1-sqrt'decay_power: float = 0.5decay_ratio: float = 0.1warmup_t: int = 0warmup_lr_init: float = 0.0t_in_epochs: bool = Truenoise_range_t: typing.Union[typing.List[int], typing.Tuple[int, int], int, NoneType] = Nonenoise_pct: float = 0.67noise_std: float = 1.0noise_seed: int = 42initialize: bool = True )
Paramètres
- optimizer — optimiseur à planifier
- t_initial — durée des phases stable et de décroissance (époques ou mises à jour, voir
t_in_epochs) - decay_t — durée de la phase de décroissance, les
decay_tdernières étapes det_initial - lr_min — lr à la fin de la phase de décroissance
- stable_fn — fonction de phase stable, l’une des valeurs ‘constant’, ‘rsqrt’, ‘power’
- stable_timescale — échelle de temps des fonctions stables ‘rsqrt’ / ‘power’, par défaut
warmup_t - stable_power — exposant de la fonction stable « power »
- decay_fn — fonction de phase de décroissance, l’une des valeurs ‘linear’, ‘1-sqrt’, ‘cosine’, ‘power’, ‘exp’ ou un objet appelable
- decay_power — exposant de la fonction de décroissance « power »
- decay_ratio — fraction finale (avant normalisation) de la fonction de décroissance « exp »
- warmup_t — durée du warmup, un préfixe de
t_initial - warmup_lr_init — lr au début du warmup
- t_in_epochs —
test en époques (step()), sinon en mises à jour (step_update()) - noise_range_t — plage de bruit du taux d'apprentissage, voir
Scheduler - noise_pct — pourcentage de la limite de bruit du taux d'apprentissage
- noise_std — écart-type du bruit du taux d'apprentissage
- noise_seed — graine de bruit pour lr
- initialize — initialise le champ
initial_lrdu groupe de paramètres à partir de la lr actuelle
Planification du taux d'apprentissage Warmup-Stable-Decay (WSD) avec fonctions de stabilisation et de décroissance sélectionnables.
Trois phases : un réchauffement linéaire sur warmup_t étapes, une phase stable, et un décroissement vers lr_min sur les decay_t dernières étapes. t_initial est la longueur des phases stable et de décroissement, le réchauffement étant toujours un préfixe, le planning a donc une longueur totale de warmup_t + t_initial (voir get_cycle_length()), après quoi lr_min est maintenu.
NOTE : comme pour les autres planificateurs, lr_min est atteint à t = warmup_t + t_initial, soit une étape après la dernière étape planifiée, de sorte que la dernière étape planifiée est en deçà de celle-ci d'une étape de décroissance. Avec une phase de décroissance courte, exécutée par époque, cela est significatif (par exemple, la dernière des 5 époques de décroissance avec « 1-sqrt » est à environ 10 % du lr stable). L'annealing final est important pour WSD, il faut donc exécuter par mise à jour (t_in_epochs=False, --sched-on-updates dans train.py) ou ajouter une époque de refroidissement (maintenue à lr_min, --cooldown-epochs).
La fonction stable est évaluée en fonction du temps écoulé depuis la fin du warmup (t_s) et vaut 1 à t_s = 0, de sorte que le warmup transmet toujours au taux d'apprentissage de base. La fonction de décroissance mappe la progression de la décroissance frac dans [0, 1] vers un facteur allant de 1 à 0 et multiplie la valeur stable, si bien qu'une fonction stable décroissante continue de décroître pendant la phase de décroissance (comme dans le calendrier Big Vision rsqrt + refroidissement linéaire).
lr(t) = lr_min + (base_lr stable(t_s) - lr_min) decay(frac)
Fonctions stables :
constant: 1, le planning WSDrsqrt: (1 + t_s / timescale) ** -0.5, le plan de racine carrée réciproque Big Vision lorsquestable_timescale == warmup_t(par défaut)power: (1 + t_s / timescale) ** -stable_power, rsqrt généralisé (planificateur Power)
Fonctions de décroissance :
1-sqrt: 1 - sqrt(frac), le meilleur refroidissement selon https://arxiv.org/abs/2405.18392 (par défaut)linear: 1 - frac, le plan « trapézoïdal » et le refroidissement Big Visioncosine: 0.5 (1 + cos(pi frac))power: 1 - frac ** decay_power, 0.5 == ‘1-sqrt’, 1.0 == ‘linear’, 2.0 est un déclin ‘square’exp: décroissance exponentielle jusqu'à une fractiondecay_ratiode la valeur stable, normalisée pour atteindre lr_min- une fonction appelable
fn(frac) -> factorpour tout autre cas