# Otimizadores e agendadores

Um otimizador atualiza os pesos do modelo durante o treinamento. O agendador envolve o otimizador e ajusta a taxa de aprendizado a cada etapa de treinamento. O [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer) cria ambos quando chama [create_optimizer_and_scheduler()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.create_optimizer_and_scheduler).

```md
                                    ┌────────────┐         ┌──────────────┐
                                    │ 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()                                    │
  │                                                                   │
  └───────────────────────────────────────────────────────────────────┘
```

Configure o comportamento do otimizador e do agendador, como `lr_scheduler_type()` e `optim()`, em [TrainingArguments](/docs/transformers/main/pt/main_classes/trainer#transformers.TrainingArguments). Os padrões (otimizador `adamw_torch` e agendador de aquecimento `linear`) são um bom ponto de partida para a maioria das execuções de ajuste fino.

```py
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
)
```

## Agendadores baseados em métricas

Alguns agendadores se adaptam à dinâmica do treinamento em vez de seguir um agendamento fixo.

[GreedyLR](https://huggingface.co/papers/2512.14527) atualiza a taxa de aprendizado a partir dos resultados de avaliação. Ela aumenta a taxa de aprendizado dividindo-a por `factor` quando a métrica continua melhorando e diminui a taxa de aprendizado multiplicando-a por `factor` quando a métrica não melhora. Quando a taxa de aprendizado atinge `min_lr` e não melhora após `reset_start` passos, o [GreedyLR](/docs/transformers/main/pt/main_classes/optimizer_schedules#transformers.GreedyLR) é reiniciado para seu estado inicial e um novo ciclo é iniciado.

[GreedyLR](/docs/transformers/main/pt/main_classes/optimizer_schedules#transformers.GreedyLR) requer avaliação durante o treinamento. Defina `eval_strategy` como `"steps"` ou `"epoch"`.

```diff
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
)
```

> [!TIP]
> O padrão `mode="min"` funciona para a perda. Se você estiver acompanhando uma métrica em que um valor maior é melhor, como a precisão, passe `"mode": "max"` em `lr_scheduler_kwargs`.

Consulte a classe [GreedyLR](/docs/transformers/main/pt/main_classes/optimizer_schedules#transformers.GreedyLR) para obter a lista completa de parâmetros configuráveis.

## Integrações com otimizadores

Transformers integra otimizadores de terceiros para cenários de treinamento especializados.

| Otimizador | Instalar | `optim="value"` | Descrição |
|---|---|---|---|
| APOLLO | `apollo-torch` | `apollo_adamw` | Eficiência de memória em full-param via projeções aleatórias; rank-1 é suficiente |
| GrokAdamW | `grokadamw` | `grokadamw` | Alvo a generalização tardia (grokking) |
| LOMO / AdaLomo | `lomo-optim` | `lomo` / `adalomo` | Fusion do gradiente + etapa de atualização para ajuste fino de todos os parâmetros com baixo consumo de memória |
| Agendamento Gratuito | `schedulefree` | `schedule_free_adamw`, `schedule_free_radam`, `schedule_free_sgd` | Elimina o annealing de LR; use em conjunto com `lr_scheduler_type="constant"` |
| GaLore | `galore-torch` | `galore_adamw`, `galore_adafactor`, `galore_adamw_8bit` | Aprendizado de parâmetros completos por projeção de baixo posto do gradiente |
| StableAdamW | `torch-optimi` | `stable_adamw` | Recorte de atualização do AdamW + AdaFactor; não é necessário recorte de gradiente |

```bash
pip install apollo-torch
```

[Approximated Gradient Scaling for Memory Efficient LLM Optimization (APOLLO)](https://huggingface.co/papers/2412.05270) é um otimizador eficiente em memória para aprendizado de parâmetros completos durante o pré-treinamento e o ajuste fino. Ele atinge o desempenho do AdamW com custo de memória semelhante ao do SGD, usando projeções aleatórias de baixo custo em vez de SVD. Para economias extremas de memória, use APOLLO-Mini, uma variante de rank 1.

Use o parâmetro `optim_target_modules` para especificar quais camadas treinar.

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

Passe hiperparâmetros adicionais por meio de `optim_args`.

> [!TIP]
> Defina `scale` como `n/r`, em que `n` é a dimensão do espaço original e `r` é a dimensão do espaço de baixo posto. Ajustar a taxa de aprendizado mantendo `scale` no valor padrão produz um efeito semelhante.

| parâmetro | descrição | APOLLO | APOLLO-Mini |
|---|---|---|---|
| rank | rank do subespaço auxiliar para a escalação do gradiente | 256 | 1 |
| scale_type | como os fatores de escala são aplicados | `channel` (escalonamento por canal) | `tensor` (escalonamento por tensor) |
| escala | ajusta as atualizações de gradiente para estabilizar o treinamento | 1.0 | 128 |
| update_proj_gap | passos antes de atualizar as matrizes de projeção | 200 | 200 |
| proj | tipo de projeção | `random` | `random` |

Ative o APOLLO-Mini com uma configuração de rank 1.

```py
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
)
```

```bash
pip install grokadamw
```

[GrokAdamW](https://github.com/cognitivecomputations/grokadamw) é direcionado ao *grokking*, em que os modelos exibem generalização tardia devido a gradientes de variação lenta.

```diff
args = TrainingArguments(
+   optim="grokadamw",
    ...  # remaining args from the TrainingArguments intro config
)
```

```bash
pip install lomo-optim
```

[Otimização de Baixa Memória (LOMO)](https://github.com/OpenLMLab/LOMO) inclui dois otimizadores para ajuste fino de todos os parâmetros com baixa memória, [LOMO](https://huggingface.co/papers/2306.09782) e [AdaLomo](https://hf.co/papers/2310.10195). Ambos fundem o cálculo do gradiente e a atualização dos parâmetros em uma única etapa. O AdaLomo adiciona uma taxa de aprendizado adaptativa por parâmetro, semelhante à do Adam.

> [!TIP]
> O AdaLomo funciona melhor sem `grad_norm`, melhorando o desempenho e a taxa de transferência.

```diff
args = TrainingArguments(
+   optim="adalomo",
    learning_rate=2e-6,
    ...  # remaining args from the TrainingArguments intro config
)
```

```bash
pip install schedulefree
```

O [otimizador Schedule Free (SFO)](https://hf.co/papers/2405.15682) substitui o momentum por uma combinação de média e interpolação, eliminando completamente a necessidade de anelar a taxa de aprendizado.

O SFO suporta os otimizadores RAdam (`schedule_free_radam`), AdamW (`schedule_free_adamw`) e SGD (`schedule_free_sgd`). O agendador RAdam não requer `warmup_steps`.

Combine SFO com `lr_scheduler_type="constant"`. Outros tipos de agendador funcionam, mas afetam o comportamento pretendido do SFO.

```diff
args = TrainingArguments(
+   optim="schedule_free_radam",
+   lr_scheduler_type="constant",
    learning_rate=2e-6,
    ...  # remaining args from the TrainingArguments intro config
)
```

```bash
pip install torch-optimi
```

[StableAdamW](https://huggingface.co/papers/2304.13013) incorpora o recorte de atualização do AdaFactor ao AdamW, eliminando a necessidade de recorte de gradiente. Caso contrário, é uma substituição direta para o AdamW.

> [!TIP]
> Se você estiver treinando com tamanhos de lote grandes ou ainda observando picos de perda, tente definir `beta_2` entre 0,95 e 0,99.

```diff
args = TrainingArguments(
+   optim="stable_adamw",
    learning_rate=2e-6,
    ...  # remaining args from the TrainingArguments intro config
)
```

```bash
pip install galore-torch trl
```

[Gradient Low-Rank Projection (GaLore)](https://hf.co/papers/2403.03507) reduz o uso de memória no treinamento de LLMs. Diferentemente de métodos de adaptação de baixo posto, como [LoRA](https://hf.co/papers/2106.09685), o GaLore preserva o aprendizado de *parâmetros completos*.

Defina `optim` em [trl.SFTConfig](https://huggingface.co/docs/trl/main/en/sft_trainer#trl.SFTConfig) para um otimizador GaLore (`"galore_adamw"`, `"galore_adafactor"` ou `"galore_adamw_8bit"`). Especifique os módulos alvo com `optim_target_modules` e os parâmetros específicos do GaLore (`rank`, `update_proj_gap`, `scale`) por meio de `optim_args`.

```py
from trl import SFTConfig

args = SFTConfig(
    output_dir="./galore",
    max_steps=100,
    optim="galore_adamw",
    optim_target_modules=[r".*.attn.*", r".*.mlp.*"],
    optim_args="rank=64, update_proj_gap=100, scale=0.10",
)
```

Adicione `_layerwise` ao nome do otimizador para otimização por camada (`"galore_adamw_layerwise"`). Somente as camadas lineares alvo do GaLore usam decomposição de baixo posto. Todas as outras camadas são otimizadas normalmente.

```py
from trl import SFTConfig, SFTTrainer

args = SFTConfig(
    output_dir="./galore",
    max_steps=100,
    optim="galore_adamw_layerwise",
    optim_target_modules=[r".*.attn.*", r".*.mlp.*"],
    optim_args="rank=64, update_proj_gap=100, scale=0.10",
)
```

O modo Layerwise é experimental. Ele só é executado em uma [GPU única](https://github.com/jiaweizzhao/GaLore?tab=readme-ov-file#train-7b-model-with-a-single-gpu-with-24gb-memory), não suporta DistributedDataParallel (DDP), e o gradient clipping e o DeepSpeed podem não funcionar.

## Personalizando o otimizador e o agendador

Crie um otimizador e um agendador personalizados para usar um otimizador ainda não integrado, ajustar as taxas de aprendizado por camada ou aplicar lógica personalizada.

### Passe uma classe e kwargs

`~Trainer.optimizer_cls_and_kwargs` aceita uma classe de otimizador personalizada, delegando a agrupamento de parâmetros e a alocação de dispositivos ao [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer).

O [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer) adia a criação do otimizador até que [create_optimizer()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.create_optimizer) seja executado, de modo que o modelo já esteja no dispositivo correto.

```py
import torch

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

### Passar instâncias pré-construídas

Passe um otimizador e um agendador predefinidos para `~Trainer.optimizers`. O [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer) ignora [create_optimizer()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.create_optimizer) e [create_scheduler()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.create_scheduler) quando instâncias pré-criadas são fornecidas. Se você não passar um agendador, o [Trainer](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer) cria um automaticamente.

> [!WARNING]
> Construa o otimizador depois de posicionar o modelo no dispositivo correto. Os parâmetros são resolvidos no momento da construção, antes de `Trainer` mover o modelo. No treinamento distribuído, dispositivos incompatíveis podem causar comportamento incorreto de forma silenciosa.

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

As instâncias pré-criadas ignoram [create_optimizer()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.create_optimizer) e [create_scheduler()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.create_scheduler), portanto, você precisa especificar seus próprios grupos de parâmetros.

### Substituir os métodos do otimizador e do agendador

Subclasse [create_optimizer()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.create_optimizer) e [create_scheduler()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.create_scheduler) para controle total. Ambos os métodos são executados *durante* o [train()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.train).

Sobrescreva [create_scheduler()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.create_scheduler) para usar um agendador como [OneCycleLR](https://docs.pytorch.org/docs/stable/generated/torch.optim.lr_scheduler.OneCycleLR.html) que não está disponível em [SchedulerType](/docs/transformers/main/pt/main_classes/optimizer_schedules#transformers.SchedulerType).

Para cada método, certifique-se de atribuir a `self` e retorná-lo.

```py
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
```

Você não precisa sobrescrever [create_optimizer()](/docs/transformers/main/pt/main_classes/trainer#transformers.Trainer.create_optimizer) se o otimizador padrão funcionar. Estender um método com `super()` é mais fácil do que substituí-lo completamente. Por exemplo, adicione um grupo de parâmetros extra mantendo tudo o mais igual.

```py
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
```

