#include <stan/agrad/rev/sqrt.hpp>
#include <gtest/gtest.h>
#include <stan/agrad/var.hpp>
TEST(AgradRev,sqrt_square_zero) {
stan::agrad::var x(0.0);
stan::agrad::var f = sqrt(square(x));
EXPECT_FLOAT_EQ(0.0,f.val());
std::vector<stan::agrad::var> g;
g.push_back(x);
std::vector<double> gradient;
f.grad(g,gradient);
EXPECT_FLOAT_EQ(1.0,gradient[0]);
}
I can fix it. I worked out the analytic gradients,
which don't have this problem. That'll solve the
specific case of sd().
Not much we can do about general code that does sqrt(0)
but has some analytic reduction, like sqrt(square(x)) = x.
In general, there are lots of ways to express square(x), such
as x * x. And the case for sd() is more like sqrt(sum(square(x)).
I don't know how to do runtime type resolution, but we
might be able to catch the expression tree structure and
collapse it. But that doesn't solve the multiple ways
to express it problem.
To unsubscribe from this group and stop receiving emails from it, send an email to stan-dev+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups "stan development mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to stan-dev+unsubscribe@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to stan-dev+u...@googlegroups.com.
I'm also OK with just raising an exception or returning an infinite
gradient.
BTW, you are going to have the same issue whenever we reimplement vectors that are uniform on a sphere by normalizing a vector of iid standard normals. If they do init = 0, then you divide by the square root of zero in the denominator.
Returning a subgradient won't affect HMC at all except maybe on the level of efficiency but then only when there is significant mass at that region and even then I expect the impact to be small because we're returning something which will be close.
It's not "bad statistical mojo" as It certainly won't impact the statistical validity of our samples since a) the Metropolis test will use the same "correct" log prob and b) so long as the same subgradient is returned, the simulation will be reversible. Patching the gradient is basically just using a different simulation Hamiltonian which is only different from the correct one in a small region around these gradient singularities.If we throw an exception we're just going to reject everything and stop sampling in that region altogether. Further, these rejections won't just occur at exactly x = 0, returning an unusually large gradient can overflow chain() calculations elsewhere resulting in a nan or inf gradient.Regarding efficiency of patching the gradient vs throwing an exception, it's not clear which will be more efficient. It seems to me allowing it to traverse through a region instead of automatically rejecting any trajectory which comes near the singularity would be more statistically efficient.
On Wed, Nov 20, 2013 at 11:52 AM, Marcus Brubaker <marcus.a...@gmail.com> wrote:
Returning a subgradient won't affect HMC at all except maybe on the level of efficiency but then only when there is significant mass at that region and even then I expect the impact to be small because we're returning something which will be close.Unfortunately, we're artificially giving mass in these regions significant mass since we're initializing starting at 0.
It's not "bad statistical mojo" as It certainly won't impact the statistical validity of our samples since a) the Metropolis test will use the same "correct" log prob and b) so long as the same subgradient is returned, the simulation will be reversible. Patching the gradient is basically just using a different simulation Hamiltonian which is only different from the correct one in a small region around these gradient singularities.If we throw an exception we're just going to reject everything and stop sampling in that region altogether. Further, these rejections won't just occur at exactly x = 0, returning an unusually large gradient can overflow chain() calculations elsewhere resulting in a nan or inf gradient.Regarding efficiency of patching the gradient vs throwing an exception, it's not clear which will be more efficient. It seems to me allowing it to traverse through a region instead of automatically rejecting any trajectory which comes near the singularity would be more statistically efficient.I'm in favor of catching errors early. One reason this was difficult to track down from the outside was due to the gradients going to nan without informative error messages. It was baffling because it only happened with sampling and not with optimization or test gradient mode. I believe we'll get a handle on the sqrt(square(0)) case soon, but the fundamental reason for this issue isn't going away and I'd like to be able to identify the problems much quicker.
Right now, I don't think we check gradients for nan values. Should we? It seems like a reasonable thing to do as opposed to what we currently do now, which is to integrate using nan derivatives and failing when the nans propagate to the positions. This could be done independent of error checking using exceptions.
On Wed, Nov 20, 2013 at 12:12 PM, Daniel Lee <bea...@alum.mit.edu> wrote:
On Wed, Nov 20, 2013 at 11:52 AM, Marcus Brubaker <marcus.a...@gmail.com> wrote:
Returning a subgradient won't affect HMC at all except maybe on the level of efficiency but then only when there is significant mass at that region and even then I expect the impact to be small because we're returning something which will be close.Unfortunately, we're artificially giving mass in these regions significant mass since we're initializing starting at 0.That doesn't give the region mass. If it has little real mass, sampling should quickly transition out of the region assuming that sampling can actually proceed.
It's not "bad statistical mojo" as It certainly won't impact the statistical validity of our samples since a) the Metropolis test will use the same "correct" log prob and b) so long as the same subgradient is returned, the simulation will be reversible. Patching the gradient is basically just using a different simulation Hamiltonian which is only different from the correct one in a small region around these gradient singularities.If we throw an exception we're just going to reject everything and stop sampling in that region altogether. Further, these rejections won't just occur at exactly x = 0, returning an unusually large gradient can overflow chain() calculations elsewhere resulting in a nan or inf gradient.Regarding efficiency of patching the gradient vs throwing an exception, it's not clear which will be more efficient. It seems to me allowing it to traverse through a region instead of automatically rejecting any trajectory which comes near the singularity would be more statistically efficient.I'm in favor of catching errors early. One reason this was difficult to track down from the outside was due to the gradients going to nan without informative error messages. It was baffling because it only happened with sampling and not with optimization or test gradient mode. I believe we'll get a handle on the sqrt(square(0)) case soon, but the fundamental reason for this issue isn't going away and I'd like to be able to identify the problems much quicker.
Catching errors early is good but throwing exceptions is only useful if the caller is actually in a position to do something useful about it or there is no other resory. In this case, all the caller can do is reject the sample and/or bail back to the user who is even less equipped to do something about it.
Sorry, the current error message is:Here's the command line output:
"Rejecting inititialization at zero because of divergent gradient."
Here's the model (sd.stan):
parameters {
vector<lower=-1,upper=1>[5] y;
}
transformed parameters {
real sd_y;
sd_y <- sd(y);
}
model {
y ~ normal(0,1);
}
> ../user_models/issue-379/sd sample init=0
Rejecting inititialization at zero because of divergent gradient.
>That's our current implementation. We start there and end there. No indication that the sd() function is the one that's giving us grief.
I thought a NaN gradient would throw the same exception that bad constraints does
but I guess I'm wrong. We could just have the gradient functors check and throw
the necessary exceptions.
If we change the gradient near singularities does it still get stuck?
Throwing an exception effectively punts the problem to the user. I agree that we should be producing better error better error messages.
There are two options -- either there's not enough mass around zero, chains never hit the singularity, and everything is fine. But if there is enough mass around zero then the chains can hit the singularity and problems arise. As Dan noted the fact that people like "0" makes initialization a problem even if sampling isn't. In either case, the user should be informed because they have an ill-defined gradient being used in their model which is a bad idea™ as it is usually indicative of a modeling (or initialization) mistake.
On Nov 20, 2013, at 6:48 PM, Marcus Brubaker <marcus.a...@gmail.com> wrote:
> If we change the gradient near singularities does it still get stuck? Throwing an exception effectively punts the problem to the user. I agree that we should be producing better error better error messages.