Source code for binf.pdf.likelihoods

"""
This module contains interfaces for likelihood functions
"""

import numpy

from csb.numeric import exp

from binf.pdf import AbstractBinfPDF


[docs]class Likelihood(AbstractBinfPDF): def __init__(self, name, forward_model, error_model): """ A likelihood function (not exactly a PDF...) which is composed of a forward model to back-calculate idealized data from model parameters and an error model modeling deviations of the data from the idealized data :param name: some name for this object :type name: str :param forward_model: forward model to back-calculate data from :type forward_model: :class:`.AbstractForwardModel` :param error_model: error model to model deviations of the data from the back-calculated data :type error_model: :class:`.AbstractErrorModel` """ super(Likelihood, self).__init__(name) self._forward_model = forward_model self._error_model = error_model self._inherit_variables() self._setup_parameters() self._set_original_variables()
[docs] def _inherit_fwm_variables(self): """ Retrieves variables from forward model and adds them to this objects's own set of variables """ fwm = self._forward_model for v in fwm._original_variables: if v in fwm.parameters: self._original_variables.update({v}) else: self._register_variable(v, differentiable=v in fwm.differentiable_variables) self.update_var_param_types(**{v: fwm.var_param_types[v]})
[docs] def _inherit_em_variables(self): """ Retrieves variables from error model and adds them to this objects's own set of variables """ em = self._error_model for v in em._original_variables: if not v == 'mock_data': if v in em.parameters: self._original_variables.update({v}) else: self._register_variable(v, differentiable=v in em.differentiable_variables) self.update_var_param_types(**{v: em.var_param_types[v]})
[docs] def _inherit_variables(self): """ Retrieves variables from forward and error model and adds them to this objects's own set of variables """ self._inherit_fwm_variables() self._inherit_em_variables()
[docs] def _setup_parameters(self): """ Sets up parameters matching the parameters in the forward and error model and binds the latter to the newly created ones """ for component in (self._forward_model, self._error_model): for p in component.get_params(): self._register(p.name) self[p.name] = p.__class__(p.value, p.name, self[p.name]) p.bind_to(self[p.name])
[docs] def _setup_fixed_variable_parameters(self): """ Sets up fixed variables as parameters, matching the fixed variables in the forward and error model and binds the latter to the newly created ones """ for model in (self._forward_model, self._error_model): for p in model.get_params(): var_param_type = model.var_param_types[p.name] model[p.name] = var_param_type(self[p.name].value, p.name) model[p.name].bind_to(self[p.name])
@property def forward_model(self): """ Returns the forward model :returns: the forward model of this likelihood object :rtype: :class:`.AbstractForwardModel` """ return self._forward_model @property def error_model(self): """ Returns the error model :returns: the error model of this likelihood object :rtype: :class:`.AbstractErrorModel` """ return self._error_model
[docs] def _split_variables(self, variables): """ Splits up variables into variables of the forward and of the error model :param variables: key / value pairs of variables :type variables: dict :returns: separate kev / value pairs for forward and error model variables :rtype: (dict, dict) """ fwm_variables = {v: variables[v] for v in variables if v in self.forward_model.variables} em_variables = {v: variables[v] for v in variables if v in self.error_model.variables} return fwm_variables, em_variables
[docs] def _evaluate_log_prob(self, **variables): fwm_variables, em_variables = self._split_variables(variables) mock_data = self.forward_model(**fwm_variables) return self.error_model.log_prob(mock_data=mock_data, **em_variables)
[docs] def _evaluate_gradient(self, **variables): fwm_variables, em_variables = self._split_variables(variables) mock_data = self.forward_model(**fwm_variables) dfm = self.forward_model.jacobi_matrix(**fwm_variables) emgrad = self.error_model.gradient(mock_data=mock_data, **em_variables) return dfm.dot(emgrad)
[docs] def clone(self): copy = self.__class__(self.name, self.forward_model.clone(), self.error_model.clone()) return copy
[docs] def conditional_factory(self, **fixed_vars): fwm = self.forward_model.clone() fwm.fix_variables(**fwm._get_variables_intersection(fixed_vars)) old_em = self.error_model variables_intersection = old_em._get_variables_intersection(fixed_vars) em = old_em.conditional_factory(**variables_intersection) result = self.__class__(self.name, fwm, em) return result