def slice(initial_theta, step, lnpdf, pdf_params, create_method='step_out', isDomainFinite=[False, False], domain=[0., 0.], nsamples=1, randomize_directions=True, callback=None): """ NAME: slice PURPOSE: simple slice sampling function (e.g., Neal 2003,Mackay 2003) INPUT: initial_theta - initial sample step - stepping out step w lnpdf - function evaluating the log of the pdf to be sampled pdf_params - parameters to pass to the pdf create_method - 'step_out', 'double', or 'whole' (whole only works if the domain is finite; defaults to 'double') nsamples - number of samples desired randomize_directions - (bool) pick a random coordinate to update isDomainFinite - is the domain finite? [bool,bool] domain - the domain if it is finite (has no effect if the domain is not finite) callback - function of current parameters to call after each new sample OUTPUT: list of samples, number if nsamples=1 REVISION HISTORY: 2009-10-29 - Written - Bovy (NYU) """ try: ndim = len(initial_theta) except TypeError: ndim = 1 if ndim == 1: #1D return bovy_mcmc_oned.slice(initial_theta, step, lnpdf, pdf_params, create_method=create_method, isDomainFinite=isDomainFinite, domain=domain, nsamples=nsamples, callback=callback) else: #multi-D return bovy_mcmc_multid.slice(initial_theta,step,lnpdf,pdf_params, create_method=create_method, isDomainFinite=isDomainFinite, domain=domain, nsamples=nsamples, randomize_directions=\ randomize_directions, callback=callback)
def slice(initial_theta,step,lnpdf,pdf_params,create_method='step_out', isDomainFinite=[False,False],domain=[0.,0.], nsamples=1,randomize_directions=True,callback=None): """ NAME: slice PURPOSE: simple slice sampling function (e.g., Neal 2003,Mackay 2003) INPUT: initial_theta - initial sample step - stepping out step w lnpdf - function evaluating the log of the pdf to be sampled pdf_params - parameters to pass to the pdf create_method - 'step_out', 'double', or 'whole' (whole only works if the domain is finite; defaults to 'double') nsamples - number of samples desired randomize_directions - (bool) pick a random coordinate to update isDomainFinite - is the domain finite? [bool,bool] domain - the domain if it is finite (has no effect if the domain is not finite) callback - function of current parameters to call after each new sample OUTPUT: list of samples, number if nsamples=1 REVISION HISTORY: 2009-10-29 - Written - Bovy (NYU) """ try: ndim = len(initial_theta) except TypeError: ndim= 1 if ndim == 1: #1D return bovy_mcmc_oned.slice(initial_theta,step,lnpdf,pdf_params, create_method=create_method, isDomainFinite=isDomainFinite, domain=domain, nsamples=nsamples, callback=callback) else: #multi-D return bovy_mcmc_multid.slice(initial_theta,step,lnpdf,pdf_params, create_method=create_method, isDomainFinite=isDomainFinite, domain=domain, nsamples=nsamples, randomize_directions=\ randomize_directions, callback=callback)
def slice(initial_theta,step,lnpdf,pdf_params,create_method='step_out',randomize_directions=True,isDomainFinite=[False,False],domain=[0.,0.], nsamples=1,callback=None): """ NAME: slice PURPOSE: simple slice sampling function (e.g., Neal 2003,Mackay 2003) performs random, coordinate aligned updates INPUT: initial_theta - ([k]) initial sample step - (1 or [k]) stepping out step w lnpdf - function evaluating the log of the pdf to be sampled, arguments are initial_theta + pdf_params pdf_params - parameters to pass to the pdf create_method - 'step_out', 'double', or whole (string or array of D strings) randomize_directions - (bool) pick a random coordinate to update isDomainFinite - is the domain finite? [[bool,bool],...] domain - the domain if it is finite (has no effect if the domain is not finite) [[0.,0.],...] nsamples - number of samples desired callback - function of parameter to call after new sample OUTPUT: list of samples, number if nsamples=1 REVISION HISTORY: 2009-10-30 - Written - Bovy (NYU) DOCTEST: >>> import numpy as nu >>> import scipy as sc >>> from scipy import linalg >>> nu.random.seed(1) >>> def lngaussian(x,params): ... return -sc.log(2.*sc.pi)+.5*sc.log(linalg.det(params[1]))-0.5*sc.dot(x-params[0],sc.dot(params[1],x-params[0])) >>> lnpdf= lngaussian >>> mean= nu.array([0.,0.]) >>> variance= nu.array([[1.,1],[1,4.]]) >>> invvar= linalg.inv(variance) >>> pdf_params= ([mean,invvar],) >>> isDomainFinite= [False,False] >>> domain= [0.,0.] >>> create_method= 'double' >>> nsamples= 10000 >>> samples= slice(nu.array([0.1,0.1]),1.,lnpdf,pdf_params,create_method, ... True,isDomainFinite,domain, ... nsamples=nsamples) >>> samples= nu.array(samples) >>> logprecision= -1.5 >>> assert (nu.mean(samples[:,0])-0.)**2. < 10.**(logprecision*2.) >>> assert (nu.mean(samples[:,1])-0.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(samples[:,0])-1.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(samples[:,1])-2.)**2. < 10.**(logprecision*2.) >>> from scipy import stats >>> assert (stats.moment(samples[:,0],3)-0.)**2. < 10.**(logprecision) >>> assert (stats.moment(samples[:,1],3)-0.)**2. < 10.**(logprecision) >>> assert (stats.moment(samples[:,0],4)-stats.norm.moment(4))**2. < 10.**(logprecision) >>> assert (stats.moment(samples[:,1]/2.,4)-stats.norm.moment(4))**2. < 10.**(logprecision) >>> assert (nu.corrcoef(samples.T)[0,1]-0.5)**2. < 10.**(logprecision) """ out= [] d= len(initial_theta) if not isinstance(isDomainFinite,sc.ndarray): isDomainFinite= sc.array(isDomainFinite) if not isinstance(domain,sc.ndarray): domain= sc.array(domain) if isinstance(step,list): step= sc.array(step) if isinstance(step,(int,float)) or len(step) == 1: step= sc.ones(d)*step if len(isDomainFinite.shape) == 1: dFinite= [] for ii in range(d): dFinite.append(isDomainFinite) isDomainFinite= dFinite if len(domain.shape) == 1: dDomain= [] for ii in range(d): dDomain.append(domain) domain= dDomain if not isinstance(create_method,list) or len(create_method) == 1: tmp_method= [] for ii in range(d): if isinstance(create_method,list): tmp_method.append(create_method[0]) else: tmp_method.append(create_method) create_method= tmp_method current_sample= initial_theta.copy() params= [] params.append(lnpdf) params.append(pdf_params) for ii in range(nsamples): if randomize_directions: permuterange= sc.random.permutation(d) else: permuterange= range(d) for dd in permuterange: thisparams= copy.copy(params) thisparams.append(dd) thisparams.append([current_sample[jj] for jj in range(d) if jj != dd])#list comprehensions are supposedly faster than numpy slicing new_up_sample= oned_mcmc.slice(current_sample[dd],step[dd],oned_lnpdf,(thisparams,),create_method[dd], isDomainFinite[dd],domain[dd],nsamples=1) current_sample= current_sample.copy() current_sample[dd]= new_up_sample if not callback is None: callback(current_sample) out.append(current_sample) if nsamples == 1: return out[0] else: return out
def slice(initial_theta, step, lnpdf, pdf_params, create_method='step_out', randomize_directions=True, isDomainFinite=[False, False], domain=[0., 0.], nsamples=1, callback=None): """ NAME: slice PURPOSE: simple slice sampling function (e.g., Neal 2003,Mackay 2003) performs random, coordinate aligned updates INPUT: initial_theta - ([k]) initial sample step - (1 or [k]) stepping out step w lnpdf - function evaluating the log of the pdf to be sampled, arguments are initial_theta + pdf_params pdf_params - parameters to pass to the pdf create_method - 'step_out', 'double', or whole (string or array of D strings) randomize_directions - (bool) pick a random coordinate to update isDomainFinite - is the domain finite? [[bool,bool],...] domain - the domain if it is finite (has no effect if the domain is not finite) [[0.,0.],...] nsamples - number of samples desired callback - function of parameter to call after new sample OUTPUT: list of samples, number if nsamples=1 REVISION HISTORY: 2009-10-30 - Written - Bovy (NYU) DOCTEST: >>> import numpy as nu >>> import scipy as sc >>> from scipy import linalg >>> nu.random.seed(1) >>> def lngaussian(x,params): ... return -sc.log(2.*sc.pi)+.5*sc.log(linalg.det(params[1]))-0.5*sc.dot(x-params[0],sc.dot(params[1],x-params[0])) >>> lnpdf= lngaussian >>> mean= nu.array([0.,0.]) >>> variance= nu.array([[1.,1],[1,4.]]) >>> invvar= linalg.inv(variance) >>> pdf_params= ([mean,invvar],) >>> isDomainFinite= [False,False] >>> domain= [0.,0.] >>> create_method= 'double' >>> nsamples= 10000 >>> samples= slice(nu.array([0.1,0.1]),1.,lnpdf,pdf_params,create_method, ... True,isDomainFinite,domain, ... nsamples=nsamples) >>> samples= nu.array(samples) >>> logprecision= -1.5 >>> assert (nu.mean(samples[:,0])-0.)**2. < 10.**(logprecision*2.) >>> assert (nu.mean(samples[:,1])-0.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(samples[:,0])-1.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(samples[:,1])-2.)**2. < 10.**(logprecision*2.) >>> from scipy import stats >>> assert (stats.moment(samples[:,0],3)-0.)**2. < 10.**(logprecision) >>> assert (stats.moment(samples[:,1],3)-0.)**2. < 10.**(logprecision) >>> assert (stats.moment(samples[:,0],4)-stats.norm.moment(4))**2. < 10.**(logprecision) >>> assert (stats.moment(samples[:,1]/2.,4)-stats.norm.moment(4))**2. < 10.**(logprecision) >>> assert (nu.corrcoef(samples.T)[0,1]-0.5)**2. < 10.**(logprecision) """ out = [] d = len(initial_theta) if not isinstance(isDomainFinite, sc.ndarray): isDomainFinite = sc.array(isDomainFinite) if not isinstance(domain, sc.ndarray): domain = sc.array(domain) if isinstance(step, list): step = sc.array(step) if isinstance(step, (int, float)) or len(step) == 1: step = sc.ones(d) * step if len(isDomainFinite.shape) == 1: dFinite = [] for ii in range(d): dFinite.append(isDomainFinite) isDomainFinite = dFinite if len(domain.shape) == 1: dDomain = [] for ii in range(d): dDomain.append(domain) domain = dDomain if not isinstance(create_method, list) or len(create_method) == 1: tmp_method = [] for ii in range(d): if isinstance(create_method, list): tmp_method.append(create_method[0]) else: tmp_method.append(create_method) create_method = tmp_method current_sample = initial_theta.copy() params = [] params.append(lnpdf) params.append(pdf_params) for ii in range(nsamples): if randomize_directions: permuterange = sc.random.permutation(d) else: permuterange = range(d) for dd in permuterange: thisparams = copy.copy(params) thisparams.append(dd) thisparams.append([ current_sample[jj] for jj in range(d) if jj != dd ]) #list comprehensions are supposedly faster than numpy slicing new_up_sample = oned_mcmc.slice(current_sample[dd], step[dd], oned_lnpdf, (thisparams, ), create_method[dd], isDomainFinite[dd], domain[dd], nsamples=1) current_sample = current_sample.copy() current_sample[dd] = new_up_sample if not callback is None: callback(current_sample) out.append(current_sample) if nsamples == 1: return out[0] else: return out