PPFormulaNet training-loss bug

该报错发生在 Transformers 库中 PPFormulaNet 模型训练时,原因是 ForCausalLMLoss 默认对 labels 左移一位,但 PPFormulaNet 是 encoder-decoder 架构,logits 与 labels 已对齐,导致训练标签错位、丢失最后一个目

快速结论:该报错发生在 Transformers 库中 PPFormulaNet 模型训练时,原因是 ForCausalLMLoss 默认对 labels 左移一位,但 PPFormulaNet 是 encoder-decoder 架构,logits 与 labels 已对齐,导致训练标签错位、丢失最后一个目标 token。优先排查是否使用了包含修复(PR #46903)的 Transformers 版本。

适用环境:Hugging Face Transformers 库,涉及 PPFormulaNetForConditionalGeneration 模型(基于 Florence2 架构)。Issue 中未提供具体的操作系统、Python、CUDA、显卡或依赖版本信息。

最快修复方案:升级到包含 PR #46903 的 Transformers main 分支(该 PR 于 2026-07-23 合并,已修复此问题)。如果无法升级,可修改源码,在调用 loss_function 时传入 shift_labels=labels 参数,禁止其内部左移。

注意事项:上述代码修复方案已在 main 分支验证,但未在已发布的稳定版本中确认;自行修改源码时需同步修改 modular_pp_formulanet.py 和生成的 modeling_pp_formulanet.py 两个文件。

问题场景

用户使用 Transformers 库训练或微调 PPFormulaNetForConditionalGeneration 模型时,发现训练损失异常(训练-loss bug)。问题定位在 modular_pp_formulanet.py 第 491 行的 self.loss_function() 调用:由于 PPFormulaNet 继承了 Florence2 的架构但重写了 forward() 方法,导致 Florence2 在 PR #46898 中已应用的修复未能传递到 PPFormulaNet。

报错原文

PPFormulaNet training-loss bug — ForCausalLMLoss incorrectly shifts labels in encoder-decoder model
The problem: PPFormulaNetForConditionalGeneration.forward() uses self.loss_function() which maps to ForCausalLMLoss. ForCausalLMLoss internally shifts labels left by 1 (labels[..., 1:]), but PPFormulaNet is an encoder-decoder model where the logits are already aligned with labels — no shift is needed.

原因分析

根本原因已确认:ForCausalLMLoss 内部默认执行 labels[..., 1:] 左移操作,这是为因果语言模型(causal LM)设计的。然而 PPFormulaNet 是 encoder-decoder 模型,其输出的 logits 与输入的 labels 已经对齐,不需要额外移位。两次移位(或说一次多余的移位)导致模型训练时 labels 错位,最终丢失最后一个目标 token。此问题与 issue #46901 描述相同,均由 PR #46903 修复。

环境排查

  • 确认 Transformers 库版本:检查是否低于包含 PR #46903(2026-07-23 合并)的版本。
  • 确认是否从源码构建:Issue 中提到从 main 分支构建并阅读当前代码后确认修复已存在。
  • 如需自行修改,确认同时修改了两个文件:modular_pp_formulanet.pymodeling_pp_formulanet.py(后者为生成文件,手动修改后注意不要被重新生成覆盖)。

解决步骤

  1. 首选方案(已验证):升级 Transformers 库到包含 PR #46903 的 main 分支或更新的发布版本。该 PR 修复了此问题,并已确认在 main 分支中生效。
  2. 备选方案(代码修改):如果无法升级,找到 modular_pp_formulanet.py 第 491 行附近的 loss_function 调用,将代码修改为:
    loss = self.loss_function(
        logits=logits,
        labels=None,
        vocab_size=self.config.text_config.vocab_size,
        shift_labels=shift_labels if shift_labels is not None else labels,
        **kwargs,
    )

    注意:此处的 shift_labels=shift_labels if shift_labels is not None else labels 是修复后的最终形态。若你的代码版本较旧,可先尝试 Issue 中提出的中间方案 shift_labels=labels,但建议直接对齐最终修复代码。

  3. 同步生成文件:手动修改 modeling_pp_formulanet.py(生成的模型文件)中对应的 loss_function 调用,确保与 modular 文件一致。

验证方法

从源码构建 main 分支后,读取 modeling_pp_formulanet.pyloss_function 调用处,确认已包含 shift_labels=shift_labels if shift_labels is not None else labels 参数。或直接重新运行训练,观察 loss 是否恢复正常、最后一个目标 token 是否参与训练。

参考来源

huggingface/transformers #47317

GamsGo AI

AI 工具推荐

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

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

了解 GamsGo AI

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

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 21432

发表回复

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