Example #1
0
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)
Example #2
0
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)
Example #3
0
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))
Example #4
0
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))