Source code for aspire.samplers.smc.emcee

import copy
import logging

import numpy as np

from ...samples import SMCSamples
from ...utils import track_calls
from .base import NumpySMCSampler

[docs] logger = logging.getLogger(__name__)
[docs] class EmceeSMC(NumpySMCSampler): @track_calls
[docs] def sample( self, n_samples: int, n_steps: int = None, adaptive: bool = True, target_efficiency: float = 0.5, target_efficiency_rate: float = 1.0, sampler_kwargs: dict | None = None, n_final_samples: int | None = None, checkpoint_callback=None, checkpoint_every: int | None = None, checkpoint_file_path: str | None = None, resume_from: str | bytes | dict | None = None, ): self.sampler_kwargs = sampler_kwargs or {} self.sampler_kwargs.setdefault("nsteps", 5 * self.dims) self.sampler_kwargs.setdefault("progress", True) self.emcee_moves = self.sampler_kwargs.pop("moves", None) return super().sample( n_samples, n_steps=n_steps, adaptive=adaptive, target_efficiency=target_efficiency, target_efficiency_rate=target_efficiency_rate, n_final_samples=n_final_samples, checkpoint_callback=checkpoint_callback, checkpoint_every=checkpoint_every, checkpoint_file_path=checkpoint_file_path, resume_from=resume_from, )
[docs] def mutate(self, particles, beta, n_steps=None): import emcee logger.info("Mutating particles") sampler = emcee.EnsembleSampler( len(particles.x), self.dims, self.log_prob, args=(beta,), vectorize=True, moves=self.emcee_moves, ) z = self.fit_preconditioning_transform(particles.x) kwargs = copy.deepcopy(self.sampler_kwargs) if n_steps is not None: kwargs["nsteps"] = n_steps sampler.run_mcmc(z, **kwargs) self.history.mcmc_acceptance.append( np.mean(sampler.acceptance_fraction) ) self.history.mcmc_autocorr.append( sampler.get_autocorr_time( quiet=True, discard=int(0.2 * self.sampler_kwargs["nsteps"]) ) ) z = sampler.get_chain(flat=False)[-1, ...] x = self.preconditioning_transform.inverse(z)[0] samples = SMCSamples( x, xp=self.xp, beta=beta, dtype=self.dtype, parameters=self.parameters, ) samples.log_q = samples.array_to_namespace( self.prior_flow.log_prob(samples.x) ) samples.log_prior = samples.array_to_namespace(self.log_prior(samples)) samples.log_likelihood = samples.array_to_namespace( self.log_likelihood(samples) ) if samples.xp.isnan(samples.log_q).any(): raise ValueError("Log proposal contains NaN values") return samples