Esempio n. 1
0
    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)
Esempio n. 2
0
    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)
Esempio n. 3
0
    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)
Esempio n. 4
0
    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