Thanks to visit codestin.com
Credit goes to github.com

Skip to content

RFC: refactor causal lm loss to handle lm_head in loss function#39047

Open
winglian wants to merge 1 commit into
huggingface:mainfrom
winglian:rfc-fused-lm-head-loss
Open

RFC: refactor causal lm loss to handle lm_head in loss function#39047
winglian wants to merge 1 commit into
huggingface:mainfrom
winglian:rfc-fused-lm-head-loss

Conversation

@winglian

Copy link
Copy Markdown
Collaborator

What does this PR do?

The ecosystem is has a lot of patches to optimize the loss for causal models. Due to frequent api changes, these patches are hard to maintain and keep up to date.

The RFC proposes changes to the ForCausalLMLoss to accept the lm_head weights and last hidden_states as part of the loss function. By moving the loss calculation here, it's much easier to add various loss variations that leverage fusing the linear + cross entropy calculations.

Fixes # (issue)

Before submitting

  • This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).
  • Did you read the contributor guideline,
    Pull Request section?
  • Was this discussed/approved via a Github issue or the forum? Please add a link
    to it if that's the case.
  • Did you make sure to update the documentation with your changes? Here are the
    documentation guidelines, and
    here are tips on formatting docstrings.
  • Did you write any new necessary tests?

Who can review?

Anyone in the community is free to review the PR once the tests have passed. Feel free to tag
members/contributors who may be interested in your PR.

@winglian

Copy link
Copy Markdown
Collaborator Author

Maybe some input from liger-kernel and cce maintainers would be helpful too @shimizust @lancerts @vaibhavjindal @erikwijmans

@Rocketknight1

Copy link
Copy Markdown
Member

This is definitely a core change to the library layout, so cc @ArthurZucker @Cyrilvallez!

@erikwijmans

Copy link
Copy Markdown

I definitely like the spirit behind this. This may get a bit complicated as sometimes how the logits are compute is specific to the model implementation (softcapping, like in Gemma 2, is what comes to mind). I think given the memory saving that fusing the cross-entropy and linear layer enables, this is worth figuring out tho :)

I do think the example given would work because you can still specify the logits from the caller (the model) if needed and any uncommon extra arguments could be put in **kwargs. The default implementation should probably support softcapping and a bias, since both aren't common it may make sense to have those be in kwargs.

@Cyrilvallez

Copy link
Copy Markdown
Member

cc @ArthurZucker - could indeed allow nice training optimizations more easily, but we lose a bit of explicitness, and add a redundant codepaths if the loss is not overriden. WDYT?

@erikwijmans

erikwijmans commented Jun 28, 2025

Copy link
Copy Markdown

One other thought: Accessing the lm head weights via self.lm_head.weight can have bad interactions with fully-sharded data-parallel.

PyTorch's FSDP2 relies on the forward call to know when to unshard the weights. The default way transformers shards is for the lm_head to be part of the model-level sharding group, so this isn't a problem as it gets unsharded by *ForCausalLM.forward, but it could be a problem.

I haven't seen this issue with ZeRO as it relies on a different mechanism.

I don't have much experience with PyTorch's original FSDP, but I believe you to explicitly use summon_full_params to access the weights in this way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants