pytorch / pytorch/pytorch

Distribution.cdf rejects values outside the support, though the CDF is defined on all of R (and the implementations already clamp for it)

Open
#193,690 2 comments 0 reactions 0 assignees View on GitHub
bot-triaged module: distributions triaged
Dominant language
Python
Stars
103k
Forks
29.5k
PR merge metrics
PR metrics pending

Description

### 🐛 Describe the bug

`cdf` validates its `value` argument against the distribution's **support**, but a CDF is defined for every real number — `F(x) = P(X <= x)` is `0` below the support and `1` above it. With the default `validate_args`, evaluating a CDF outside the support raises instead of returning those values.

The most ordinary case this breaks is plotting a CDF over a grid that extends past the support:

```python
import torch, torch.distributions as D

grid = torch.linspace(-0.5, 1.5, 9)
D.Uniform(0., 1.).cdf(grid)
# ValueError: Expected value argument (Tensor of shape (9,)) to be within the support (Interval(...))

D.Uniform(0., 1., validate_args=False).cdf(grid)
# [0.0, 0.0, 0.0, 0.25, 0.5, 0.75, 1.0, 1.0, 1.0] <- correct, and what SciPy returns
```

Same for `Exponential(1.).cdf(-1.)` and `Gamma(2., 2.).cdf(-1.)`.

### Why this looks unintended rather than by design

`Uniform.cdf` clamps its result specifically so that out-of-support inputs produce `0`/`1`:

```python
def cdf(self, value):
if self._validate_args:
self._validate_sample(value) # rejects value outside [low, high]
result = (value - self.low) / (self.high - self.low)
return result.clamp(min=0, max=1) # ...but this exists to handle exactly those values
```

Under the default settings the `clamp` is unreachable: any input that would need clamping has already been rejected two lines above. The clamp only does anything when validation is off — so the implementation already encodes the intended out-of-support semantics, and the validation gate prevents them being used.

The mathematical distinction is that support validation is right for `log_prob` (the density is genuinely undefined/zero outside) but not for `cdf`, where every real input has a well-defined answer. `_validate_sample`'s docstring says it covers "`log_prob`, `cdf` and `icdf`", so the two cases are currently conflated.

### Scope / what I'm asking

The pattern is consistent across the library (`uniform`, `exponential`, `gamma`, `laplace`, `half_normal`, ...), so this is a deliberate-looking systematic choice rather than a one-file slip, and changing it affects every distribution — which is why I'm opening an issue rather than sending a patch.

Two options, if you agree it should change:

1. Have `cdf`/`icdf` validate only shape/broadcastability (via a variant of `_validate_sample` that skips the support check), keeping the strict support check for `log_prob`. This matches SciPy and makes the existing clamps meaningful.
2. Keep the current behaviour and document that CDF evaluation outside the support requires `validate_args=False`.

If the answer is (1), the distributions whose `cdf` doesn't already clamp/saturate would need that added so they return `0`/`1` rather than extrapolating — happy to do that work and send the PR.

Possibly related: #186826 covers the opposite end of the same area (`icdf` performing *no* validation even with `validate_args=True`), so `cdf` validating too much and `icdf` too little might be worth settling together.

### Versions

torch 2.13.0+cpu, Python 3.11.9, Windows. Behaviour also present in current `main` source.

cc @fritzo @neerajprad @alicanb @nikitaved

Contributor guide

Open the contributing guide

Research direction

Start with the named Uniform.cdf implementation and the _validate_sample docstring, then compare the cdf behavior of Exponential, Gamma, Laplace, and HalfNormal. Trace how validate_args is applied to cdf, log_prob, and icdf; done requires an agreed validation policy and consistent out-of-support CDF results across the affected distributions.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
machine-learning
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.