_load_rng_state after get_batch_samples may break training reproducibility when dataloader has random operations

在 Hugging Face Transformers 库的 Trainer 中,当用户从 checkpoint 恢复训练,并且 dataloader 包含随机操作(例如在 Dataset 的 __getitem__ 中应用随机噪声、数据增强或使用随机采样器)时,训练过程可能无法复现原始不间断运行的

_load_rng_state after get_batch_samples may break training reproducibility when dataloader has random operations

_load_rng_state after get_batch_samples may break training reproducibility when dataloader has random operations

快速结论:该问题发生在使用 Hugging Face Transformers Trainer 从 checkpoint 恢复训练时,如果 dataloader 中包含了随机操作(如数据增强、噪声注入等),当前的调用顺序 get_batch_samples() 先于 _load_rng_state() 会导致训练无法保持逐比特(bit-for-bit)复现。优先排查 _inner_training_loop 中 RNG 状态恢复与数据加载的执行顺序。

问题场景

在 Hugging Face Transformers 库的 Trainer 中,当用户从 checkpoint 恢复训练,并且 dataloader 包含随机操作(例如在 Dataset 的 __getitem__ 中应用随机噪声、数据增强或使用随机采样器)时,训练过程可能无法复现原始不间断运行的结果。

报错原文

该问题不产生显式报错,而是表现为训练结果在复现时出现偏差。核心问题描述为:

When `get_batch_samples` is called before `_load_rng_state`, the random operations within the dataloader consume the RNG state from the *current* execution stream, not the *restored* one.
This leads to two issues:
1. The data batch fetched is different from the one in the original, uninterrupted run.
2. The subsequent `_load_rng_state` call resets the RNG, but the `training_step` (e.g., with Dropout) then operates on this incorrect data, and uses an RNG state that is out of sync with the original run's state progression.

原因分析

Trainer_inner_training_loop 中,当前实现为:先调用 get_batch_samples() 获取数据批次,再调用 _load_rng_state() 恢复随机数生成器(RNG)状态。这种顺序导致数据加载过程中消耗的是恢复前的 RNG 状态,因此获取到的数据批次与原始不间断运行不一致。随后恢复 RNG 状态虽然能影响模型训练步骤(如 Dropout),但模型操作的已是错误的数据,并且 RNG 状态与原始运行的状态推进不再同步。如果反过来,先恢复 RNG 状态(_load_rng_state()),再获取数据批次(get_batch_samples()),则数据加载和模型训练步骤都能使用正确的 RNG 状态,实现完全复现。

环境排查

  • Python 版本(建议 >= 3.8)
  • PyTorch 版本(建议 >= 1.10)
  • Transformers 版本(建议 >= 4.x,具体视 issue 提交时间)
  • CUDA 版本及 GPU 型号(如果使用 GPU 训练)
  • 确认 dataloader 中是否包含随机操作(如数据增强、随机变换等)

解决步骤

  1. 手动调整调用顺序(可优先尝试):Trainer_inner_training_loop 中,将对 _load_rng_state() 的调用提前到 get_batch_samples() 之前。即:先恢复 RNG 状态,再获取数据批次。
  2. 验证复现性:使用 issue 中提供的实验脚本,分别测试两种顺序:
    • Hypothesis A: load_rng_state() -> get_batch_samples()(修复后)
    • Hypothesis B: get_batch_samples() -> load_rng_state()(当前实现)

    确认 Hypothesis A 能复现原始不间断运行的输出。

  3. 等待官方确认与 PR 合入:issue 中已有社区成员提出相同的修复建议(“Just swap the order”),但尚未得到官方核心维护者(如 @SunMarc)的确认。建议关注该 issue 的进展,或自行 Fork 并应用上述修改。

验证方法

运行 issue 中提供的实验脚本,比较以下三种输出的损失值或其他训练指标是否一致:

  • 原始不间断运行(Golden standard)
  • 使用修复后的顺序(load_rng_state() 先于 get_batch_samples()
  • 当前实现(get_batch_samples() 先于 load_rng_state()

如果修复后的顺序输出与原始不间断运行完全一致,则说明问题已解决。

参考来源

huggingface/transformers #39215

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 14176

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注