Skip to content

Poisson, Tweedie & Count Losses

← Censored Regression | Poisson-Gaussian →

Loss functions for count data, positive-continuous targets, and distributions with power mean-variance relationships.

See the count-loss API: PoissonDevianceLoss, TweedieLoss, NegativeBinomialNLLLoss, ZeroInflatedPoissonNLLLoss.


Mathematical Background

The Tweedie family unifies many common models through a single power-variance relationship:

\[\boxed{\;\text{Var}(Y) = \phi\,\mu^p\;}\]
Power \(p\) Distribution Domain Classic Use Case
\(0\) Normal \(\mathbb{R}\) Standard regression
\(1\) Poisson \(\{0,1,2,\ldots\}\) Event counts
\(1 < p < 2\) Compound Poisson-Gamma \(\{0\} \cup \mathbb{R}^+\) Insurance claims, rainfall
\(2\) Gamma \(\mathbb{R}^+\) Prices, durations, intensities
\(3\) Inverse Gaussian \(\mathbb{R}^+\) Highly right-skewed positives

Poisson Losses

PoissonDevianceLoss

The Poisson deviance (G-statistic) — measures goodness-of-fit for count data. See PoissonDevianceLoss API.

\[D(y, \lambda) = \sum_i\!\left[y_i \log\!\left(\frac{y_i}{\lambda_i}\right) - (y_i - \lambda_i)\right]\]

(half the classical G-statistic; matches PoissonDevianceLoss in code)

from torchregress.losses import PoissonDevianceLoss

loss_fn = PoissonDevianceLoss(log_input=True)  # model predicts log(λ)
loss = loss_fn(log_lambda, y_counts)
Parameter Type Default Description
log_input bool True If True, y_pred = \(\log\lambda\)

PoissonLikelihoodRatioLoss

Baker–Cousins likelihood ratio for binned data (PDG-standard):

\[-2\ln \Lambda = 2\sum_i\!\left[f_i - n_i + n_i \ln\!\left(\frac{n_i}{f_i}\right)\right]\]
from torchregress.losses import PoissonLikelihoodRatioLoss

loss_fn = PoissonLikelihoodRatioLoss(log_input=True)
loss = loss_fn(log_expected, observed_counts)

When to use

Preferred over Poisson deviance for histogram fitting (binned spectra, histograms) where the goodness-of-fit interpretation matters. Standard in particle physics.

ZeroInflatedPoissonNLLLoss

For count data with excess zeros beyond what a standard Poisson would predict. See ZeroInflatedPoissonNLLLoss API.

\[P(Y = 0) = \pi + (1 - \pi)\,e^{-\lambda}, \qquad P(Y = k) = (1 - \pi)\,\frac{\lambda^k e^{-\lambda}}{k!}, \; k \geq 1\]
from torchregress.losses import ZeroInflatedPoissonNLLLoss

loss_fn = ZeroInflatedPoissonNLLLoss(log_input=True)
# Model outputs [log(λ), logit(π)] concatenated
loss = loss_fn(model_output, y_counts)

When to use

Species counts (most plots have zero detections), manufacturing defects, rare disease incidence.

NegativeBinomialNLLLoss

For overdispersed count data where \(\text{Var}(Y) > \mathbb{E}[Y]\). See NegativeBinomialNLLLoss API.

\[\text{Var}(Y) = \mu + \frac{\mu^2}{\theta}\]
from torchregress.losses import NegativeBinomialNLLLoss

loss_fn = NegativeBinomialNLLLoss(learn_theta=True)  # learn dispersion
loss = loss_fn(y_pred_mean, y_counts)
Parameter Type Default Description
learn_theta bool False Learn the dispersion parameter \(\theta\)
min_theta float 1e-6 Minimum \(\theta\) for stability

When to use

When Poisson is a poor fit (residual variance >> mean): gene expression counts (RNA-seq), ecological overdispersion, web traffic.


Tweedie Losses

TweedieLoss

General-purpose Tweedie deviance for any power \(p\). See TweedieLoss API.

\[D(y, \mu) = \frac{1}{2}(y - \mu)^2\]
\[D(y, \mu) = 2\bigl[\mu - y + y\log(y/\mu)\bigr]\]
\[D(y, \mu) = 2\!\left[\log(\mu/y) + y/\mu - 1\right]\]
\[D(y, \mu) = \frac{2}{(2-p)(1-p)}\!\left[y^{2-p} - (2-p)\,y\,\mu^{1-p} + (1-p)\,\mu^{2-p}\right]\]
from torchregress.losses import TweedieLoss

# Compound Poisson-Gamma (zeros + positive continuous)
loss_fn = TweedieLoss(p=1.5, link="log")

# Model predicts log(μ)
loss = loss_fn(log_mu, y_target)
Parameter Type Default Description
p float 1.5 Power parameter
link str or None None "log" or "identity"

GammaLoss

Convenience class for \(p = 2\) (positive continuous targets with constant CV):

from torchregress.losses import GammaLoss

loss_fn = GammaLoss(link="log")

When to use

Prices, durations, insurance payouts — positive targets where the coefficient of variation is roughly constant.

InverseGaussianLoss

For \(p = 3\) (highly right-skewed positive targets):

from torchregress.losses import InverseGaussianLoss

loss_fn = InverseGaussianLoss(link="log")

Strictly positive targets

GammaLoss and InverseGaussianLoss (and TweedieLoss with \(p \ge 2\)) raise ValueError if any unmasked target is \(\le 0\): both densities have support \(y > 0\) and their deviances are undefined at \(y = 0\). For data with exact zeros use CompoundPoissonLoss (\(1 < p < 2\)) or a hurdle model; do not shift the targets, which changes the estimand.

