},
{
'rate': 0.2,
+ },
+ {
+ 'rate': torch.tensor([0.0], requires_grad=True),
+ },
+ {
+ 'rate': 0.0,
}
]),
Example(RelaxedBernoulli, [
]),
Example(Poisson, [
{
- 'rate': torch.tensor([0.0], requires_grad=True),
+ 'rate': torch.tensor([-0.1], requires_grad=True),
},
{
'rate': -1.0,
def test_poisson_log_prob(self):
rate = torch.randn(2, 3).abs().requires_grad_()
rate_1d = torch.randn(1).abs().requires_grad_()
+ rate_zero = torch.zeros([], requires_grad=True)
- def ref_log_prob(idx, x, log_prob):
- l = rate.view(-1)[idx].detach()
+ def ref_log_prob(ref_rate, idx, x, log_prob):
+ l = ref_rate.view(-1)[idx].detach()
expected = scipy.stats.poisson.logpmf(x, l)
self.assertEqual(log_prob, expected, atol=1e-3, rtol=0)
set_rng_seed(0)
- self._check_log_prob(Poisson(rate), ref_log_prob)
+ self._check_log_prob(Poisson(rate), lambda *args: ref_log_prob(rate, *args))
+ self._check_log_prob(Poisson(rate_zero), lambda *args: ref_log_prob(rate_zero, *args))
self._gradcheck_log_prob(Poisson, (rate,))
self._gradcheck_log_prob(Poisson, (rate_1d,))
+ # We cannot check gradients automatically for zero rates because the finite difference
+ # approximation enters the forbidden parameter space. We instead compare with the
+ # theoretical results.
+ dist = Poisson(rate_zero)
+ s = dist.sample()
+ dist.log_prob(s).backward()
+ torch.testing.assert_allclose(rate_zero.grad, -1.0)
+ dist.log_prob(torch.ones_like(rate_zero)).backward()
+ torch.testing.assert_allclose(rate_zero.grad, torch.inf)
+
@unittest.skipIf(IS_MACOS, "See https://github.com/pytorch/pytorch/issues/60347")
@unittest.skipIf(not TEST_NUMPY, "Numpy not found")
def test_poisson_sample(self):
- name: xlogy.Tensor(Tensor self, Tensor other) -> Tensor
self: grad * at::xlogy((self != 0), other)
- other: grad * self / other
+ other: grad * at::where(other.isnan() | (self != 0), self / other, zeros_like(other))
result: self_t * at::xlogy((self_p != 0), other_p) + other_t * self_p / other_p
- name: xlogy.Scalar_Self(Scalar self, Tensor other) -> Tensor
- other: grad * self / other
+ other: grad * at::where(other.isnan() | (!self.equal(0)), self / other, zeros_like(other))
result: auto_element_wise
- name: xlogy.Scalar_Other(Tensor self, Scalar other) -> Tensor
Args:
rate (Number, Tensor): the rate parameter
"""
- arg_constraints = {'rate': constraints.positive}
+ arg_constraints = {'rate': constraints.nonnegative}
support = constraints.nonnegative_integer
@property
if self._validate_args:
self._validate_sample(value)
rate, value = broadcast_all(self.rate, value)
- return (rate.log() * value) - rate - (value + 1).lgamma()
+ return value.xlogy(rate) - rate - (value + 1).lgamma()
@property
def _natural_params(self):