Source code for binf.samplers.gibbs

"""
Gibbs sampler implementations
"""

import numpy

from csb.statistics.samplers import State
from csb.statistics.samplers.mc.singlechain import AbstractSingleChainMC


[docs]class GibbsSampler(AbstractSingleChainMC): def __init__(self, pdf, state, subsamplers): """ Implements a Gibbs sampler :param pdf: PDF object representing the pdf this sampler is supposed to sample from :type pdf: :class:`.AbstractBinfPDF` :param state: initial state :type state: :class:`.BinfState` :param subsamplers: subsamplers for each variable of the PDF object :type subsamplers: dict """ self._state = None self._pdf = None self._subsamplers = {} self._conditional_pdfs = {} self._state = state self._pdf = pdf self._subsamplers = subsamplers self._setup_conditional_pdfs() self._update_subsampler_states()
[docs] def _setup_conditional_pdfs(self): """ Sets up the conditional PDFs from the full PDF """ for var in self.state.variables.keys(): fixed_vars = {x: self.state.variables[x] for x in self.state.variables if not x == var} fixed_vars.update(**{x: self._pdf[x].value for x in self._pdf.parameters if x in self._pdf._original_variables}) cond_pdf = self._pdf.conditional_factory(**fixed_vars) self._conditional_pdfs.update({var: cond_pdf}) self.subsamplers[var].pdf = self._conditional_pdfs[var]
[docs] def _update_conditional_pdf_params(self): """ Updates parameters of the conditional PDFs to values set in this object's PDF """ for pdf in self._conditional_pdfs.values(): for param in pdf.parameters: if param in self._state.variables.keys(): pdf[param].set(self._state.variables[param])
[docs] def _checkstate(self, state): """ Checks whether the state is a dict """ if not type(state) == dict: raise TypeError(state)
@property def pdf(self): """ Returns the PDF object this sampler samples from :returns: PDF object :rtype: :class:`.AbstractBinfPDF` """ return self._pdf @pdf.setter def pdf(self, value): """ Sets the PDF this sampler samples from and refreshes the conditional PDFs """ self._pdf = value self._setup_conditional_pdfs() @property def state(self): """ Returns the current state of this sampler :returns: current state :rtype: :class:`.BinfState` """ return self._state @property def subsamplers(self): """ Returns the subsamplers the Gibbs sampler iterates over :returns: subsamplers for each variable :rtype: dict """ return self._subsamplers
[docs] def update_samplers(self, **samplers): """ Updates the subsamplers """ self._subsamplers.update(**samplers)
[docs] def _update_subsampler_states(self): """ Updates subsampler states, e.g., after a replica exchange swap """ from csb.statistics.samplers.mc import AbstractMC for variable in self.state.variables: if isinstance(self.subsamplers[variable], AbstractMC): self.subsamplers[variable].state = State(self.state.variables[variable]) else: self.subsamplers[variable].state = self.state.variables[variable]
[docs] def _update_state(self, **variables): """ Updates this object's state's variables to new values """ for variable, new_value in variables.items(): if type(new_value) == State: new_value = new_value.position self._state.update_variables(**{variable: new_value})
[docs] def sample(self): """ Performs one iteration of the Gibbs sampling scheme :returns: a state :rtype: :class:`.BinfState` """ ## needed for RE self._update_subsampler_states() for var in sorted(list(self._pdf.variables)): self._update_conditional_pdf_params() new = self.subsamplers[var].sample() self._update_state(**{var: new}) return self._state
[docs] def _calc_pacc(): """ Not applicable """ pass
[docs] def _propose(): """ Not applicable """ pass
@property def last_draw_stats(self): """ Returns information about most recent move for each subsampler :returns: information about most recent move for each subsampler :rtype: dict """ return {k: v.last_draw_stats[k] for k, v in self.subsamplers.items() if getattr(v, 'last_draw_stats', None) is not None} @property def sampling_stats(self): """ Sampling statistics, consisting of sampler statistics of the subsamplers :returns: all subsampler sampling statistics :rtype: OrderedDict """ from collections import OrderedDict ss = [s for s in self.subsamplers.values() if 'sampling_stats' in dir(s)] return OrderedDict(**{key: value for sampler in ss for key, value in sampler.sampling_stats.items()})