Transformers documentation

优化器与调度器

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

优化器与调度器

优化器在训练过程中更新模型权重。调度器封装优化器,并在每个训练步骤中调整学习率。Trainer 在调用 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()                                    │
  │                                                                   │
  └───────────────────────────────────────────────────────────────────┘

在 TrainingArguments 中配置优化器和调度器的行为,例如 lr_scheduler_type() 和 optim()。默认设置(adamw_torch 优化器和 linear 预热调度器)是大多数微调任务的良好起点。

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
)

基于指标的调度器

一些调度器会根据训练动态进行自适应调整,而不是遵循固定的调度方案。

GreedyLR 根据评估结果更新学习率。当指标持续改善时,它通过将学习率除以 factor 来提高学习率;当指标没有改善时,它通过将学习率乘以 factor 来降低学习率。当学习率降至 min_lr 且在 reset_start 步之后仍未改善时,GreedyLR 会重置为初始状态并开始新的周期。

GreedyLR 在训练过程中需要进行评估。请将 eval_strategy 设置为 "steps" 或 "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
)

默认的 mode="min" 适用于损失值。如果您跟踪的是数值越高越好的指标(例如准确率),请在 lr_scheduler_kwargs 中传入 "mode": "max"。

有关可配置参数的完整列表,请参阅 GreedyLR 类。

优化器集成

Transformers 集成了第三方优化器,以支持特定的训练场景。

优化器安装optim="value"描述
APOLLOapollo-torchapollo_adamw通过随机投影实现内存高效的全参数训练;秩 1 已足够
GrokAdamWgrokadamwgrokadamw针对延迟泛化(grokking)
LOMO / AdaLomolomo-optimlomo / adalomo融合梯度与更新步骤,以实现低内存的全参数微调
无调度schedulefreeschedule_free_adamw, schedule_free_radam, schedule_free_sgd消除学习率退火;请搭配使用 lr_scheduler_type="constant"
GaLoregalore-torchgalore_adamw, galore_adafactor, galore_adamw_8bit通过梯度低秩投影进行全参数学习
StableAdamWtorch-optimistable_adamwAdamW + AdaFactor 更新裁剪;无需梯度裁剪
APOLLO
GrokAdamW
LOMO
无调度
StableAdamW
GaLore
pip install apollo-torch

用于内存高效大语言模型优化的近似梯度缩放(APOLLO)是一种在预训练和微调期间进行全参数学习时内存高效的优化器。它通过使用廉价的随机投影而非 SVD,以类似 SGD 的内存开销实现了与 AdamW 相当的性能。若需极致节省内存,请使用 APOLLO-Mini,这是一种秩为 1 的变体。

使用 optim_target_modules 参数来指定要训练的层。

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

通过 optim_args 传递额外的超参数。

将 scale 设置为 n/r,其中 n 为原始空间维度,r 为低秩空间维度。保持 scale 为默认值并调整学习率,也能达到类似的效果。

参数描述APOLLOAPOLLO-Mini
rank用于梯度缩放的辅助子空间的秩2561
scale_type缩放因子的应用方式channel(按通道缩放)tensor(按张量缩放)
scale调整梯度更新以稳定训练1.0128
update_proj_gap更新投影矩阵前的步数200200
proj投影类型randomrandom

使用秩为 1 的配置启用 APOLLO-Mini。

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
)

自定义优化器和调度器

创建自定义优化器和调度器,以使用尚未集成的优化器、调整逐层学习率或应用自定义逻辑。

传入一个类和 kwargs

~Trainer.optimizer_cls_and_kwargs 接受自定义的优化器类,同时将参数分组和设备放置委托给 Trainer。

Trainer 会将优化器的构建推迟到 create_optimizer() 执行时,因此此时模型已经位于正确的设备上。

import torch

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

传入预构建的实例

将预定义的优化器和调度器传递给 ~Trainer.optimizers。当提供预构建的实例时,Trainer 会跳过 create_optimizer() 和 create_scheduler()。如果未传递调度器,Trainer 会自动创建一个。

在将模型放置到正确的设备之后再构建优化器。参数在构造时即被解析,早于 Trainer 移动模型。在分布式训练中,设备不匹配可能会悄无声息地导致错误行为。

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),
)

预构建实例会绕过 create_optimizer() 和 create_scheduler(),因此您需要自行指定参数组。

重写优化器和调度器方法

子类化 create_optimizer() 和 create_scheduler() 以获得完全的控制权。这两个方法都会在 train() 期间 运行。

重写 create_scheduler(),以使用 SchedulerType 中不可用的调度器,例如 OneCycleLR。

对于每种方法,请确保将其赋值给 self 并返回它。

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

如果默认优化器可用,则无需重写 create_optimizer()。使用 super() 扩展方法比完全替换它更简单。例如,在保持其他所有内容不变的情况下,添加一个额外的参数组。

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