def _hamiltonian_step(self, start, p0, step_size): n_steps = max(1, int(self.path_length / step_size)) n_steps = min(self.max_steps, n_steps) energy_change = -np.inf state = start last = state div_info = None try: for _ in range(n_steps): last = state state = self.integrator.step(step_size, state) except IntegrationError as e: div_info = DivergenceInfo("Integration failed.", e, last, None) else: if not np.isfinite(state.energy): div_info = DivergenceInfo( "Divergence encountered, bad energy.", None, last, state) energy_change = start.energy - state.energy if np.isnan(energy_change): energy_change = -np.inf if np.abs(energy_change) > self.Emax: div_info = DivergenceInfo( "Divergence encountered, large integration error.", None, last, state) accept_stat = min(1, np.exp(energy_change)) if div_info is not None or np.random.rand() >= accept_stat: end = start accepted = False else: end = state accepted = True stats = { "path_length": self.path_length, "n_steps": n_steps, "accept": accept_stat, "energy_error": energy_change, "energy": state.energy, "accepted": accepted, "model_logp": state.model_logp, } return HMCStepData(end, accept_stat, div_info, stats)
def _hamiltonian_step(self, start, p0, step_size): n_steps = max(1, int(self.path_length / step_size)) n_steps = min(self.max_steps, n_steps) energy_change = -np.inf state = start div_info = None try: for _ in range(n_steps): state = self.integrator.step(step_size, state) except IntegrationError as e: div_info = DivergenceInfo('Divergence encountered.', e, state) else: if not np.isfinite(state.energy): div_info = DivergenceInfo( 'Divergence encountered, bad energy.', None, state) energy_change = start.energy - state.energy if np.isnan(energy_change): energy_change = -np.inf if np.abs(energy_change) > self.Emax: div_info = DivergenceInfo( 'Divergence encountered, large integration error.', None, state) accept_stat = min(1, np.exp(energy_change)) if div_info is not None or np.random.rand() >= accept_stat: end = start accepted = False else: end = state accepted = True stats = { 'path_length': self.path_length, 'n_steps': n_steps, 'accept': accept_stat, 'energy_error': energy_change, 'energy': state.energy, 'accepted': accepted, 'model_logp': state.model_logp, } return HMCStepData(end, accept_stat, div_info, stats)
def _hamiltonian_step(self, start, p0, step_size): path_length = np.random.rand() * self.path_length n_steps = max(1, int(path_length / step_size)) energy_change = -np.inf state = start div_info = None try: for _ in range(n_steps): state = self.integrator.step(step_size, state) except IntegrationError as e: div_info = DivergenceInfo('Divergence encountered.', e, state) else: if not np.isfinite(state.energy): div_info = DivergenceInfo('Divergence encountered, bad energy.', None, state) energy_change = start.energy - state.energy if np.abs(energy_change) > self.Emax: div_info = DivergenceInfo('Divergence encountered, large integration error.', None, state) accept_stat = min(1, np.exp(energy_change + state.log_jac)) if div_info is not None or np.random.rand() >= accept_stat: end = start accepted = False else: end = state accepted = True stats = { 'path_length': path_length, 'n_steps': n_steps, 'accept': accept_stat, 'energy_error': energy_change, 'energy': state.energy, 'accepted': accepted, # 'log_jacobian': state.log_jac, # TODO: backends/ndarray.py to allow this } return HMCStepData(end, accept_stat, div_info, stats)
def _single_step(self, left, epsilon): """Perform a leapfrog step and handle error cases.""" try: # `State` type right = self.integrator.step(epsilon, left) except IntegrationError as err: error_msg = str(err) error = err right = None else: # h - H0 energy_change = right.energy - self.start_energy if np.isnan(energy_change): energy_change = np.inf if np.abs(energy_change) > np.abs(self.max_energy_change): self.max_energy_change = energy_change if np.abs(energy_change) < self.Emax: # Acceptance statistic # e^{H(q_0, p_0) - H(q_n, p_n)} max(1, e^{H(q_0, p_0) - H(q_n, p_n)}) # Saturated Metropolis accept probability with Boltzmann weight # if h - H0 < 0 log_p_accept_weighted = -energy_change + min( 0.0, -energy_change) log_size = -energy_change proposal = Proposal( right.q.data, right.q_grad.data, right.energy, log_p_accept_weighted, right.model_logp, ) tree = Subtree(right, right, right.p.data, proposal, log_size, log_p_accept_weighted, 1) return tree, None, False else: error_msg = "Energy change in leapfrog step is too large: %s." % energy_change error = None tree = Subtree(None, None, None, None, -np.inf, -np.inf, 1) divergance_info = DivergenceInfo(error_msg, error, left, right) return tree, divergance_info, False