Transformers documentation

Optimiseurs et planificateurs

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Optimiseurs et planificateurs

Un optimiseur met à jour les poids du modèle pendant l’entraînement. Le planificateur encapsule l’optimiseur et ajuste le taux d’apprentissage à chaque étape d’entraînement. Trainer crée les deux lorsqu’il appelle create_optimizer_and_scheduler().

                                    ┌────────────┐         ┌──────────────┐
                                    │ Optimizer  │         │  Scheduler   │
                                    │ (adamw_torch_fused)◄─│  (linear)    │
                                    │            │         │              │
                                    │ param_groups         |              |
                                    │  └ lr       ◄────────┤              |
                                    │  └ weight_decay      │              │
                                    └──────┬─────┘         └──────────────┘
                                           │                      
  ┌──── EACH TRAINING STEP ───────────────────────────────────────────┐
  │                                        │                          │
  │   model(batch)                         │                          │
  │       │                                │                          │
  │       ▼                                │                          │
  │     loss ──► loss.backward() ──► param.grad                       │
  │                                        │                          │
  │                          ┌─────────────┘                          │
  │                          ▼                                        │
  │              optimizer.step()                                     │
  │                          │                                        │
  │                          ▼                                        │
  │                   param.data updated                              │
  │                          │                                        │
  │                          ▼                                        │
  │              lr_scheduler.step()  ──► recalculates lr             │
  │                          │            writes to optimizer         │
  │                          ▼            .param_groups['lr']         │
  │              model.zero_grad()                                    │
  │                                                                   │
  └───────────────────────────────────────────────────────────────────┘

Configurez le comportement de l'optimiseur et du planificateur, comme lr_scheduler_type() et optim(), dans TrainingArguments. Les valeurs par défaut (l'optimiseur adamw_torch et le planificateur de montée en charge linear) constituent un bon point de départ pour la plupart des exécutions de fine-tuning.

from transformers import TrainingArguments

args = TrainingArguments(
    ...,
    # Optimizer
    optim="adamw_torch",          # or "adamw_torch_fused", "adafactor", "sgd", etc.
    learning_rate=2e-5,
    weight_decay=0.01,
    adam_beta1=0.9,
    adam_beta2=0.999,
    adam_epsilon=1e-8,
    # Scheduler
    lr_scheduler_type="cosine",   # "linear", "cosine", "constant_with_warmup", etc.
    warmup_steps=500,
    lr_scheduler_kwargs={"num_cycles": 3},  # scheduler-specific extras
)

Planificateurs basés sur des métriques

Certains planificateurs s'adaptent à la dynamique de l'entraînement au lieu de suivre un plan fixe.

GreedyLR met à jour le taux d’apprentissage à partir des résultats d’évaluation. Il augmente le taux d’apprentissage en le divisant par factor lorsque la métrique continue de s’améliorer, et le diminue en le multipliant par factor lorsque la métrique ne s’améliore pas. Lorsque le taux d’apprentissage atteint min_lr et ne s’améliore plus après reset_start étapes, GreedyLR revient à son état initial et démarre un nouveau cycle.

GreedyLR nécessite une évaluation pendant l’entraînement. Définissez eval_strategy sur "steps" ou "epoch".

args = TrainingArguments(
+   lr_scheduler_type="greedy",
+   lr_scheduler_kwargs={"patience": 10, "factor": 0.95, "min_lr": 1e-5},
+   eval_strategy="steps",
+   eval_steps=200,
    ...  # remaining args from the TrainingArguments intro config
)

Le mode par défaut mode="min" convient à la perte. Si vous suivez une métrique pour laquelle une valeur plus élevée est préférable, comme la précision, passez "mode": "max" dans lr_scheduler_kwargs.

Consultez la classe GreedyLR pour la liste complète des paramètres configurables.

Intégrations d'optimiseurs

Transformers intègre des optimiseurs tiers pour des scénarios d’entraînement spécialisés.

OptimiseurInstalleroptim="value"Description
APOLLOapollo-torchapollo_adamwMéthode full-param efficace en mémoire via des projections aléatoires ; un rang de 1 suffit
GrokAdamWgrokadamwgrokadamwCible la généralisation différée (grokking)
LOMO / AdaLomolomo-optimlomo / adalomoFusionne l'étape de gradient et l'étape de mise à jour pour l'ajustement fin de tous les paramètres avec une faible consommation mémoire
Sans planificationschedulefreeschedule_free_adamw, schedule_free_radam, schedule_free_sgdSupprime l’annealing du taux d’apprentissage ; à utiliser avec lr_scheduler_type="constant"
GaLoregalore-torchgalore_adamw, galore_adafactor, galore_adamw_8bitApprentissage à paramètres complets par projection de gradient de faible rang
StableAdamWtorch-optimistable_adamwMise à jour AdamW + AdaFactor avec élagage ; aucun élagage des gradients n'est nécessaire
APOLLO
GrokAdamW
LOMO
Sans planification
StableAdamW
GaLore
pip install apollo-torch

