probability icon indicating copy to clipboard operation
probability copied to clipboard

PoissonLogNormalQuadratureCompound parameterization doesn't match LogNormal parameterization

Open pekaalto opened this issue 5 years ago • 5 comments

What are loc and scale in this distribution.

Consider this:

import tensorflow_probability as tfp
import numpy as np
tfd = tfp.distributions

loc = 2.4
scale = 0.8

d1 = tfd.JointDistributionSequential([
    tfd.LogNormal(loc, scale),
    lambda z: tfd.Poisson(z)
])

d2 = tfd.PoissonLogNormalQuadratureCompound(loc, scale)

N = 100000
sample_1 = d1.sample(N)[1].numpy()
sample_2 = d2.sample(N).numpy()
sample_3 = np.random.poisson(np.random.lognormal(loc, scale , size=N))

print(sample_1.mean(), sample_1.var())
print(sample_2.mean(), sample_2.var())
print(sample_3.mean(), sample_3.var())
15.20101 217.6014
28675494000.0 5.8343047e+21
15.22877 224.11053428710002

Is it expected that the parameterization is different to LogNormal?

How can I obtain the "standard parameterization"? . I have tried to do log(scale) which gives closer but not correct answer.

pekaalto avatar May 13 '20 12:05 pekaalto

Also checking:

d = tfd.PoissonLogNormalQuadratureCompound(loc=0, scale=0.5)
print(d.prob(np.arange(0, 10)).numpy())

doesn't match figure 3 in this paper: https://arxiv.org/pdf/1801.03080.pdf

pekaalto avatar May 13 '20 14:05 pekaalto

What if you increase the quadrature_size parameter? The default of 8 may be too coarse.

On Wed, May 13, 2020 at 10:37 pekaalto [email protected] wrote:

Also checking:

d = tfd.PoissonLogNormalQuadratureCompound(loc=0, scale=0.5) print(d.prob(np.arange(0, 10)).numpy())

doesn't match figure 3 in this paper: https://arxiv.org/pdf/1801.03080.pdf

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/tensorflow/probability/issues/929#issuecomment-628033620, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABG2GO7C3LUJKJB62XWEXDRRKWDTANCNFSM4M7WS2TQ .

csuter avatar May 13 '20 15:05 csuter

@csuter that doesn't help. I tried up to 512 (default is 8).

I think it's just some weird reparameterization issue.

If I set scale = 0. Then these are equal.

d1 = tfd.JointDistributionSequential([
    tfd.LogNormal(mu, 0.0),
    lambda z: tfd.Poisson(z)
])

d2 = tfd.PoissonLogNormalQuadratureCompound(np.log(mu), 0.0))

But I don't know how to map the parameters if scale > 0.

I seems weird to me that we need to take log here because actually the distribution mean in this case is exp(mu).

So somehow the exps and logs are mixed here. This passes but I am not sure if it should pass:

any_number = np.random.rand()
d = tfd.PoissonLogNormalQuadratureCompound(loc = any_number, scale=0.0)
np.testing.assert_almost_equal(d.mean().numpy(), np.exp(np.exp(d.loc)), decimal=5)

pekaalto avatar May 13 '20 15:05 pekaalto

@jvdillon @langmore anything jump out at you here?

csuter avatar May 13 '20 16:05 csuter

I also ran across this issue. In short, the default value for quadrature_fn= in the constructor of PoissonLogNormalQuadratureCompound is set to quadrature_scheme_lognormal_quantiles, but this function is completely broken.

Quick fix: Create your distribution as

dist = tfd.PoissonLogNormalQuadratureCompound(..., 
                     quadrature_fn = tfd.quadrature_scheme_lognormal_gauss_hermite)

This seems to work pretty well.

More detail: From what I can see, there are two key issues:

  1. quadrature_scheme_lognormal_quantiles mixes up the log rate, which follows a normal distribution, and the rate, which follows a log-normal distribution, and attempts to parameterize log rate as log-normal.
  2. The log-normal distribution is very influenced by extreme values and so the quantile quadrature which deliberately puts all its points in the middle will have a hard time.

bwalker1 avatar Aug 25 '23 08:08 bwalker1