stan-dev / stan-dev/math

The derivatives of neg_binomial_lpmf are incorrect for large alpha

Open
#1,578 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
839
Forks
220
Avg merge
2d 4h
Merged PRs (30d)
14

Description

Description

The neg_binomial_lpmf(n, alpha, beta) is approximated by Poisson for alpha > 1e10. While this approximation is OK for the density, the derivatives get messed up.

Example

Analytically, the derivative wrt. alpha for n = 0 is log(beta / (1 + beta)). So, for beta = 0.8 the derivative should be roughly -0.81093 irrespective of alpha. However, when we set alpha = 1e10 + 1, the current implementation evaluates the gradient as -1.25.

Similarly (and perhaps more worrying) the derivative wrt. beta for n = 0 is (alpha * (1 + beta) *(-(beta/(1 + beta)^2) + 1/(1 + beta)))/beta, so for beta = 0.8 and alpha = 1e10 + 1 the analytic derivative is 6.94e9 while the current implementation in Stan returns 1.56e10.

(see bottom of https://www.wolframcloud.com/obj/martin.modrak/Published/NegBinomial_test.nb for Mathematica code I used to obtain those).

Expected Output

On a branch (https://github.com/martinmodrak/math/blob/bugfix/1578-neg_binomial_derivatives_at_cutoff/test/unit/math/rev/prob/neg_binomial_test.cpp) I wrote a test that compares the derivatives to those computed by complex step. The test is derived from the tests implemented in #1497 for neg_binomial_2_lpmf. A good question is: "Is the complex step derivative accurate for large alpha?" Unfortunately Mathematica (at least the free cloud version) refuses to compute exact derivatives for n > 0 and alpha = 1e10, but the complex step results match exact solutions for n = 0 and the test passes for values just below the alpha cutoff, so I believe, this is a true failure. I would expect the test to pass.

Current Version:

v3.0.0

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the neg_binomial_lpmf implementation and the test at test/unit/math/rev/prob/neg_binomial_test.cpp on the referenced branch. Run that test around the alpha cutoff and compare the alpha and beta derivatives with the complex-step results; done means the large-alpha derivative checks pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.