Approximated Gradient Scaling for Memory Efficient LLM Optimization (APOLLO) est un optimiseur économe en mémoire pour l'apprentissage de tous les paramètres lors du pré-entraînement et de l'ajustement fin. Il égale les performances d'AdamW avec un coût mémoire comparable à celui de SGD, en utilisant des projections aléatoires peu coûteuses au lieu de la SVD. Pour des économies de mémoire extrêmes, utilisez APOLLO-Mini, une variante de rang 1.

Utilisez le paramètre optim_target_modules pour spécifier les couches à entraîner.

args = TrainingArguments(
+   optim="apollo_adamw",
+   optim_target_modules=[r".*.attn.*", r".*.mlp.*"],
    ...  # remaining args from the TrainingArguments intro config
)

Transmettez des hyperparamètres supplémentaires via optim_args.

Définissez scale sur n/r, où n est la dimension de l’espace d’origine et r est la dimension de l’espace de faible rang. Ajuster le taux d’apprentissage tout en maintenant scale à sa valeur par défaut produit un effet similaire.

paramètredescriptionAPOLLOAPOLLO-Mini
rankrang du sous-espace auxiliaire pour le mise à l'échelle des gradients2561
scale_typecomment les facteurs d'échelle sont appliquéschannel (mise à l'échelle par canal)tensor (mise à l'échelle par tenseur)
scaleajuste les mises à jour des gradients pour stabiliser l'entraînement1.0128
update_proj_gapétapes avant la mise à jour des matrices de projection200200
projtype de projectionrandomrandom

Activer APOLLO-Mini avec une configuration de rang 1.

args = TrainingArguments(
    optim="apollo_adamw",
    optim_target_modules=[r".*.attn.*", r".*.mlp.*"],
    optim_args="proj=random,rank=1,scale=128.0,scale_type=tensor,update_proj_gap=200",
    ...  # remaining args from the TrainingArguments intro config
)

Personnalisation de l'optimiseur et du planificateur

Créez un optimiseur et un planificateur personnalisés pour utiliser un optimiseur non encore intégré, ajuster les taux d’apprentissage par couche ou appliquer une logique personnalisée.

Passer une classe et des kwargs

~Trainer.optimizer_cls_and_kwargs accepte une classe d'optimiseur personnalisée tout en déléguant le regroupement des paramètres et l'affectation aux dispositifs à Trainer.

Trainer diffère la création de l’optimiseur jusqu’à l’exécution de create_optimizer(), de sorte que le modèle se trouve déjà sur l’appareil correct.

import torch

trainer = Trainer(
    ...
    optimizer_cls_and_kwargs=(
        torch.optim.SGD,
        {"momentum": 0.9, "nesterov": True}
    ),
)

Passer des instances préconstruites

Passez un optimiseur et un planificateur prédéfinis à ~Trainer.optimizers. Trainer ignore create_optimizer() et create_scheduler() lorsque des instances préconstruites sont fournies. Si vous ne passez pas de planificateur, Trainer en crée automatiquement un.

Construisez l’optimiseur après avoir placé votre modèle sur l’appareil approprié. Les paramètres sont résolus lors de la construction, avant que Trainer ne déplace le modèle. En entraînement distribué, un désaccord d’appareils peut provoquer silencieusement un comportement incorrect.

import torch
from transformers import Trainer, get_cosine_schedule_with_warmup

optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5)
scheduler = get_cosine_schedule_with_warmup(
    optimizer, num_warmup_steps=500, num_training_steps=10_000
)

trainer = Trainer(
    ...
    optimizers=(optimizer, scheduler),
)

Les instances préconstruites contournent create_optimizer() et create_scheduler(), il est donc nécessaire de spécifier vos propres groupes de paramètres.

Écraser les méthodes de l'optimiseur et du planificateur

Sous-classez create_optimizer() et create_scheduler() pour un contrôle total. Les deux méthodes s'exécutent durant train().

Écrasez create_scheduler() pour utiliser un planificateur tel que OneCycleLR qui n’est pas disponible dans SchedulerType.

Pour chaque méthode, assurez-vous d'assigner à self et de la retourner.

import torch
from transformers import Trainer

class MyTrainer(Trainer):

    def create_scheduler(self, num_training_steps, optimizer=None):
        optimizer = optimizer or self.optimizer
        self.lr_scheduler = torch.optim.lr_scheduler.OneCycleLR(
            optimizer,
            max_lr=0.1,
            total_steps=num_training_steps,
        )
        return self.lr_scheduler

Il n’est pas nécessaire de redéfinir create_optimizer() si l’optimiseur par défaut convient. Étendre une méthode à l’aide de super() est plus simple que de la remplacer entièrement. Par exemple, vous pouvez ajouter un groupe de paramètres supplémentaire tout en conservant le reste inchangé.

class MyTrainer(Trainer):
    def create_optimizer(self, model=None):
        super().create_optimizer(model)  # builds the default two param groups
        # add extra param group
        self.optimizer.add_param_group({
            "params": self.model.classifier.parameters(),
            "lr": self.args.learning_rate * 10,
        })
        return self.optimizer
Update on GitHub