Source code for trendpy.mcmc

# -*- coding: utf-8 -*-

# mcmc.py

# MIT License

# Copyright (c) 2017 Rene Jean Corneille

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

from __future__ import absolute_import

from numpy import reshape, zeros

[docs]class MCMC(object): def __init__(self, sampler): self.sampler = sampler self.simulations = None
[docs] def define_parameters(self): """ Method to set the parameter set to be updated in the MCMC algorithm. """ return self.sampler.define_parameters()
[docs] def initial_value(self,parameter_name): """ Method that sets the initial value of the parameters to be estimated. :param parameter_name: name of the parameter. :type parameter_name: str :return: initial value of the parameter :rtype: `Numpy.dnarray` """ return self.sampler.initial_value(parameter_name)
[docs] def distribution_parameters(self, parameter_name): """ Method that sets the parameters of the posterior distribution of the parameters to be estimated. :param parameter_name: name of the parameter. :type parameter_name: str :return: dictionary the parameters needed to compute the next value of the Markov chain for the parameter with name: parameter_name. :rtype: dict """ return self.sampler.distribution_parameters(parameter_name) # returns a dictionary
[docs] def generate(self, parameter_name): """ This method handles the generation of the random draws of the Markov chain for each parameters. :param parameter_name: name of the parameter of interest :type parameter_name: string :return: random draw from the posterior probability distribution :rtype: `Numpy.dnarray` """ return self.sampler.generate(parameter_name)
[docs] def output(self, burn, parameter_name): """ Computes the poserior mean of the parameters. :param parameter_name: name of the parameter of interest :type parameter_name: string :param burn: number of draws dismissed as burning samples :type burn: int :return: output of the MCMC algorithm :rtype: `Numpy.dnarray` """ return self.sampler.output(self.simulations, burn, parameter_name)
[docs] def run(self, number_simulations, max_restart, verbose): """ Runs the MCMC algorithm. :param number_simulations: number of random draws for each parameter. :type number_simulations: int :param max_restart: number of times the MCMC routine is allowed to restart. :type max_restart: int :param verbose: control console log information detail. :type verbose: int """ self.simulations = {key : zeros((param.size[0],param.size[1],number_simulations)) for (key, param) in self.sampler.parameters.list.items()} for name in self.sampler.parameters.hierarchy: self.sampler.parameters.list[name].current_value = self.initial_value(name) for i in range(number_simulations): if verbose > 0: print("== step %i ==" % (int(i+1),)) restart = 0 restart_step = True while restart_step: for name in self.sampler.parameters.hierarchy: if verbose > 3: print("== parameter %s ==" % name) try: self.sampler.parameters.list[name].current_value = self.generate(name) self.simulations[name][:,:,i] = self.sampler.parameters.list[name].current_value.reshape(self.sampler.parameters.list[name].size) restart_step = False restart = 0 except: if restart < max_restart: restart+=1 if verbose > 4: print("== restart step %i ==" % i) restart_step = True break else: raise ValueError("Convergence error")