def fitfunc(self, fitfunc): self._fitfunc = fitfunc self._fitfunc_has_xerr = False if 'x_err' in getargspec(fitfunc).args: self._fitfunc_has_xerr = True
def sample(self, steps, nthin=1, random_state=None, f=None, callback=None, verbose=True, pool=0): """ Performs sampling from the objective. Parameters ---------- steps : int Collect `steps` samples into the chain. The sampler will run a total of `steps * nthin` moves. nthin : int, optional Each chain sample is separated by `nthin` iterations. random_state : int or `np.random.RandomState`, optional If `random_state` is an int, a new `np.random.RandomState` instance is used, seeded with `random_state`. If `random_state` is already a `np.random.RandomState` instance, then that `np.random.RandomState` instance is used. Specify `random_state` for repeatable sampling f : file-like or str File to incrementally save chain progress to. Each row in the file is a flattened array of size `(nwalkers, ndim)` or `(ntemps, nwalkers, ndim)`. There are `steps` rows in the file. callback : callable callback function to be called at each iteration step verbose : bool, optional Gives updates on the sampling progress pool : int or map-like object, optional If `pool` is an `int` then it specifies the number of threads to use for parallelization. If `pool == 0`, then all CPU's are used. If pool is an object with a map method that follows the same calling sequence as the built-in map function, then this pool is used for parallelisation. Notes ----- Please see :class:`emcee.EnsembleSampler` for its detailed behaviour. >>> # we'll burn the first 500 steps >>> fitter.sample(500) >>> # after you've run those, then discard them by resetting the >>> # sampler. >>> fitter.sampler.reset() >>> # Now collect 40 steps, each step separated by 50 sampler >>> # generations. >>> fitter.sample(40, nthin=50) One can also burn and thin in `Curvefitter.process_chain`. """ self._check_vars_unchanged() if self._state is None: self.initialise() self.__pt_iterations = 0 if isinstance(self.sampler, PTSampler): steps *= nthin # for saving progress to file def _callback_wrapper(state, h=None): if callback is not None: callback(state.coords, state.log_prob) if h is not None: # if you're parallel tempering, then you only # want to save every nthin if isinstance(self.sampler, PTSampler): self.__pt_iterations += 1 if self.__pt_iterations % nthin: return None h.write(' '.join(map(str, state.coords.ravel()))) h.write('\n') # set the random state of the sampler # normally one could give this as an argument to the sample method # but PTSampler didn't historically accept that... if random_state is not None: rstate0 = check_random_state(random_state).get_state() self._state.random_state = rstate0 if isinstance(self.sampler, PTSampler): self.sampler._random = rstate0 # remove chains from each of the parameters because they slow down # pickling but only if they are parameter objects. flat_params = f_unique(flatten(self.objective.parameters)) flat_params = [param for param in flat_params if is_parameter(param)] # zero out all the old parameter stderrs for param in flat_params: param.stderr = None param.chain = None # make sure the checkpoint file exists if f is not None: with possibly_open_file(f, 'w') as h: # write the shape of each step of the chain h.write('# ') shape = self._state.coords.shape h.write(', '.join(map(str, shape))) h.write('\n') # using context manager means we kill off zombie pool objects # but does mean that the pool has to be specified each time. with possibly_create_pool(pool) as g, possibly_open_file(f, 'a') as h: # if you're not creating more than 1 thread, then don't bother with # a pool. if pool == 1: self.sampler.pool = None else: self.sampler.pool = g # these kwargs are provided to the sampler.sample method kwargs = {'iterations': steps, 'thin': nthin} # new emcee arguments sampler_args = getargspec(self.sampler.sample).args if 'progress' in sampler_args and verbose: kwargs['progress'] = True verbose = False if 'thin_by' in sampler_args: kwargs['thin_by'] = nthin kwargs.pop('thin', 0) # ptemcee returns coords, lnprob # emcee returns a State object if isinstance(self.sampler, PTSampler): for result in self.sampler.sample(self._state.coords, **kwargs): self._state = State(result[0], log_prob=result[1] + result[2], random_state=self.sampler._random) _callback_wrapper(self._state, h=h) else: for state in self.sampler.sample(self._state, **kwargs): self._state = state _callback_wrapper(state, h=h) self.sampler.pool = None # finish off the progress bar if verbose: sys.stdout.write("\n") # sets parameter value and stderr return process_chain(self.objective, self.chain)
def sample( self, steps, nthin=1, random_state=None, f=None, callback=None, verbose=True, pool=-1, ): """ Performs sampling from the objective. Parameters ---------- steps : int Collect `steps` samples into the chain. The sampler will run a total of `steps * nthin` moves. nthin : int, optional Each chain sample is separated by `nthin` iterations. random_state : {int, `np.random.RandomState`, `np.random.Generator`} If `random_state` is not specified the `~np.random.RandomState` singleton is used. If `random_state` is an int, a new ``RandomState`` instance is used, seeded with random_state. If `random_state` is already a ``RandomState`` or a ``Generator`` instance, then that object is used. Specify `random_state` for repeatable minimizations. f : file-like or str File to incrementally save chain progress to. Each row in the file is a flattened array of size `(nwalkers, ndim)` or `(ntemps, nwalkers, ndim)`. There are `steps` rows in the file. callback : callable callback function to be called at each iteration step. Has the signature `callback(coords, logprob)`. verbose : bool, optional Gives updates on the sampling progress pool : int or map-like object, optional If `pool` is an `int` then it specifies the number of threads to use for parallelization. If `pool == -1`, then all CPU's are used. If pool is a map-like callable that follows the same calling sequence as the built-in map function, then this pool is used for parallelisation. Notes ----- Please see :class:`emcee.EnsembleSampler` for its detailed behaviour. >>> # we'll burn the first 500 steps >>> fitter.sample(500) >>> # after you've run those, then discard them by resetting the >>> # sampler. >>> fitter.sampler.reset() >>> # Now collect 40 steps, each step separated by 50 sampler >>> # generations. >>> fitter.sample(40, nthin=50) One can also burn and thin in `Curvefitter.process_chain`. """ self._check_vars_unchanged() # setup a random number generator rng = check_random_state(random_state) if self._state is None: self.initialise(random_state=rng) # for saving progress to file def _callback_wrapper(state, h=None): if callback is not None: callback(state.coords, state.log_prob) if h is not None: h.write(" ".join(map(str, state.coords.ravel()))) h.write("\n") # remove chains from each of the parameters because they slow down # pickling but only if they are parameter objects. flat_params = f_unique(flatten(self.objective.parameters)) flat_params = [param for param in flat_params if is_parameter(param)] # zero out all the old parameter stderrs for param in flat_params: param.stderr = None param.chain = None # make sure the checkpoint file exists if f is not None: with possibly_open_file(f, "w") as h: # write the shape of each step of the chain h.write("# ") shape = self._state.coords.shape h.write(", ".join(map(str, shape))) h.write("\n") # set the random state of the sampler # normally one could give this as an argument to the sample method # but PTSampler didn't historically accept that... if isinstance(rng, np.random.RandomState): rstate0 = rng.get_state() self._state.random_state = rstate0 self.sampler.random_state = rstate0 # using context manager means we kill off zombie pool objects # but does mean that the pool has to be specified each time. with MapWrapper(pool) as g, possibly_open_file(f, "a") as h: # these kwargs are provided to the sampler.sample method kwargs = {"iterations": steps, "thin": nthin} # if you're not creating more than 1 thread, then don't bother with # a pool. if isinstance(self.sampler, emcee.EnsembleSampler): if pool == 1: self.sampler.pool = None else: self.sampler.pool = g else: kwargs["mapper"] = g # new emcee arguments sampler_args = getargspec(self.sampler.sample).args if "progress" in sampler_args and verbose: kwargs["progress"] = True verbose = False if "thin_by" in sampler_args: kwargs["thin_by"] = nthin kwargs.pop("thin", 0) # perform the sampling for state in self.sampler.sample(self._state, **kwargs): self._state = state _callback_wrapper(state, h=h) if isinstance(self.sampler, emcee.EnsembleSampler): self.sampler.pool = None # sets parameter value and stderr return process_chain(self.objective, self.chain)
def fitfunc(self, fitfunc): self._fitfunc = fitfunc self._fitfunc_has_xerr = False if fitfunc is not None and "x_err" in getargspec(fitfunc).args: self._fitfunc_has_xerr = True