You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
normal_lcdf and normal_lccdf give infinite gradients for infinite inputs. #2881
data{
real y;
}
parameters{
real mu;
real<lower = 0> sigma;
}
model{
target += normal_lcdf(y | mu, sigma);
}
When y is infinite (and given that mu and sigma are finite, here ensured by declaring them as parameters), then the gradient is zero. However, it seems that Stan yields infinite gradients here.
If possible, it would be nice to special-case infinite y and return the correct gradients. However, there's some question beyond my expertise of whether this special-casing would play nicely with vectorization in opencl.
@jsocolar, thanks for bringing this up. I'm putting up a minimal example in C++ to walk through it.
If you pop this into a file called test/unit/math/normal_lcdf_test.cpp, you'll be able to run it from the command line like: python runTests.py test/unit/math/normal_lcdf_test.cpp
When y is infinite (and given that mu and sigma are finite, here ensured by declaring them as parameters), then the gradient is zero. However, it seems that Stan yields infinite gradients here.
Just curious... how'd you come to this conclusion? And which gradient did you think was "infinite"? (The gradient has two elements.) It'd be good to know how you're thinking about what the math library does and how it's generating gradients, especially at the boundary conditions.
To get into the example, if you look at the test:
d normal_lcdf(y, mu, sigma) / dmu = 0
d normal_lcdf(y, mu, sigma) / dsigma = NaN
(NaN does not equal infinity, but it doesn't mean that's good.)
I think you're expecting d / dsigma = 0? Is that right?
I didn't trace through to figure out why it's having trouble computing that term, but I'm sure it could be addressed. I'd lean towards throwing an exception at the boundaries, but I think that would change the behavior of Stan in a way that we'd have to have a larger discussion to implement.
Just curious... how'd you come to this conclusion? And which gradient did you think was "infinite"? (The gradient has two elements.) It'd be good to know how you're thinking about what the math library does and how it's generating gradients, especially at the boundary conditions.
I concluded that the gradient should be zero because that's the well defined limit of the gradient with respect to both mu and sigma as y approaches infinity. I concluded (incorrectly I think) that Stan's gradient was infinite (correct conclusion: not finite) by running the Stan program from the OP via cmdstanr with
Chain 1 Rejecting initial value:
Chain 1 Gradient evaluated at the initial value is not finite.
Chain 1 Stan can't start sampling from this initial value.
Based on your follow-up, I assume that the problem is the partial wrt sigma, that the NaN is the problem, and that when I said "infinite" I really meant "not finite".
The use case for returning zero here is given in the discourse thread linked from the OP. It shouldn't be particularly burdensome to code around the current behavior, which I agree isn't necessarily wrong, but if there's appetite on the Stan side for returning zero for the partial wrt sigma then that'd also solve the original discourse issue.
Activity
ASKurz commentedon Mar 6, 2023
Thank you for opening this issue, @jsocolar.
syclik commentedon Mar 7, 2023
@jsocolar, thanks for bringing this up. I'm putting up a minimal example in C++ to walk through it.
If you pop this into a file called
test/unit/math/normal_lcdf_test.cpp, you'll be able to run it from the command line like:python runTests.py test/unit/math/normal_lcdf_test.cppJust curious... how'd you come to this conclusion? And which gradient did you think was "infinite"? (The gradient has two elements.) It'd be good to know how you're thinking about what the math library does and how it's generating gradients, especially at the boundary conditions.
To get into the example, if you look at the test:
d normal_lcdf(y, mu, sigma) / dmu = 0d normal_lcdf(y, mu, sigma) / dsigma = NaN(
NaNdoes not equal infinity, but it doesn't mean that's good.)I think you're expecting
d / dsigma = 0? Is that right?I didn't trace through to figure out why it's having trouble computing that term, but I'm sure it could be addressed. I'd lean towards throwing an exception at the boundaries, but I think that would change the behavior of Stan in a way that we'd have to have a larger discussion to implement.
Thoughts?
jsocolar commentedon Mar 7, 2023
@syclik Thanks for taking a look!
I concluded that the gradient should be zero because that's the well defined limit of the gradient with respect to both
muandsigmaasyapproaches infinity. I concluded (incorrectly I think) that Stan's gradient was infinite (correct conclusion: not finite) by running the Stan program from the OP viacmdstanrwithand getting back a bunch of
Based on your follow-up, I assume that the problem is the partial wrt sigma, that the
NaNis the problem, and that when I said "infinite" I really meant "not finite".The use case for returning zero here is given in the discourse thread linked from the OP. It shouldn't be particularly burdensome to code around the current behavior, which I agree isn't necessarily wrong, but if there's appetite on the Stan side for returning zero for the partial wrt sigma then that'd also solve the original discourse issue.
avehtari commentedon Oct 7, 2026
This is fixed by #3406 (not yet merged)