Skip to content

Return -inf from Categorical.logProb outside 0..K-1 - #180

Merged
marcelluethi merged 1 commit into
dimwit-dev:mainfrom
marcelluethi:categorical-fix
Oct 27, 2026
Merged

marcelluethi merged 1 commit into
dimwit-dev:mainfrom
marcelluethi:categorical-fix

Conversation

@marcelluethi

Copy link
Copy Markdown
Contributor

JAX does not raise on out-of-range indices: it clamps an index >= K to K-1 and wraps a negative index around.
So Categorical.logProb returned a finite, plausible log-probability for impossible values, e.g. log p(K-1)for x = K or x = -1. Values outside 0..K-1 are now masked to -inf.

It should be a law in dimwit that logprob of any value outside the support is -inf (log(0))
Tests are added, which ensure that logprob is -inf outside its support

JAX does not raise on out-of-range indices: it clamps an index >= K to
 K-1 and wraps a negative index around. So Categorical.logProb returned a finite, plausible log-probability for impossible values, e.g. log p(K-1)
 for x = K or x = -1. Values outside 0..K-1 are now masked to -inf.

Add tests ensuring that logprob is -inf outside its support
@marcelluethi
marcelluethi requested a review from benikm91 October 26, 2026 06:58
liftPyTensor(logProbs.jaxValue.__getitem__(x.jaxValue))
// JAX clamps out-of-range indices (and wraps negative ones), so values outside 0..K-1 are masked explicitly
val indexed: Tensor0[LogProb] = liftPyTensor(logProbs.jaxValue.__getitem__(x.jaxValue))
val inRange = (x >= Tensor0(0)) and (x < Tensor0(probs.shape.dimensions(0)))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should work as which read better (into cast):

val inRange = (x >= 0) and (x < probs.shape.dimensions(0))

@benikm91 benikm91 left a comment •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the change. It is in DimWit's spirit to not just wrap values around.

I am fine with "-inf" but did you consider to throw a runtime error? Maybe not possible because we are in tensorland?

The code can be slightly improved but good as it is. Approved.

@marcelluethi

Copy link
Copy Markdown
Contributor Author

I am fine with "-inf" but did you consider to throw a runtime error? Maybe not possible because we are in tensorland?

It is a good point and we should maybe think a bit more deeply about it. My hunch is that -inf is okay here. The probability of each event is 0, and hence the log probability '-inf'. It is not really an exceptional situation which should throw. It is also sometimes possible to recover from it. If we, for example, have a sampler that goes out of the support and makes the cost -inf, it may just discard this value and continue with another sample. Gradients become, however, meaningless.

@marcelluethi
marcelluethi merged commit 3797e4b into dimwit-dev:main Oct 27, 2026
1 check passed
benikm91 pushed a commit that referenced this pull request Oct 28, 2026
Return -inf from Categorical.logProb outside 0..K-1
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.

2 participants