# 回调

[TrainerCallback](/docs/transformers/v5.23.0/zh/main_classes/callback#transformers.TrainerCallback) 会介入特定的训练事件（如 epoch 开始、评估、训练结束），以修改训练状态或控制流程。您可以使用回调将指标记录到 Trackio 等实验跟踪器中，自定义保存和评估的时机，或添加其他自定义行为。通过叠加多个回调来组合各项功能。

回调无法修改训练循环本身，例如前向传播。若要更改 [Trainer](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.Trainer) 的计算内容，请改为 [子类化](./trainer_customize) 其方法。

下图展示了回调可以挂钩的所有事件。

```md
on_train_begin
  └─ for each epoch:
      on_epoch_begin
      └─ for each step:
          on_step_begin
          ├─ for each gradient accumulation substep:
          │   on_substep_end
          on_pre_optimizer_step   ← after gradient clipping, before optimizer.step()
          on_optimizer_step       ← after optimizer.step()
          on_step_end
          └─ (conditionally):
              on_log
              on_evaluate
              on_save
      on_epoch_end
on_train_end
on_predict / on_prediction_step
on_push_begin
```

## 创建回调

子类化 [TrainerCallback](/docs/transformers/v5.23.0/zh/main_classes/callback#transformers.TrainerCallback) 并覆盖上图中一个或多个事件方法。下面的示例演示了三个钩子：

- `on_epoch_begin` 会打印 [TrainerState](/docs/transformers/v5.23.0/zh/main_classes/callback#transformers.TrainerState) 中的当前 epoch（实时值）以及 [TrainingArguments](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.TrainingArguments) 中的学习率（静态值）。
- `on_step_end` 从 lr_scheduler（通过 `**kwargs` 传入）中读取当前的学习率，并在 [TrainerControl](/docs/transformers/v5.23.0/zh/main_classes/callback#transformers.TrainerControl) 上设置 `should_evaluate`（完整的控制对象列表请参见 [TrainerControl](/docs/transformers/v5.23.0/zh/main_classes/callback#transformers.TrainerControl)），以在学习率低于阈值时触发评估。
- `on_train_end` 会打印最佳指标及其出现的步数。

```python
from transformers import TrainerCallback

class EpochLoggerCallback(TrainerCallback):
    def __init__(self, lr_eval_threshold=1e-5):
        self.lr_eval_threshold = lr_eval_threshold

    def on_epoch_begin(self, args, state, control, **kwargs):
        print(f"Starting epoch {int(state.epoch) + 1}/{state.num_train_epochs} "
              f"(lr={args.learning_rate})")

    def on_step_end(self, args, state, control, **kwargs):
        lr_scheduler = kwargs.get("lr_scheduler")
        if lr_scheduler is not None:
            current_lr = lr_scheduler.get_last_lr()[0]
            if current_lr < self.lr_eval_threshold:
                control.should_evaluate = True

    def on_train_end(self, args, state, control, **kwargs):
        print(f"Training complete! Best metric: {state.best_metric} at step {state.best_global_step}")
```

在 `callbacks` 参数中，将该回调注册到 [Trainer](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.Trainer)。您也可以以列表形式传入多个回调。

```python
trainer = Trainer(
    callbacks=[EpochLoggerCallback(lr_eval_threshold=1e-5)],
    ...,
)
```

## 内置回调

Transformers 包含多个默认启用的内置回调。额外的[集成回调](./main_classes/callback)会向日志平台（如[Trackio](https://huggingface.co/docs/trackio/en/index)）记录信息。

### DefaultFlowCallback

[DefaultFlowCallback](/docs/transformers/v5.23.0/zh/main_classes/callback#transformers.DefaultFlowCallback) 根据 [TrainingArguments](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.TrainingArguments) 中的 `logging_strategy`、`eval_strategy` 和 `save_strategy` 值，管理默认的日志记录、评估和检查点保存计划。在合适的步数或轮次时，它会设置相应的 `control` 标志（`should_log`、`should_evaluate`、`should_save`）。此外，当 `global_step` 达到 `max_steps` 时，它还会设置 `should_training_stop`。

重写此回调是自定义*何时*执行日志记录、评估或保存的主要方式。

### ProgressCallback 和 PrinterCallback

[Trainer](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.Trainer) 会根据 [TrainingArguments](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.TrainingArguments) 中的 [disable_tqdm](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.TrainingArguments.disable_tqdm) 字段，自动在这两个回调之间进行选择。

- 默认使用 [ProgressCallback](/docs/transformers/v5.23.0/zh/main_classes/callback#transformers.ProgressCallback)。它在训练期间显示 tqdm 进度条，在评估或预测期间显示单独的进度条，并在每次 `on_log` 事件时打印最新的指标。在分布式训练期间，它仅在主进程上运行，以避免重复输出。
- [PrinterCallback](/docs/transformers/v5.23.0/zh/main_classes/callback#transformers.PrinterCallback) 在 `disable_tqdm=True` 时使用。它会在每次 `on_log` 事件时将日志字典打印到标准输出，且不显示进度条。

您也可以使用 [remove_callback()](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.Trainer.remove_callback) 和 [add_callback()](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.Trainer.add_callback) 手动替换它们。

```py
from transformers import PrinterCallback

trainer = Trainer(...)
trainer.remove_callback(ProgressCallback)
trainer.add_callback(PrinterCallback)
```

### EarlyStoppingCallback

[EarlyStoppingCallback](/docs/transformers/v5.23.0/zh/main_classes/callback#transformers.EarlyStoppingCallback) 会在评估指标停止提升时停止训练。每次评估后，它会检查指标的提升幅度是否超过 `early_stopping_threshold`。如果指标在连续 `early_stopping_patience` 次评估中均未提升，训练将停止。

[EarlyStoppingCallback](/docs/transformers/v5.23.0/zh/main_classes/callback#transformers.EarlyStoppingCallback) 需要两个 [TrainingArguments](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.TrainingArguments)：

- `metric_for_best_model`，用于监控的评估指标
- `eval_strategy`，是否在 `"steps"` 或 `"epoch"` 上进行评估

```py
from transformers import EarlyStoppingCallback

trainer = Trainer(
    ...,
    callbacks=[EarlyStoppingCallback(early_stopping_patience=3, early_stopping_threshold=0.001)],
)
```

## 后续步骤

- 查看所有可用于向实验跟踪器记录日志的[集成回调](./main_classes/callback)。
- [子类化 Trainer 方法](./trainer_customize)指南介绍了在需要更改训练循环计算内容时，如何重写 [Trainer](/docs/transformers/v5.23.0/zh/main_classes/trainer#transformers.Trainer) 方法。