CompoundPoissonLoss

For \(1 < p < 2\) — handles data with a point mass at zero and positive continuous values:

from torchregress.losses import CompoundPoissonLoss

loss_fn = CompoundPoissonLoss(p=1.5, link="log")

Insurance example

In insurance, most policies have zero claims (point mass at 0), but claims that do occur are continuous and right-skewed — exactly the compound Poisson-Gamma model.

Numerical Limitations of Compound Poisson (1 < p < 2)

Evaluating the Tweedie likelihood for \(1 < p < 2\) involves an infinite series representation of the density function (Dunn & Smyth, 2005). Because of this, evaluations can be computationally slower than plain Poisson or Gamma losses. Additionally, if the power parameter \(p\) is close to 1 or 2, gradient computation can become numerically unstable. Ensure you set a stable min_std / jitter and monitor gradients.

Numerical pitfalls across all Tweedie variants

  • Negative log-rates: When log_input=True, the model predicts \(\log\lambda\). If predicted log-rates become negative and the link exponentiates them, the rate \(\lambda = e^{\log\lambda}\) stays positive — but large negative log-rates produce near-zero rates that can cause log(0) operations in deviance terms. Clamp or use a minimum rate floor.
  • Near-boundary instability (\(p \to 1\) or \(p \to 2\)): The Tweedie density normalizing constant involves the infinite series mentioned above. As \(p\) approaches 1 (Poisson boundary) or 2 (Gamma boundary), the series converges very slowly, causing both runtime and gradient issues. For \(p\) exactly 1 or 2, use the specialized PoissonDevianceLoss or GammaLoss instead.
  • Dispersion sensitivity (Negative Binomial): NegativeBinomialNLLLoss with a very small dispersion \(\theta\) (< 0.01) produces extreme overdispersion where the variance-to-mean ratio becomes huge, leading to unstable gradients. Use min_theta to floor the dispersion parameter.

Limitations

  1. Compound Poisson numerical instability (\(1 < p < 2\)): The Tweedie density normalising constant involves an infinite series that converges slowly near the boundaries \(p \to 1\) (Poisson) and \(p \to 2\) (Gamma). Use PoissonDevianceLoss or GammaLoss for exactly \(p = 1\) or \(p = 2\).
  2. Negative log-rate clipping: When log_input=True, large negative predicted log-rates produce near-zero rates \(\lambda = e^{\log\lambda}\), leading to \(\log(0)\) in deviance terms. Always clamp the minimum rate (min_rate) or use a small jitter.
  3. Negative Binomial dispersion sensitivity: NegativeBinomialNLLLoss with \(\theta < 0.01\) produces extreme overdispersion with unstable gradients. Floor \(\theta\) with min_theta.
  4. Tweedie power \(p\) is not learned: The power parameter \(p\) must be specified externally (e.g., from domain knowledge or a profile likelihood sweep). The loss does not optimise \(p\) jointly with the model.
  5. Zero-inflated model identifiability: ZeroInflatedPoissonNLLLoss jointly estimates \(\pi\) (zero-inflation probability) and \(\lambda\) (rate). These parameters can trade off, especially with small datasets. Monitor both during training.

Decision Guide

graph TD
    A["Count / positive data?"] -->|Counts ∈ ℤ⁺| B{"Overdispersed?"}
    A -->|"Positive continuous"| C{"Zeros present?"}
    A -->|"Mixed: zeros + continuous"| D["CompoundPoissonLoss"]
    B -->|No| E["PoissonDevianceLoss"]
    B -->|"Var >> mean"| F["NegativeBinomialNLLLoss"]
    B -->|"Excess zeros"| G["ZeroInflatedPoissonNLLLoss"]
    C -->|No| H{"CV constant?"}
    C -->|Yes| D
    H -->|Yes| I["GammaLoss"]
    H -->|"Highly skewed"| J["InverseGaussianLoss"]

Complete Example

import torch
import torch.nn as nn
from torchregress.losses import TweedieLoss, NegativeBinomialNLLLoss

# Insurance claims: many zeros, occasional large payouts
class ClaimsModel(nn.Module):
    def __init__(self, in_dim):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(in_dim, 64), nn.ReLU(),
            nn.Linear(64, 32), nn.ReLU(),
            nn.Linear(32, 1),
        )

    def forward(self, x):
        return self.net(x)  # predicts log(μ)

model = ClaimsModel(in_dim=20)
loss_fn = TweedieLoss(p=1.6, link="log")  # compound Poisson-Gamma
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

for x, y in train_loader:
    loss = loss_fn(model(x), y)
    optimizer.zero_grad(); loss.backward(); optimizer.step()

Next steps


References

# Reference
1 B. Jørgensen. "Exponential Dispersion Models." JRSS-B, 49(2):127–162, 1987.
2 P. Dunn, G. Smyth. "Evaluation of Tweedie Exponential Dispersion Model Densities." J. Stat. Comp. Sim., 73(4):325–349, 2005.
3 P. McCullagh, J.A. Nelder. Generalized Linear Models, 2nd ed. Chapman & Hall, 1989.
4 S. Baker, R.D. Cousins. "Clarification of the Use of Chi-square and Likelihood Functions in Fits to Histograms." Nucl. Instr. Meth., 221(2):437–442, 1984.
5 J. Nelder, R. Wedderburn. "Generalized Linear Models." JRSS-A, 135(3):370–384, 1972.