Skip to content

[BUG] NegativeBinomial uses the scipy probs convention with torch — the mean head parameterizes r²/µ #418

Description

@ChrisW09

Describe the bug
NegativeBinomialDistribution uses the scipy success-probability convention with torch's NegativeBinomial, inverting the parameterization (deeptab/distributions/negative_binomial.py:41-44):

r = torch.tensor(1.0) / dispersion
p = r / (r + mean)
dist.NegativeBinomial(total_count=r, probs=p)

torch defines mean = total_count * probs / (1 - probs), so probs must be mean / (r + mean). With the code as written, the constructed distribution's mean is r²/µ instead of µ (verified: µ=10, r=1 gives distribution mean 0.1).

Training still converges — the network simply learns whatever head output makes softplus(head) equal r²/µ — but the "mean" column is then not the mean, so every downstream consumer silently gets garbage: predict() output, mean-based metrics (RMSE/MAE via _extract_mean), and NegativeBinomialDeviance which reads column 0 as µ.

To Reproduce

import torch
import torch.distributions as dist

mu, r = torch.tensor(10.0), torch.tensor(1.0)
print(dist.NegativeBinomial(total_count=r, probs=r / (r + mu)).mean)   # 0.1  (= r^2/mu)
print(dist.NegativeBinomial(total_count=r, probs=mu / (r + mu)).mean)  # 10.0 (correct)

Expected behavior
probs = mean / (r + mean) (or equivalently logits = log(mean) - log(r)), so that the head column trained as the mean actually parameterizes the mean.

Screenshots
n/a

Desktop (please complete the following information):

  • OS: macOS (Darwin 25.5.0, arm64)
  • Python version: 3.11.15
  • deeptab Version: 2.0.0 (main @ 4e6a359)

Additional context
The in-code comment # variance = mean + mean^2 / dispersion is also inconsistent with r = 1/dispersion (that choice yields var = µ + µ²·dispersion) — worth clarifying which convention dispersion is meant to follow. NegativeBinomialDeviance in deeptab/metrics/distributional.py interprets its alpha as the size r, while the model's column 1 is dispersion = 1/r under the training code — the two should be reconciled together with this fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions