Source code for infpy.convergence_test

#
# Copyright John Reid 2008
#

"""
Code to implement convergence tests (primarily for sequences of log likelihoods).
"""

import logging

[docs]def check_LL_increased(last_LL, LL, tag="", tolerance=.01, raise_error=True): """ Takes 2 numpy arrays of components of a log likelihood. Assumes the total LL is the sum of each array. Compares the 2 LLs and if the new one is smaller than the first by at least tolerance, raises an error. """ LL_sum, last_LL_sum = LL.sum(), last_LL.sum() abs_change = LL_sum - last_LL_sum if abs_change < -tolerance: msg = '%s: LL has decreased %f from %f to %f:\nFrom:%s\nTo: %s\nDiff:%s' % ( tag, LL_sum - last_LL_sum, last_LL_sum, LL_sum, last_LL, LL, LL-last_LL ) logging.warning(msg) if raise_error: raise ValueError(msg) return LL
[docs]class LlConvergenceTest(object): """Tests for convergence of a series of log likelihoods.""" def __init__(self, eps=1e-8, should_increase=True, use_absolute_difference=False): """ @arg eps: The tolerance for the convergence test. @arg should_increase: If true a warning is printed if the log likelihoods don't always increase. @arg use_absolute_difference: If true the absolute differences is used for the convergence test, otherwise any decrease is viewed as convergence. """ self.LLs = list() "The log likelihoods." self.should_increase = should_increase "If true a warning is printed if the log likelihoods don't always increase." self.eps = eps "If true a warning is printed if the log likelihoods don't always increase." self.use_absolute_difference = use_absolute_difference "If true the absolute differences is used for the convergence test, otherwise any decrease is viewed as convergence." def __call__(self, LL): "@return: True iff converged." self.LLs.append(LL) if len(self.LLs) < 2: return False else: if self.should_increase: if self.LLs[-1] < self.LLs[-2]: logging.warning( 'Iteration %4d: Log likelihoods are not increasing as expected: %f < %f' % (len(self.LLs), self.LLs[-1], self.LLs[-2]) ) #raise RuntimeError('Log likelihoods are not increasing as expected: %f < %f' % (self.LLs[-1], self.LLs[-2])) diff = self.LLs[-1] - self.LLs[-2] if self.use_absolute_difference: diff = abs(diff) return diff < self.eps