Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALInference 4.1.9.1-00ddc7f
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
nest2pos.py
Go to the documentation of this file.
1import numpy as np
2from numpy import log1p, log, logaddexp, digitize, zeros, exp, concatenate, all, cumsum, ones
3from numpy.random import uniform
4from functools import reduce
5
6def logsubexp(x,y):
7 assert all(x >= y), 'cannot take log of negative number %s - %s'%(str(x),str(y))
8
9 return x + log1p(-exp(y-x))
10
11def log_integrate_log_trap(log_func,log_support):
12 """
13 Trapezoidal integration of given log(func)
14 Returns log of the integral
15 """
16
17 log_func_sum = logaddexp(log_func[:-1], log_func[1:]) - log(2)
18 log_dxs = logsubexp(log_support[:-1], log_support[1:])
19
20 return logaddexp.reduce(log_func_sum + log_dxs)
21
22
23def compute_weights(data, Nlive):
24 """Returns log_ev, log_wts for the log-likelihood samples in data,
25 assumed to be a result of nested sampling with Nlive live points."""
26
27 start_data=concatenate(([float('-inf')], data[:-Nlive]))
28 end_data=data[-Nlive:]
29
30 log_wts=zeros(data.shape[0])
31
32 log_vols_start=cumsum(ones(len(start_data)+1)*log1p(-1./Nlive))-log1p(-1./Nlive)
33 log_vols_end=np.zeros(len(end_data))
34 log_vols_end[-1]=np.NINF
35 log_vols_end[0]=log_vols_start[-1]+np.log1p(-1.0/Nlive)
36 for i in range(len(end_data)-1):
37 log_vols_end[i+1]=log_vols_end[i]+np.log1p(-1.0/(Nlive-i))
38
39 log_likes = concatenate((start_data,end_data,[end_data[-1]]))
40
41 log_vols=concatenate((log_vols_start,log_vols_end))
42
43 log_ev = log_integrate_log_trap(log_likes, log_vols)
44
45 log_dXs = logsubexp(log_vols[:-1], log_vols[1:])
46 log_wts = log_likes[1:-1] + log_dXs[:-1]
47
48 log_wts -= log_ev
49
50 return log_ev, log_wts
51
52def draw_posterior(data, log_wts, verbose=False):
53 """Draw points from the given data (of shape (Nsamples, Ndim))
54 with associated log(weight) (of shape (Nsamples,)). Draws uniquely so
55 there are no repeated samples"""
56 maxWt=max(log_wts)
57 normalised_wts=log_wts-maxWt
58 selection=[n > log(uniform()) for n in normalised_wts]
59 idx=list(filter(lambda i: selection[i], range(len(selection))))
60 return data[idx]
61
62def draw_posterior_many(datas, Nlives, verbose=False):
63 """Draw samples from the posteriors represented by the
64 (Nruns, Nsamples, Nparams)-shaped array datas, each sampled with
65 the corresponding Nlive number of live points. Will draw without repetition,
66 and weight according to the evidence in each input run"""
67 # list of log_evidences, log_weights
68 import astropy
69 log_evs,log_wts=zip(*[compute_weights(data['logL'],Nlive) for data,Nlive in zip(datas, Nlives)])
70 if verbose: print('Computed log_evidences: %s'%(str(log_evs)))
71
72 log_total_evidence=reduce(logaddexp, log_evs)
73 log_max_evidence=max(log_evs)
74 #print 'evidences: %s'%(str(log_evs))
75 fracs=[exp(log_ev-log_max_evidence) for log_ev in log_evs]
76 if verbose: print('Relative weights of input files: %s'%(str(fracs)))
77 Ns=[fracs[i]/len(datas[i]) for i in range(len(fracs))]
78 Ntot=max(Ns)
79 fracs=[n/Ntot for n in Ns]
80 if verbose: print('Relative weights of input files taking into account their length: %s'%(str(fracs)))
81
82 posts=[draw_posterior(data,logwt) for (data,logwt,logZ) in zip(datas,log_wts,log_evs)]
83 if verbose: print('Number of input samples: %s'%(str([len(x) for x in log_wts])))
84 if verbose: print('Expected number of samples from each input file %s'%(str([int(f*len(p)) for f,p in zip(fracs,posts)])))
85 bigpos=[]
86 for post,frac in zip(posts,fracs):
87 mask = uniform(size=len(post))<frac
88 bigpos.append(post[mask])
89 result = astropy.table.vstack(bigpos)
90 if verbose: print('Total number of samples produced: %i'%(len(result)))
91 return result
92
93def draw_N_posterior(data,log_wts, N, verbose=False):
94 """
95 Draw N samples from the input data, weighted by log_wt.
96 For large N there may be repeated samples
97 """
98 if(N==0): return []
99 log_cumsums=zeros(log_wts.shape[0]+1)
100 log_cumsums[0]=-float('inf')
101 for i,log_wt in enumerate(log_wts):
102 log_cumsums[i+1]=logaddexp(log_cumsums[i], log_wt)
103
104 us=log(uniform(size=N))
105 idxs=digitize(us, log_cumsums)
106
107 return data[idxs-1]
108
109def draw_N_posterior_many(datas, Nlives, Npost, verbose=False):
110 """
111 Draw Npost samples from the posteriors represented by the
112 (Nruns, Nsamples, Nparams)-shaped array datas, each sampled with
113 the corresponding number of live points Nlive. The returned number
114 of samples may not be exactly Npost due to rounding
115 """
116 # get log_evidences, log_weights.
117 import astropy
118 log_evs,log_wts=zip(*[compute_weights(data['logL'],Nlive) for data,Nlive in zip(datas, Nlives)])
119
120 log_total_evidence=reduce(logaddexp, log_evs)
121 Ns=[int(round(Npost*exp(log_ev-log_total_evidence))) for log_ev in log_evs]
122 posts=[draw_N_posterior(data,logwt,N) for (data,logwt,N) in zip(datas,log_wts,Ns)]
123 return astropy.table.vstack(posts)
124
125def draw_posterior_many_ROQ_runs(datas, Nlives, verbose=False):
126 """Draw samples from the posteriors represented by the
127 (Nruns, Nsamples, Nparams)-shaped array datas from ROQ runs, each sampled with
128 the corresponding Nlive number of live points. First rescales evidence in each
129 mass prior bin then will draw without repetition,
130 and weight according to the evidence in each input run ala draw_posterior_many"""
131
132 # list of log_evidences, log_weights
133 import astropy
134 log_evs,log_wts=zip(*[compute_weights(data['logL'],Nlive) for data,Nlive in zip(datas, Nlives)])
135 if verbose: print('Computed log_evidences: %s'%(str(log_evs)))
136
137 log_total_evidence=reduce(logaddexp, log_evs)
138 log_max_evidence=max(log_evs)
139 #print 'evidences: %s'%(str(log_evs))
140 fracs=[exp(log_ev-log_max_evidence) for log_ev in log_evs] #TODO: add logPriorVol from ROQ run
141 if verbose: print('Relative weights of input files: %s'%(str(fracs)))
142 Ns=[fracs[i]/len(datas[i]) for i in range(len(fracs))]
143 Ntot=max(Ns)
144 fracs=[n/Ntot for n in Ns]
145 if verbose: print('Relative weights of input files taking into account their length: %s'%(str(fracs)))
146
147 bigpos=[]
148 posts=[draw_posterior(data,logwt) for (data,logwt,logZ) in zip(datas,log_wts,log_evs)]
149 if verbose: print('Number of input samples: %s'%(str([len(x) for x in log_wts])))
150 if verbose: print('Expected number of samples from each input file %s'%(str([int(f*len(p)) for f,p in zip(fracs,posts)])))
151 return astropy.table.vstack(bigpos)
#define max(a, b)
static double logaddexp(double x, double y)
Definition: logaddexp.h:37
def draw_N_posterior(data, log_wts, N, verbose=False)
Draw N samples from the input data, weighted by log_wt.
Definition: nest2pos.py:97
def draw_posterior_many_ROQ_runs(datas, Nlives, verbose=False)
Draw samples from the posteriors represented by the (Nruns, Nsamples, Nparams)-shaped array datas fro...
Definition: nest2pos.py:130
def draw_posterior(data, log_wts, verbose=False)
Draw points from the given data (of shape (Nsamples, Ndim)) with associated log(weight) (of shape (Ns...
Definition: nest2pos.py:55
def log_integrate_log_trap(log_func, log_support)
Trapezoidal integration of given log(func) Returns log of the integral.
Definition: nest2pos.py:15
def logsubexp(x, y)
Definition: nest2pos.py:6
def draw_posterior_many(datas, Nlives, verbose=False)
Draw samples from the posteriors represented by the (Nruns, Nsamples, Nparams)-shaped array datas,...
Definition: nest2pos.py:66
def compute_weights(data, Nlive)
Returns log_ev, log_wts for the log-likelihood samples in data, assumed to be a result of nested samp...
Definition: nest2pos.py:25
def draw_N_posterior_many(datas, Nlives, Npost, verbose=False)
Draw Npost samples from the posteriors represented by the (Nruns, Nsamples, Nparams)-shaped array dat...
Definition: nest2pos.py:115