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 segmentdata[t:s](sexclusive). Kept for backward compatibility.pdf_rows(data, t): log marginal likelihoods ofdata[t:s]for everysint+1 .. nin 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 |
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 |
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 |
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 |
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 |
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 |
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 |
None
|
device
|
str, torch.device, or None
|
Device to place tensors on. |
None
|
cache_enabled
|
bool
|
Retained for backward compatibility (see |
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 |
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 |
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 |
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. |