Skip to content

Offline likelihoods

Offline likelihood functions for Bayesian changepoint detection.

This module provides likelihood functions for offline (batch) changepoint detection using PyTorch for efficient computation and GPU acceleration.

All likelihoods expose two evaluation entry points:

  • pdf(data, t, s): log marginal likelihood of the segment data[t:s] (s exclusive). Kept for backward compatibility.
  • pdf_rows(data, t): log marginal likelihoods of data[t:s] for every s in t+1 .. n in a single vectorized pass. The dynamic programming driver uses this method; it is the reason offline detection runs in seconds instead of minutes (see GitHub issue #47).

Sufficient statistics (cumulative sums of x and x**2, and cumulative outer products where needed) are computed once per dataset by setup() and reused for every segment query.

BaseLikelihood

Bases: ABC

Abstract base class for offline likelihood functions.

Subclasses must implement pdf and should override _compute_stats and pdf_rows for vectorized evaluation. The default pdf_rows falls back to calling pdf once per segment, so existing subclasses keep working unchanged.

Parameters:

Name Type Description Default
device str, torch.device, or None

Device to place tensors on (CPU or GPU).

None
cache_enabled bool

Retained for backward compatibility. Sufficient statistics are now precomputed once per dataset by setup(); there is no per-call cache to enable or disable.

True

setup(data)

Prepare per-dataset sufficient statistics.

Idempotent and cheap when called repeatedly with the same tensor: statistics are recomputed only when the underlying storage, its in-place mutation counter, the shape, strides, dtype, or device of data change.

Returns the prepared [T, D] tensor the statistics refer to.

pdf(data, t, s) abstractmethod

Compute the log marginal likelihood of the segment data[t:s].

Parameters:

Name Type Description Default
data Tensor

The complete time series data.

required
t int

Start index of the segment (inclusive).

required
s int

End index of the segment (exclusive).

required

Returns:

Type Description
float

Log marginal likelihood of data[t:s].

pdf_rows(data, t)

Log marginal likelihoods of data[t:s] for all s in t+1 .. n.

Returns a tensor of shape [n - t] whose element j equals pdf(data, t, t + 1 + j). Subclasses override this with a fully vectorized implementation; this fallback loops over pdf so that third-party likelihoods only implementing pdf keep working.

StudentT

Bases: _CumsumLikelihood

Student's t (Normal-Gamma) marginal likelihood for offline detection.

Computes the exact closed-form log marginal likelihood of a segment under a Normal likelihood with conjugate Normal-Gamma prior on (mean, precision) (Murphy, "Conjugate Bayesian analysis of the Gaussian distribution", 2007, eq. 95-97). Multivariate input is treated as independent dimensions whose log marginals are summed, matching the historical behavior of this class.

Parameters:

Name Type Description Default
alpha0 float

Prior shape parameter for precision (default: 1.0).

1.0
beta0 float

Prior rate parameter for precision (default: 1.0).

1.0
kappa0 float

Prior precision scaling for the mean (default: 1.0).

1.0
mu0 float

Prior mean (default: 0.0).

0.0
device str, torch.device, or None

Device to place tensors on.

None
cache_enabled bool

Retained for backward compatibility (see BaseLikelihood).

True

Examples:

>>> import torch
>>> likelihood = StudentT()
>>> data = torch.randn(100)
>>> log_prob = likelihood.pdf(data, 10, 50)  # Segment from 10 to 50
Notes

Earlier versions evaluated every segment point under the posterior predictive with the final posterior parameters, which is an approximation of the marginal likelihood. This implementation computes the exact marginal in closed form; it is also what makes full vectorization possible.

pdf(data, t, s)

Compute the log marginal likelihood of data[t:s].

Parameters:

Name Type Description Default
data Tensor

Complete time series data.

required
t int

Start index (inclusive).

required
s int

End index (exclusive).

required

Returns:

Type Description
float

Log marginal likelihood of the segment.

IndependentFeaturesLikelihood

Bases: _CumsumLikelihood

Independent features likelihood for multivariate data.

Assumes features are independent with unknown means and variances, following section 3.1 of Xuan & Murphy (2007). The math matches the original NumPy implementation of this package exactly.

Parameters:

Name Type Description Default
device str, torch.device, or None

Device to place tensors on.

None
cache_enabled bool

Retained for backward compatibility (see BaseLikelihood).

True

Examples:

>>> import torch
>>> likelihood = IndependentFeaturesLikelihood()
>>> data = torch.randn(100, 5)  # 100 time points, 5 dimensions
>>> log_prob = likelihood.pdf(data, 10, 50)

pdf(data, t, s)

Compute the log marginal likelihood of data[t:s] assuming independent features.

Parameters:

Name Type Description Default
data Tensor

Complete time series data (shape: [T] or [T, D]).

required
t int

Start index (inclusive).

required
s int

End index (exclusive).

required

Returns:

Type Description
float

Log marginal likelihood of the segment.

FullCovarianceLikelihood

Bases: _CumsumLikelihood

Full covariance likelihood for multivariate data.

Models the full covariance structure following section 3.2 of Xuan & Murphy (2007). The math matches the original NumPy implementation of this package exactly.

Parameters:

Name Type Description Default
device str, torch.device, or None

Device to place tensors on.

None
cache_enabled bool

Retained for backward compatibility (see BaseLikelihood).

True

Examples:

>>> import torch
>>> likelihood = FullCovarianceLikelihood()
>>> data = torch.randn(100, 3)  # 100 time points, 3 dimensions
>>> log_prob = likelihood.pdf(data, 10, 50)

pdf(data, t, s)

Compute the log marginal likelihood of data[t:s] using the full covariance model.

Parameters:

Name Type Description Default
data Tensor

Complete time series data (shape: [T] or [T, D]).

required
t int

Start index (inclusive).

required
s int

End index (exclusive).

required

Returns:

Type Description
float

Log marginal likelihood of the segment.

MultivariateT

Bases: _CumsumLikelihood

Multivariate Student's t (Normal-Wishart) likelihood for offline detection.

Computes the exact log marginal likelihood of a segment under a multivariate Normal likelihood with conjugate Normal-Wishart prior on (mean vector, precision matrix).

Parameters:

Name Type Description Default
dims int

Number of dimensions. If None, taken from the data on every call; if given, data with a different dimension raises ValueError.

None
dof0 float

Prior degrees of freedom (default: dims + 1).

None
kappa0 float

Prior precision for mean (default: 1.0).

1.0
mu0 Tensor

Prior mean vector (default: zero vector).

None
Psi0 Tensor

Scale matrix of the prior on the covariance side (the inverse of the Wishart scale W used by the online MultivariateT): Psi0 = dof0 * C encodes a prior covariance C. Default dof0 * I, i.e. unit prior covariance, matching the online class. Versions up to 1.1.0 used I, which is dof0 times tighter.

None
device str, torch.device, or None

Device to place tensors on.

None
cache_enabled bool

Retained for backward compatibility (see BaseLikelihood).

True

Examples:

>>> import torch
>>> likelihood = MultivariateT(dims=3)
>>> data = torch.randn(100, 3)
>>> log_prob = likelihood.pdf(data, 10, 50)

pdf(data, t, s)

Compute the log marginal likelihood of data[t:s] under the multivariate Student's t model.

Parameters:

Name Type Description Default
data Tensor

Complete time series data (shape: [T] or [T, D]).

required
t int

Start index (inclusive).

required
s int

End index (exclusive).

required

Returns:

Type Description
float

Log marginal likelihood of the segment.

Poisson

Bases: _CumsumLikelihood

Poisson (Gamma-Poisson) marginal likelihood for offline detection of changes in the rate of count data.

Each segment's counts are i.i.d. Poisson with an unknown rate lambda under a conjugate Gamma(alpha0, beta0) prior (shape, rate). The marginal likelihood of a segment of n counts with sum S is, in closed form (Gelman et al., Bayesian Data Analysis, 3rd ed., section 2.6, Poisson model with gamma prior):

log p = lgamma(alpha0 + S) - lgamma(alpha0) + alpha0 log(beta0) - (alpha0 + S) log(beta0 + n) - sum_i lgamma(x_i + 1).

Multivariate input is treated as independent Poisson dimensions, as StudentT does, and their log marginals are summed.

Parameters:

Name Type Description Default
device str, torch.device, or None

Device to place tensors on.

None
cache_enabled bool

Retained for backward compatibility (see BaseLikelihood).

True
alpha0 float

Shape of the Gamma prior on the rate (default 1.0).

1.0
beta0 float

Rate of the Gamma prior on the rate (default 1.0). The prior mean rate is alpha0 / beta0; a small beta0 makes the prior vague.

1.0

Raises:

Type Description
ValueError

If the data contain negative or non-integer values.

Examples:

>>> import torch
>>> likelihood = Poisson(alpha0=1.0, beta0=0.1)
>>> counts = torch.poisson(torch.full((100,), 4.0))
>>> log_marginal = likelihood.pdf(counts, 10, 50)

pdf(data, t, s)

Log marginal likelihood of the counts data[t:s].

Parameters:

Name Type Description Default
data Tensor

Complete series of counts.

required
t int

Start index (inclusive).

required
s int

End index (exclusive).

required

Returns:

Type Description
float

Log marginal likelihood of the segment.

NormalKnownVariance

Bases: _CumsumLikelihood

Normal likelihood with known variance and a conjugate Normal prior on the mean, for offline detection of changes in the mean when the noise level is known.

Within a segment x_i ~ N(mu, variance) i.i.d. with mu ~ N(mu0, prior_variance). Integrating mu out, the n values of a segment are jointly Normal with mean mu0 and covariance variance I + prior_variance 1 1^T (Murphy, "Conjugate Bayesian analysis of the Gaussian distribution", 2007, section 2), so with d_i = x_i - mu0 and c = variance + n prior_variance:

log p = -n/2 log(2 pi) - (n-1)/2 log(variance) - 1/2 log(c) - (sum d_i^2 - prior_variance (sum d_i)^2 / c) / (2 variance).

Multivariate input is treated as independent dimensions sharing the same hyperparameters, and their log marginals are summed.

Parameters:

Name Type Description Default
device str, torch.device, or None

Device to place tensors on.

None
cache_enabled bool

Retained for backward compatibility (see BaseLikelihood).

True
variance float

The known observation variance (default 1.0). Only changes in the mean are modeled; if the true variance differs, variance changes and misfit show up as mean changes.

1.0
mu0 float

Prior mean of the segment mean (default 0.0).

0.0
prior_variance float

Prior variance of the segment mean (default 1.0). Make it large compared with the spread of segment means you expect.

1.0

Examples:

>>> import torch
>>> likelihood = NormalKnownVariance(variance=0.25, prior_variance=100.0)
>>> data = torch.cat([torch.randn(50) * 0.5, torch.randn(50) * 0.5 + 2])
>>> log_marginal = likelihood.pdf(data, 0, 50)

pdf(data, t, s)

Log marginal likelihood of data[t:s].

Parameters:

Name Type Description Default
data Tensor

Complete time series.

required
t int

Start index (inclusive).

required
s int

End index (exclusive).

required

Returns:

Type Description
float

Log marginal likelihood of the segment.