Fix top-p sampling excluding the threshold-crossing token#360
Open
winklemad wants to merge 1 commit into
Open
Conversation
`top_p_logits` masked tokens with `cumsum <= top_p` on the inclusive cumulative probability, which drops the token that crosses the threshold. The kept nucleus therefore has cumulative mass strictly *below* top_p -- e.g. with probabilities [0.4, 0.3, 0.2, 0.1] and top_p=0.8 it keeps only [0, 1] (mass 0.70) instead of [0, 1, 2] (mass 0.90), biasing every fractional-top_p generation toward the mode. Keep a token while the cumulative mass *before* it is below top_p, so the crossing token is retained and the kept mass reaches top_p, matching the standard nucleus (Holtzman et al., 2019) definition. Added a regression test asserting the kept set reaches >= top_p.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No linked issue — found by reading the code.
The bug
top_p_logits(esm/utils/sampling.py) builds the nucleus mask from the inclusive cumulative probability:Masking with
cumsum <= top_pdrops the token that crosses the threshold, so the kept set's cumulative mass is always strictly belowtop_p:Standard nucleus sampling (Holtzman et al., 2019) keeps the smallest set whose cumulative probability reaches
top_p, which includes the crossing token — here[0, 1, 2], mass0.90. Sotop_p=0.8actually samples from a 0.70-mass nucleus, biasing every fractional-top_pgeneration toward the mode (config.top_pflows here via_sample_track).Fix
Keep a token while the cumulative mass before it is below
top_p((cumsum - probs) < top_p), so the crossing token is retained and the kept mass reachestop_p. The existing "at least one token" guard is unchanged.After the fix:
top_p=0.8 → [0,1,2](mass 0.90),0.7 → [0,1](0.70),0.35 → [0](0.40),1.0 →all — every kept set's mass is>= top_p.Testing
Added
test_top_p_logits_reaches_threshold, asserting the kept set and that its mass reachestop_pfor several thresholds. It fails before this change and passes after;esm/utils/sampling_test.pypasses andruff check/ruff formatare clean on the changed lines.