spey.backends.default_pdf.simple_pdf.MultivariateNormal#
- class spey.backends.default_pdf.simple_pdf.MultivariateNormal(signal_yields: List[float] | Callable[[ndarray], ndarray], background_yields: List[float], data: List[int], covariance_matrix: List[List[float]] | callable, n_signal_parameters: int = 0, signal_parameter_bounds: List[Tuple[float | None, float | None]] | None = None)[source]#
Multivariate Normal likelihood with optional parameter-dependent covariance (
default.multivariate_normal).This backend models the likelihood as a single multivariate normal distribution over all bins simultaneously, capturing inter-bin correlations through an \(N \times N\) covariance matrix \(\Sigma\):
\[\mathcal{L}(\mu) = \frac{1}{\sqrt{(2\pi)^N \det\Sigma(\mu)}} \exp\!\left[-\frac{1}{2} \bigl(\boldsymbol{\lambda}(\mu) - \mathbf{n}^{\rm obs}\bigr)^\top \Sigma(\mu)^{-1} \bigl(\boldsymbol{\lambda}(\mu) - \mathbf{n}^{\rm obs}\bigr) \right],\]where \(\lambda_i(\mu) = \mu n^s_i + n^b_i\) and \(\Sigma(\mu)\) may be constant or \(\mu\)-dependent (see below).
Callable covariance matrix
covariance_matrixcan be a callable that takes the full parameter vectorparsand returns an \(N \times N\) covariance matrix. This allows, for example, signal-strength-dependent uncertainties:\[\Sigma(\mu) = \Sigma_{\rm bkg} + \mu^2\, \Sigma_{\rm sig}.\]Added in version 0.1.9.
Changed in version 0.2.6: Callable
covariance_matrixsupport added.covariance_matrixcan also take callable function as an input where function takes nuisance parameters as inputs and return a new covariance matrix as output.Example — callable covariance matrix:
>>> import spey >>> import numpy as np >>> signal_yields = np.array([12.0, 15.0]) >>> background_yields = np.array([50.0, 48.0]) >>> data = np.array([36., 33.]) >>> covariance_matrix = np.array([[144.0, 13.0], [25.0, 256.0]]) >>> covariance_signal = np.array([[5.0, 1.0], [2.0, 3.0]]) >>> # ``pars`` include all the parameters of the model, >>> # including the POI and any extra signal parameters >>> def cov_matrix(pars: np.ndarray) -> np.ndarray: >>> return covariance_matrix + covariance_signal * pars[0]**2 >>> pdf_wrapper = spey.get_backend('default.multivariate_normal') >>> model = pdf_wrapper( ... signal_yields=signal_yields, ... background_yields=background_yields, ... data=data, ... covariance_matrix=cov_matrix, ... )
Example — callable signal yields with additional parameters:
signal_yieldscan be a callable that accepts extra parameters beyond \(\mu\) and returns the per-bin signal yields as anp.ndarray. The number of extra parameters must be declared vian_signal_parametersso that the optimiser can construct the correct parameter vector. The first element of the parameter vector is always \(\mu\); the remaining elements (pars[1:]) are forwarded to the callable at each function evaluation.>>> import spey >>> import numpy as np >>> background_yields = np.array([50.0, 48.0]) >>> data = np.array([36., 33.]) >>> covariance_matrix = np.array([[144.0, 13.0], [25.0, 256.0]]) >>> base_signal = np.array([12.0, 15.0]) >>> # signal_yields is a function of one extra parameter (signal_par_0) >>> def signal_yields(extra_pars: np.ndarray) -> np.ndarray: ... return base_signal * (1.0 + extra_pars[0]) >>> pdf_wrapper = spey.get_backend('default.multivariate_normal') >>> model = pdf_wrapper( ... signal_yields=signal_yields, ... background_yields=background_yields, ... data=data, ... covariance_matrix=covariance_matrix, ... n_signal_parameters=1, ... ) >>> muhat, nll = model.maximize_likelihood()
The resulting
ModelConfigwill contain two parameters:["mu", "signal_par_0"].Attention
The functional
signal_yieldsis used to compute the expected signal yields in each bin. The optimiser only passes relevant parameter set tosignal_yieldsfunction, excluding signal strength (i.e. the first parameter \(\mu\)). Callablecovariance_matrixreceives the full parameter vector, including the POI and any extra signal parameters.Changed in version 0.2.6: The ability to input a callable covariance matrix has been added.
Changed in version 0.2.7:
signal_yieldsnow accepts a callable with signature(extra_pars: np.ndarray) -> np.ndarrayin addition to a plain array. The companion argumentn_signal_parameters(default0) declares how many extra parameters the callable expects; they are appended to the parameter vector after \(\mu\) and their names are automatically set tosignal_par_0,signal_par_1, …- Parameters:
signal_yields (
List[float] | Callable[[np.ndarray], np.ndarray]) – signal yields per bin, or a callable that takes the extra signal parameters (pars[1:]) and returns the signal yields as anp.ndarray.background_yields (
List[float]) – background yields per bin.data (
List[int]) – observed data per bin.covariance_matrix (
List[List[float]] | callable) –covariance matrix (square matrix), or a callable that takes the full parameter vector and returns a covariance matrix.
If you have a correlation matrix and absolute uncertainties please use
correlation_to_covariance()
n_signal_parameters (
int, default0) – number of additional free parameters to pass to a callablesignal_yields. Has no effect whensignal_yieldsis a plain array. When greater than zero the optimiser parameter vector is extended to[mu, signal_par_0, ..., signal_par_{n-1}].signal_parameter_bounds (
List[Tuple[Optional[float], Optional[float]]] | None) – Optimiser bounds for each extra signal parameter. Each entry is a(lower, upper)pair; useNonefor an unbounded side. WhenNone, every extra signal parameter receives(None, None). Must have exactlyn_signal_parametersentries when provided.
- __init__(signal_yields: List[float] | Callable[[ndarray], ndarray], background_yields: List[float], data: List[int], covariance_matrix: List[List[float]] | callable, n_signal_parameters: int = 0, signal_parameter_bounds: List[Tuple[float | None, float | None]] | None = None)[source]#
Methods
__init__(signal_yields, background_yields, ...)asimov_negative_loglikelihood([poi_test, ...])Compute the profiled negative log-likelihood at fixed \(\mu\) on Asimov data.
combine(other, **kwargs)Combine this statistical model with another backend instance.
config([allow_negative_signal, poi_upper_bound])Model configuration.
expected_data(pars, **kwargs)Compute the expected data vector \(\{\lambda_i(\mu)\}\) at the given parameter point.
get_hessian_logpdf_func([expected, data])Return a callable that evaluates the Hessian of \(\ln\mathcal{L}(\mu)\).
get_logpdf_func([expected, data])Return a callable that evaluates \(\ln\mathcal{L}(\mu)\).
get_objective_function([expected, data, do_grad])Return the objective function \(-\ln\mathcal{L}(\mu)\) used by the optimiser.
get_sampler(pars)Return a callable that draws pseudo-data from the main model.
minimize_asimov_negative_loglikelihood([...])Find the global minimum of the negative log-likelihood on Asimov data (free fit).
minimize_negative_loglikelihood([expected, ...])Find the global minimum of the negative log-likelihood (free fit).
negative_loglikelihood([poi_test, expected])Compute the profiled negative log-likelihood at a fixed \(\mu\).
Attributes
covariance_matrixn_signal_parametersNumber of signal parameters
authorAuthor of the backend
background_yieldsdatais_aliveReturns True if at least one bin has non-zero signal yield.
main_modelMain model distribution — Poisson (or Gaussian) term of the likelihood.
nameName of the backend
signal_yieldsspey_requiresSpey version required for the backend
versionVersion of the backend
constraintsConstraints to be used during optimisation process