cofi.utils.ReducedLikelihood#
- class cofi.utils.ReducedLikelihood(data: ndarray, forward_func: Callable, fwd_kwargs: dict | None = None, G: ndarray | None = None, Cd_ref: ndarray | None = None, case: str = 'none', nu: float = 4.0, s: float = 1.0, eps: float = 1e-154, kernel=None, n_params: int | None = None)[source]#
Reduced likelihood for various data covariance cases.
This class implements reduced likelihood functions for different assumptions about the data covariance structure:
‘none’: Fixed covariance (standard Gaussian likelihood)
‘scaled’: Scaled reference covariance
‘kernel’: Profiled amplitude with parameterized kernel covariance
‘kernel_full’: Explicit amplitude with parameterized kernel covariance
‘spherical’: Spherical covariance (diagonal with same variance)
‘diag’: Diagonal covariance with Student-t likelihood (robust)
‘diag_legacy’: Diagonal covariance (legacy, numerically unstable near zero)
‘full’: Full covariance matrix estimation
- Parameters:
data (np.ndarray) – The observed data vector of shape (n_data,)
forward_func (Callable) – A callable that takes model parameters and returns predicted data of shape (n_data,). Should accept **fwd_kwargs if provided.
fwd_kwargs (dict, optional) – Keyword arguments to pass to forward_func
G (Optional[np.ndarray], default=None) – Jacobian matrix of shape (n_data, n_params). Required for
gradient()andhessian()but not forlog_likelihood(). Must be updated before each evaluation for non-linear problems.Cd_ref (Optional[np.ndarray], default=None) – Reference covariance matrix. Required for ‘scaled’ case. For ‘none’ case: if not provided, defaults to identity matrix (assumes uncorrelated, unit-variance noise). Not used for ‘spherical’, ‘diag’, ‘diag_legacy’, or ‘full’ cases.
kernel (optional) – Kernel instance (e.g.
SquaredExponentialKernel). Required forcase='kernel'. Must exposen_params,evaluate(eta),derivative(eta), andsecond_derivative(eta)methods.case (str, default='none') – The covariance case: ‘none’, ‘scaled’, ‘kernel’, ‘kernel_full’, ‘spherical’, ‘diag’, ‘diag_legacy’, or ‘full’. The
'kernel_full'case is like'kernel'but with explicitphi = log(sigma_d)as a parameter instead of profilingsigma_dout. Model vector:[m_phys, phi, eta].nu (float, default=4.0) – Degrees of freedom for Student-t likelihood (used in ‘diag’ case). Smaller values (e.g., 3-5) give heavier tails and more robustness to outliers. Larger values approach Gaussian behavior.
s (float, default=1.0) – Scale parameter for Student-t likelihood (used in ‘diag’ case). Controls the width of the distribution. Should be set to approximate the expected noise standard deviation (e.g., via a quick least-squares prefit).
eps (float, default=1e-154) – Small number for numerical stability
n_params (int, optional) – Number of physical model parameters (excluding kernel hyperparameters). When
Gis provided, this is inferred fromG.shape[1]. WhenG=None, provide this to enable model shape validation forlog_likelihood()without computing the Jacobian. If bothGandn_paramsare provided, they must be consistent (G.shape[1] == n_params).
- Raises:
ValueError – If Cd_ref is not provided for ‘scaled’ case If kernel is not provided for ‘kernel’ case If case is not one of the supported options If G is not set when calling gradient() or hessian()
Examples
>>> import numpy as np >>> from cofi.utils import ReducedLikelihood >>> >>> # Define data and forward function >>> data = np.array([1.0, 2.0, 3.0]) >>> def forward_func(m): ... return np.array([m[0], m[1], m[0] + m[1]]) # Linear forward model >>> >>> # Jacobian matrix (can be computed separately) >>> G = np.array([[1, 0], [0, 1], [1, 1]]) >>> >>> # Create likelihood with spherical covariance assumption >>> likelihood = ReducedLikelihood( ... data=data, ... forward_func=forward_func, ... G=G, ... case='spherical' ... ) >>> >>> # Evaluate at a model >>> model = np.array([1.5, 2.5]) >>> log_p = likelihood.log_likelihood(model) >>> grad = likelihood.gradient(model) >>> hess = likelihood.hessian(model) >>> >>> # For non-linear problems, update G before each evaluation >>> new_model = np.array([2.0, 3.0]) >>> # Compute new Jacobian (e.g., using finite differences) >>> G_new = compute_jacobian(new_model) # User-defined >>> likelihood.G = G_new >>> log_p_new = likelihood.log_likelihood(new_model)
Derivative-free optimization (no Jacobian needed):
>>> # For Nelder-Mead or other derivative-free methods, >>> # only log_likelihood() is needed — no G required. >>> likelihood = ReducedLikelihood( ... data=data, ... forward_func=forward_func, ... case='spherical', ... n_params=2, # number of model parameters ... ) >>> log_p = likelihood.log_likelihood(model) # Works without G
Reference Details
- __call__(model: ndarray) float#
A class instance itself can also be called as a function.
It works exactly the same as
log_likelihood.In other words, the following two usages are exactly the same:
>>> my_likelihood = GaussianLikelihood(data, forward_func) >>> log_p = my_likelihood(np.array([1,2,3])) # usage 1 >>> log_p = my_likelihood.log_likelihood(np.array([1,2,3])) # usage 2
- Parameters:
model (np.ndarray) – The model parameters to evaluate
- Returns:
The log-likelihood value
- Return type:
float
- get_ml_cov(model: ndarray) ndarray | None[source]#
Evaluate the covariance matrix at given model parameters.
This method does not require the Jacobian matrix
Gto be set.
- gradient(model: ndarray) ndarray[source]#
Evaluate the gradient at given model parameters.
Requires the Jacobian matrix
Gto be set. IfG=None, raisesValueErrorwith guidance on how to proceed.
- hessian(model: ndarray) ndarray[source]#
Evaluate the hessian at given model parameters.
Requires the Jacobian matrix
Gto be set. IfG=None, raisesValueErrorwith guidance on how to proceed.
- log_likelihood(model: ndarray) float[source]#
Evaluate the log-likelihood at given model parameters.
This method does not require the Jacobian matrix
Gto be set.
- G#
Jacobian matrix of shape (n_data, n_params).
- model_shape#
Return the model shape.
- model_size#
The number of unknowns that current likelihood function accepts.
- Returns:
The total number of model parameters
- Return type:
Number