def metropolis(initial_theta,proposal_params,lnpdf,pdf_params,symmetric=False, sample_proposal=sample_gaussian_proposal, eval_ln_proposal=eval_ln_gaussian_proposal, nsamples=1,randomize_directions=True,callback=None): """ NAME: metropolis PURPOSE: metropolis mcmc INPUT: initial_theta - initial sample proposal_params - parameters for the proposal function (e.g., typical steps) (single for all dimensions or list of functions) lnpdf - function evaluating the log of the pdf to be sampled pdf_params - parameters to pass to the pdf (tuple) sample_proposal - given x and proposal_params, sample a proposal using this function DEFAULT: GAUSSIAN (single function for all dimensions or list of functions) eval_ln_proposal - given x and proposal_params, evaluate the log of the proposal density DEFAULT: GAUSSIAN (single function for all dimensions or list of functions) symmetric - (bool) if True, the proposal distribution is symmetric and will not be evaluated (bool or list of bools randomize_directions - (bool) pick a random coordinate to update nsamples - number of samples desired callback - function of current parameters to call after each new sample OUTPUT: tuple consisting of list of samples, number if nsamples=1 acceptance ratio, 1 or 0 if nsamples=1 REVISION HISTORY: 2011-07-27 - Written - Bovy (NYU) """ try: ndim = len(initial_theta) except TypeError: ndim= 1 if ndim == 1: #1D return bovy_mcmc_oned.metropolis(initial_theta, sample_proposal, eval_ln_proposal, proposal_params,lnpdf, pdf_params,symmetric=symmetric, nsamples=nsamples,callback=callback) else: #multi-D return bovy_mcmc_multid.metropolis(initial_theta, sample_proposal, eval_ln_proposal, proposal_params,lnpdf, pdf_params,symmetric=symmetric, nsamples=nsamples, randomize_directions=\ randomize_directions, callback=callback)
def metropolis(initial_theta, proposal_params, lnpdf, pdf_params, symmetric=False, sample_proposal=sample_gaussian_proposal, eval_ln_proposal=eval_ln_gaussian_proposal, nsamples=1, randomize_directions=True, callback=None): """ NAME: metropolis PURPOSE: metropolis mcmc INPUT: initial_theta - initial sample proposal_params - parameters for the proposal function (e.g., typical steps) (single for all dimensions or list of functions) lnpdf - function evaluating the log of the pdf to be sampled pdf_params - parameters to pass to the pdf (tuple) sample_proposal - given x and proposal_params, sample a proposal using this function DEFAULT: GAUSSIAN (single function for all dimensions or list of functions) eval_ln_proposal - given x and proposal_params, evaluate the log of the proposal density DEFAULT: GAUSSIAN (single function for all dimensions or list of functions) symmetric - (bool) if True, the proposal distribution is symmetric and will not be evaluated (bool or list of bools randomize_directions - (bool) pick a random coordinate to update nsamples - number of samples desired callback - function of current parameters to call after each new sample OUTPUT: tuple consisting of list of samples, number if nsamples=1 acceptance ratio, 1 or 0 if nsamples=1 REVISION HISTORY: 2011-07-27 - Written - Bovy (NYU) """ try: ndim = len(initial_theta) except TypeError: ndim = 1 if ndim == 1: #1D return bovy_mcmc_oned.metropolis(initial_theta, sample_proposal, eval_ln_proposal, proposal_params, lnpdf, pdf_params, symmetric=symmetric, nsamples=nsamples, callback=callback) else: #multi-D return bovy_mcmc_multid.metropolis(initial_theta, sample_proposal, eval_ln_proposal, proposal_params,lnpdf, pdf_params,symmetric=symmetric, nsamples=nsamples, randomize_directions=\ randomize_directions, callback=callback)
def metropolis(initial_theta,sample_proposal,eval_ln_proposal, proposal_params,lnpdf,pdf_params,symmetric=False, nsamples=1,randomize_directions=True,callback=None): """ NAME: metropolis PURPOSE: metropolis mcmc INPUT: initial_theta - initial sample sample_proposal - given x and proposal_params, sample a proposal using this function (single function for all dimensions or list of functions) eval_ln_proposal - given x and proposal_params, evaluate the log of the proposal density (single function for all dimensions or list of functions) proposal_params - parameters for the proposal function (e.g., typical steps) (single for all dimensions or list of functions) lnpdf - function evaluating the log of the pdf to be sampled pdf_params - parameters to pass to the pdf (tuple) symmetric - (bool) if True, the proposal distribution is symmetric and will not be evaluated (bool or list of bools randomize_directions - (bool) pick a random coordinate to update nsamples - number of samples desired OUTPUT: tuple consisting of list of samples, number if nsamples=1 acceptance ratio, 1 or 0 if nsamples=1 REVISION HISTORY: 2011-07-27 - Written - Bovy (NYU) DOCTEST: >>> import numpy as nu >>> nu.random.seed(1) >>> import scipy as sc >>> from scipy import linalg >>> from scipy import stats >>> 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])) >>> def sample_gaussian_proposal(mean,stddev): ... return stats.norm.rvs()*stddev+mean >>> def eval_ln_gaussian_proposal(new,old,stddev): ... return -0.5*sc.log(2.*sc.pi*stddev**2.)-0.5*(old-new)**2./stddev**2. >>> lnpdf= lngaussian >>> pdf_params= ([sc.array([0.,1.]),sc.array([[1.,0.],[0.,4.]])],) >>> sample_proposal= sample_gaussian_proposal >>> eval_ln_proposal= eval_ln_gaussian_proposal >>> proposal_params= (2.,) >>> symmetric=False >>> initial_theta= nu.array([5.,-3]) >>> nsamples= 40000 >>> samples,faccept= metropolis(initial_theta,sample_proposal,eval_ln_proposal,proposal_params,lnpdf,pdf_params,symmetric=symmetric,nsamples=nsamples) >>> print "%4.1f%% of the samples were accepted" % (100.*nu.mean(faccept)) 39.6% of the samples were accepted >>> samples= samples[nsamples/2:-1] #discard burn-in >>> xs= [s[0] for s in samples] >>> ys= [s[1] for s in samples] >>> logprecision= -2. >>> assert (nu.mean(xs)-0.)**2. < 10.**(logprecision*2.) >>> assert (nu.mean(ys)-1.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(xs)-1.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(ys)-.5)**2. < 10.**(logprecision*2.) >>> proposal_params= [(2.,),(4.,)] >>> initial_theta= nu.array([5.,-3]) >>> nsamples= 80000 >>> samples,faccept= metropolis(initial_theta,sample_proposal,eval_ln_proposal,proposal_params,lnpdf,pdf_params,symmetric=symmetric,nsamples=nsamples) >>> print "%4.1f%% of the samples were accepted" % (100.*nu.mean(faccept)) 32.6% of the samples were accepted >>> samples= samples[nsamples/2:-1] #discard burn-in >>> xs= [s[0] for s in samples] >>> ys= [s[1] for s in samples] >>> logprecision= -2. >>> assert (nu.mean(xs)-0.)**2. < 10.**(logprecision*2.) >>> assert (nu.mean(ys)-1.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(xs)-1.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(ys)-.5)**2. < 10.**(logprecision*2.) """ out= [] d= len(initial_theta) #dimensionality if isinstance(proposal_params,tuple): proposal_params= [proposal_params for ii in range(d)] elif isinstance(proposal_params,list) \ and isinstance(proposal_params[0],(int,float)): proposal_params= [(proposal_params[ii],) for ii in range(d)] elif isinstance(proposal_params,(int,float)): proposal_params= [(proposal_params,) for ii in range(d)] if not isinstance(sample_proposal,list): sample_proposal= [sample_proposal for ii in range(d)] if not isinstance(eval_ln_proposal,list): eval_ln_proposal= [eval_ln_proposal for ii in range(d)] if isinstance(symmetric,bool): symmetric= [symmetric for ii in range(d)] current_sample= initial_theta.copy() params= [] params.append(lnpdf) params.append(pdf_params) naccept= sc.zeros(d) 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,accepted= oned_mcmc.metropolis(current_sample[dd], sample_proposal[dd], eval_ln_proposal[dd], proposal_params[dd], oned_lnpdf,(thisparams,), symmetric=symmetric[dd], nsamples=1) current_sample= current_sample.copy() current_sample[dd]= new_up_sample naccept[dd]+= accepted if not callback is None: callback(current_sample) out.append(current_sample) if nsamples == 1: return (out[0],naccept) else: return (out,naccept/float(nsamples))
def metropolis(initial_theta, sample_proposal, eval_ln_proposal, proposal_params, lnpdf, pdf_params, symmetric=False, nsamples=1, randomize_directions=True, callback=None): """ NAME: metropolis PURPOSE: metropolis mcmc INPUT: initial_theta - initial sample sample_proposal - given x and proposal_params, sample a proposal using this function (single function for all dimensions or list of functions) eval_ln_proposal - given x and proposal_params, evaluate the log of the proposal density (single function for all dimensions or list of functions) proposal_params - parameters for the proposal function (e.g., typical steps) (single for all dimensions or list of functions) lnpdf - function evaluating the log of the pdf to be sampled pdf_params - parameters to pass to the pdf (tuple) symmetric - (bool) if True, the proposal distribution is symmetric and will not be evaluated (bool or list of bools randomize_directions - (bool) pick a random coordinate to update nsamples - number of samples desired OUTPUT: tuple consisting of list of samples, number if nsamples=1 acceptance ratio, 1 or 0 if nsamples=1 REVISION HISTORY: 2011-07-27 - Written - Bovy (NYU) DOCTEST: >>> import numpy as nu >>> nu.random.seed(1) >>> import scipy as sc >>> from scipy import linalg >>> from scipy import stats >>> 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])) >>> def sample_gaussian_proposal(mean,stddev): ... return stats.norm.rvs()*stddev+mean >>> def eval_ln_gaussian_proposal(new,old,stddev): ... return -0.5*sc.log(2.*sc.pi*stddev**2.)-0.5*(old-new)**2./stddev**2. >>> lnpdf= lngaussian >>> pdf_params= ([sc.array([0.,1.]),sc.array([[1.,0.],[0.,4.]])],) >>> sample_proposal= sample_gaussian_proposal >>> eval_ln_proposal= eval_ln_gaussian_proposal >>> proposal_params= (2.,) >>> symmetric=False >>> initial_theta= nu.array([5.,-3]) >>> nsamples= 40000 >>> samples,faccept= metropolis(initial_theta,sample_proposal,eval_ln_proposal,proposal_params,lnpdf,pdf_params,symmetric=symmetric,nsamples=nsamples) >>> print "%4.1f%% of the samples were accepted" % (100.*nu.mean(faccept)) 39.6% of the samples were accepted >>> samples= samples[nsamples/2:-1] #discard burn-in >>> xs= [s[0] for s in samples] >>> ys= [s[1] for s in samples] >>> logprecision= -2. >>> assert (nu.mean(xs)-0.)**2. < 10.**(logprecision*2.) >>> assert (nu.mean(ys)-1.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(xs)-1.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(ys)-.5)**2. < 10.**(logprecision*2.) >>> proposal_params= [(2.,),(4.,)] >>> initial_theta= nu.array([5.,-3]) >>> nsamples= 80000 >>> samples,faccept= metropolis(initial_theta,sample_proposal,eval_ln_proposal,proposal_params,lnpdf,pdf_params,symmetric=symmetric,nsamples=nsamples) >>> print "%4.1f%% of the samples were accepted" % (100.*nu.mean(faccept)) 32.6% of the samples were accepted >>> samples= samples[nsamples/2:-1] #discard burn-in >>> xs= [s[0] for s in samples] >>> ys= [s[1] for s in samples] >>> logprecision= -2. >>> assert (nu.mean(xs)-0.)**2. < 10.**(logprecision*2.) >>> assert (nu.mean(ys)-1.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(xs)-1.)**2. < 10.**(logprecision*2.) >>> assert (nu.std(ys)-.5)**2. < 10.**(logprecision*2.) """ out = [] d = len(initial_theta) #dimensionality if isinstance(proposal_params, tuple): proposal_params = [proposal_params for ii in range(d)] elif isinstance(proposal_params,list) \ and isinstance(proposal_params[0],(int,float)): proposal_params = [(proposal_params[ii], ) for ii in range(d)] elif isinstance(proposal_params, (int, float)): proposal_params = [(proposal_params, ) for ii in range(d)] if not isinstance(sample_proposal, list): sample_proposal = [sample_proposal for ii in range(d)] if not isinstance(eval_ln_proposal, list): eval_ln_proposal = [eval_ln_proposal for ii in range(d)] if isinstance(symmetric, bool): symmetric = [symmetric for ii in range(d)] current_sample = initial_theta.copy() params = [] params.append(lnpdf) params.append(pdf_params) naccept = sc.zeros(d) 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, accepted = oned_mcmc.metropolis( current_sample[dd], sample_proposal[dd], eval_ln_proposal[dd], proposal_params[dd], oned_lnpdf, (thisparams, ), symmetric=symmetric[dd], nsamples=1) current_sample = current_sample.copy() current_sample[dd] = new_up_sample naccept[dd] += accepted if not callback is None: callback(current_sample) out.append(current_sample) if nsamples == 1: return (out[0], naccept) else: return (out, naccept / float(nsamples))