def fit(self, X, y, y_error=1, x_error=None, *, sample_kwargs={'draws': 1000, 'target_accept': 0.9, 'return_inferencedata': False}): kwds = {} if self.kwds is not None: kwds.update(self.kwds) kwds['fit_intercept'] = False model = self._choose_regressor() self.clf_ = model(**kwds) self.fit_intercept = False if x_error is not None: x_error = np.atleast_2d(x_error) with pm.Model(): # slope and intercept of eta-ksi relation slope = pm.Flat('slope', shape=(X.shape[0], )) inter = pm.Flat('inter') # intrinsic scatter of eta-ksi relation int_std = pm.HalfFlat('int_std') # standard deviation of Gaussian that ksi are drawn from (assumed mean zero) tau = pm.HalfFlat('tau', shape=(X.shape[0],)) # intrinsic ksi mu = pm.Normal('mu', mu=0, sigma=tau, shape=(X.shape[0],)) # Some wizzarding with the dimensions all around. ksi = pm.Normal('ksi', mu=mu, tau=tau, shape=X.T.shape) # intrinsic eta-ksi linear relation + intrinsic scatter eta = pm.Normal('eta', mu=(tt.dot(slope.T, ksi.T) + inter), sigma=int_std, shape=y.shape) # observed xi, yi x = pm.Normal('xi', mu=ksi.T, sigma=x_error, observed=X, shape=X.shape) # noqa: F841 y = pm.Normal('yi', mu=eta, sigma=y_error, observed=y, shape=y.shape) self.trace = pm.sample(**sample_kwargs) # TODO: make it optional to choose a way to define best HND, edges = np.histogramdd(np.hstack((self.trace['slope'], self.trace['inter'][:, None])), bins=50) w = np.where(HND == HND.max()) # choose the maximum posterior slope and intercept slope_best = [edges[i][w[i][0]] for i in range(len(edges) - 1)] intercept_best = edges[-1][w[-1][0]] self.clf_.coef_ = np.array([intercept_best, *slope_best]) return self
def fit_adj_pass_model(successes, attempts): ## inputs are two lists in the form: ## successes = [successful long passes, total successful passes] ## attempts = [attempted long passes, total attempted passes] ## returns: ## sl, a numpy array of shape (6000,N) containing 6000 posterior samples of success probabilites (N is the number of players in the ## original data frame who have registered non-zero expected succcesses) ## sb, an empty list ## kk, boolean indicating which players have actually registered non-zero expected successes ## 'adj_pass', character string indicating the model type. import numpy as np import pymc3 as pm import pymc3.distributions.transforms as tr import theano.tensor as tt LonCmp = successes[0] TotCmp = successes[1] LonAtt = attempts[0] TotAtt = attempts[1] kk = (LonCmp > 0) & np.isfinite(LonAtt) LonCmp = LonCmp[kk] LonAtt = LonAtt[kk] TotCmp = TotCmp[kk] TotAtt = TotAtt[kk] ShCmp = TotCmp - LonCmp ShAtt = TotAtt - LonAtt average_long_tendency = np.mean(LonAtt / TotAtt) N = np.sum(kk) def logp_ab(value): ''' prior density''' return tt.log(tt.pow(tt.sum(value), -5 / 2)) with pm.Model() as model: # Uninformative prior for alpha and beta ab_short = pm.HalfFlat('ab_short', shape=2, testval=np.asarray([1., 1.])) ab_long = pm.HalfFlat('ab_long', shape=2, testval=np.asarray([1., 1.])) pm.Potential('p(a_s, b_s)', logp_ab(ab_short)) pm.Potential('p(a_l, b_l)', logp_ab(ab_long)) lambda_short = pm.Beta('lambda_s', alpha=ab_short[0], beta=ab_short[1], shape=N) lambda_long = pm.Beta('lambda_l', alpha=ab_long[0], beta=ab_long[1], shape=N) y_short = pm.Binomial('y_s', p=lambda_short, observed=ShCmp, n=ShAtt) y_long = pm.Binomial('y_l', p=lambda_short * lambda_long, observed=LonCmp, n=LonAtt) approx = pm.fit(n=30000) s_sh = approx.sample(6000)['lambda_s'] s_lo = approx.sample(6000)['lambda_l'] sl = average_long_tendency * s_lo + (1 - average_long_tendency) * s_sh return [sl, [], kk, 'adj_pass']
def fit(self, matches, target): lineups = set(matches['t1_lineup'].unique()).union( matches['t2_lineup'].unique()) self.lineup_f2id = dict(enumerate( lineups, 0)) # start from 0 for zero-based indexing self.lineup_id2f = {v: k for k, v in self.lineup_f2id.items()} t1 = matches['t1_lineup'].map(self.lineup_id2f) t2 = matches['t2_lineup'].map(self.lineup_id2f) # threshold_date = str(datetime.datetime.strptime(matches['date'].max(), '%Y-%m-%d %H:%M') -\ # datetime.timedelta(days=self.time_span)) # t1_older = matches[matches['date'] <= threshold_date]['t1_lineup'].map(self.lineup_id2f) # t2_older = matches[matches['date'] <= threshold_date]['t2_lineup'].map(self.lineup_id2f) # t1_newer = matches[matches['date'] > threshold_date]['t1_lineup'].map(self.lineup_id2f) # t2_newer = matches[matches['date'] > threshold_date]['t2_lineup'].map(self.lineup_id2f) t_num = len(lineups) # number of teams # obs_older = target[matches['date'] <= threshold_date] # obs_newer = target[matches['date'] > threshold_date] # modeling older observations with pm.Model() as model: sigma = pm.HalfFlat('sigma', shape=t_num) alpha = pm.Normal('alpha', mu=0, sigma=sigma, shape=t_num) theta = pm.Deterministic('theta', alpha[t1] - alpha[t2]) y = pm.Bernoulli('y', logit_p=theta, observed=target) self.trace = pm.sample(self.fit_iters, tune=self.tune) '''# modeling newer observations
def make_model(spec: ModelSpec, dat, basis, unfold, aPosterior): with pm.Model() as model: # Prior for alpha if isinstance(spec.alphaPrior, float): alpha = spec.alphaPrior elif isinstance(spec.alphaPrior, AlphaLognormal): alphaLN = aPosterior.lognormal(scale=spec.alphaPrior.scale) alpha = pm.Lognormal('alpha', mu=alphaLN.mu, sd=alphaLN.sig) elif spec.alphaPrior is None: alpha = pm.HalfFlat('alpha') else: raise Exception("Unknown prior for alpha") # Prior for phi nPhi = len(basis) om = unfold.omegas[0].mat chol = np.linalg.cholesky(np.linalg.inv(om)) low = np.repeat(0, nPhi) if spec.phiPrior == "positive": phiDistr = pm.Bound(pm.MvNormal, lower=low) elif spec.phiPrior == "any": phiDistr = pm.MvNormal phi = phiDistr('phi', mu=np.zeros(nPhi), chol=chol / np.sqrt(alpha), shape=nPhi) # Experimental data f = pm.Normal( 'f', mu=pm.math.dot(unfold.K, phi), sd=dat['err'].values, shape=len(dat), observed=dat['cnt'].values, ) return model
def fit_counts_model(counts, mins_played): ## estimates a hierarchical poisson model for count data ## takes as input: ## counts, a numpy array of shape (num_players,) containing the total numbers of actions completed (across all games) ## mins_played, a numpy array of shape (num_players,) containing the total number of minutes each player was observed for ## returns: ## sl, a numpy array of shape (6000,N) containing 6000 posterior samples of actions per 90 (N is the number of players in the ## original data frame who have actually played minutes) ## sb, a numpy array of shape (6000,2) containing 6000 posterior samples of the population-level gamma shape parameter & ## the population-level mean ## kk, boolean indicating which players have actually played minutes import numpy as np import pymc3 as pm kk = (mins_played > 0) & np.isfinite(counts) mins_played = mins_played[kk] counts = counts[kk] N = counts.shape[0] with pm.Model() as model: beta = pm.HalfNormal('beta', sigma=100) mu = pm.HalfFlat('mu') lambdas = pm.Gamma('lambdas', alpha=mu * beta, beta=beta, shape=N) lambda_tilde = lambdas * mins_played y = pm.Poisson('y', lambda_tilde, observed=counts) approx = pm.fit(n=30000) sl = approx.sample(6000)['lambdas'] * 90 sb = np.c_[approx.sample(6000)['beta'], approx.sample(6000)['mu']] return [sl, sb, kk, 'count']
def fit(self, X, y, y_error, x_error, sample_kwargs={ 'draws': 1000, 'target_accept': 0.9 }): X = np.atleast_2d(X) x_error = np.atleast_2d(x_error) with pm.Model(): # slope and intercept of eta-ksi relation slope = pm.Flat('slope', shape=(X.shape[0], )) inter = pm.Flat('inter') # intrinsic scatter of eta-ksi relation int_std = pm.HalfFlat('int_std') # standard deviation of Gaussian that ksi are drawn from (assumed mean zero) tau = pm.HalfFlat('tau', shape=(X.shape[0], )) # intrinsic ksi mu = pm.Normal('mu', mu=0, sd=tau, shape=(X.shape[0], )) # Some wizzarding with the dimensions all around. ksi = pm.Normal('ksi', mu=mu, tau=tau, shape=X.T.shape) # intrinsic eta-ksi linear relation + intrinsic scatter eta = pm.Normal('eta', mu=(tt.dot(slope.T, ksi.T) + inter), sd=int_std, shape=y.shape) # observed xi, yi x = pm.Normal('xi', mu=ksi.T, sd=x_error, observed=X, shape=X.shape) y = pm.Normal('yi', mu=eta, sd=y_error, observed=y, shape=y.shape) self.trace = pm.sample(**sample_kwargs) return self
def main(): if len(sys.argv) < 2 or len(sys.argv) > 3: print( 'usage: python3 inference_dir.py [chain no] [optional output no]') sys.exit() elif len(sys.argv) == 2: c = int(sys.argv[1]) d = int(sys.argv[1]) if len(sys.argv) == 3: c = int(sys.argv[1]) d = int(sys.argv[2]) np.random.seed(c) np.random.shuffle(lang_ind) np.random.shuffle(sound_ind) lang_minibatch = pm.Minibatch(lang_ind, 500) sound_minibatch = pm.Minibatch(sound_ind, 500) model_ln = pm.Model() with model_ln: beta = pm.HalfFlat('beta') "theta = language-level prior over components" theta = tt.stack([ pm.Dirichlet('theta_{}'.format(l), a=tt.ones(K) * beta, shape=K) for l in range(L) ]) psi = [ pm.MvNormal('psi_{}'.format(k), mu=[0] * S, cov=Sigma, shape=S) for k in range(K) ] "phi = component-level collection of distributions over sound change" phi = tt.stack([ tt.concatenate([ pm.Deterministic( 'phi_{}_{}'.format(k, x), tt.nnet.softmax(psi[k][s_breaks[x][0]:s_breaks[x][1]])[0]) for x in range(X) ]) for k in range(K) ]) target = pm.DensityDist('target', logprob(theta=theta, phi=phi), observed=dict(lang_array=lang_minibatch, sound_array=sound_minibatch), total_size=N) inference_ln = pm.ADVI() inference_ln.fit(50000, obj_optimizer=pm.adam(learning_rate=.01, beta1=uniform(.7, .9)), callbacks=[pm.callbacks.CheckParametersConvergence()]) trace_ln = inference_ln.approx.sample() posterior = { k: trace_ln[k] for k in trace_ln.varnames if not k.endswith('__') } posterior['ELBO'] = inference_ln.hist f = open('posterior_ln_shuffle_{}.pkl'.format(d), 'wb') pkl.dump(posterior, f) f.close()
def constructBasicModel(pdfDict): """ Construct model without axions! (Null hypothesis) """ with pm.Model() as model: # We using HalfFlat cuz we dgaf -- probably we should switch to a more informative prior Tritium = pm.HalfFlat("Tritium") Bkg = pm.HalfFlat("Bkg") Fe55 = pm.HalfFlat("Fe55") Zn65 = pm.HalfFlat("Zn65") Ge68 = pm.HalfFlat("Ge68") # Generate array of deterministic variables (per bin) det = Tritium * pdfDict['Tritium'] + Bkg * pdfDict[ 'Bkg'] + Fe55 * pdfDict['Fe55'] + Zn65 * pdfDict[ 'Zn65'] + Ge68 * pdfDict['Ge68'] L = pm.Poisson("L", mu=det, observed=pdfDict['Data']) return model
def _gen_d_vars_pm(tmñ=(), fmt_nmbrs='{}'): egr = {} for p, líms in líms_paráms.items(): nmbr = fmt_nmbrs.format(p) if aprioris is None: if líms[0] is None: if líms[1] is None: dist_pm = pm.Flat(nmbr, shape=tmñ) else: if líms[1] == 0: dist_pm = -pm.HalfFlat(nmbr, shape=tmñ) else: dist_pm = líms[1] - pm.HalfFlat(nmbr, shape=tmñ) else: if líms[1] is None: if líms[0] == 0: dist_pm = pm.HalfFlat(nmbr, shape=tmñ) else: dist_pm = líms[0] + pm.HalfFlat(nmbr, shape=tmñ) else: dist_pm = pm.Uniform(nmbr, lower=líms[0], upper=líms[1], shape=tmñ) else: dist, prms = aprioris[p] if (líms[0] is not None or líms[1] is not None) and dist != pm.Uniform: acotada = pm.Bound(dist, lower=líms[0], upper=líms[1]) dist_pm = acotada(nmbr, shape=tmñ, **prms) else: if dist == pm.Uniform: prms['lower'] = max(prms['lower'], líms[0]) prms['upper'] = min(prms['upper'], líms[1]) dist_pm = dist(nmbr, shape=tmñ, **prms) egr[p] = dist_pm return egr
def constructModel(pdfDict, energyBins): """ Construct pymc3 model """ with pm.Model() as model: # We using HalfFlat cuz we dgaf -- probably we should switch to a more informative prior Axion = pm.HalfFlat("Axion") Tritium = pm.HalfFlat("Tritium") Bkg = pm.HalfFlat("Bkg") Fe55 = pm.HalfFlat("Fe55") Zn65 = pm.HalfFlat("Zn65") Ge68 = pm.HalfFlat("Ge68") # Create the detector efficiency deterministic # NOTE: Problem with # Mu = pm.Normal('Mu', mu = 0.36, sd = 0.5) # Sig = pm.Normal('Sig', mu = 1.26, sd = 0.5) # eff = 0.5*(1+tt.erf((pdfDict['Energy'] - Mu)/(tt.sqrt(2)*Sig))) # Reparameterize efficiency as logistic function Mu = pm.Normal('Mu', mu=0.77, sd=0.1) Sig = pm.Normal('Sig', mu=0.56, sd=0.1) eff = 1. / (1. + tt.exp(-(pdfDict['Energy'] - Mu) / Sig)) # Generate array of deterministic variables (per bin) det = (Tritium * pdfDict['Tritium'] + Bkg * pdfDict['Bkg'] + Axion * pdfDict['Axion'] + Fe55 * pdfDict['Fe55'] + Zn65 * pdfDict['Zn65'] + Ge68 * pdfDict['Ge68']) * eff # det = Tritium*pdfDict['Tritium'] + Bkg*pdfDict['Bkg'] + Axion*pdfDict['Axion'] + Fe55*pdfDict['Fe55'] + Zn65*pdfDict['Zn65'] + Ge68*pdfDict['Ge68'] L = pm.Poisson("L", mu=det, observed=pdfDict['Data']) return model
def test_model_not_drawable_prior(self): data = np.random.poisson(lam=10, size=200) model = pm.Model() with model: mu = pm.HalfFlat("sigma") pm.Poisson("foo", mu=mu, observed=data) trace = pm.sample(tune=1000) with model: with pytest.raises(ValueError) as excinfo: pm.sample_prior_predictive(50) assert "Cannot sample" in str(excinfo.value) samples = pm.sample_posterior_predictive(trace, 50) assert samples["foo"].shape == (50, 200)
def main(): if len(sys.argv) < 2 or len(sys.argv) > 3: print( 'usage: python3 inference_dir.py [chain no] [optional output no]') sys.exit() elif len(sys.argv) == 2: c = int(sys.argv[1]) d = int(sys.argv[1]) if len(sys.argv) == 3: c = int(sys.argv[1]) d = int(sys.argv[2]) np.random.seed(c) lang_minibatch = pm.Minibatch(lang_ind, 500) sound_minibatch = pm.Minibatch(sound_ind, 500) model_dir = pm.Model() with model_dir: beta = pm.HalfFlat('beta') "theta = language-level prior over components" theta = tt.stack([ pm.Dirichlet('theta_{}'.format(l), a=tt.ones(K) * beta, shape=K) for l in range(L) ]) phi = tt.stack([ tt.concatenate([ pm.Dirichlet('phi_{}_{}'.format(k, x), a=tt.ones(R[x]) * alpha, shape=R[x]) for x in range(X) ]) for k in range(K) ]) target = pm.DensityDist('target', logprob(theta=theta, phi=phi), observed=dict(lang_array=lang_minibatch, sound_array=sound_minibatch), total_size=N) inference_dir = pm.ADVI() inference_dir.fit( 50000, obj_optimizer=pm.adam(learning_rate=.01, beta1=uniform(.7, .9)), callbacks=[pm.callbacks.CheckParametersConvergence()]) trace_dir = inference_dir.approx.sample() posterior = { k: trace_dir[k] for k in trace_dir.varnames if not k.endswith('__') } posterior['ELBO'] = inference_dir.hist f = open('posterior_dir_{}.pkl'.format(d), 'wb') pkl.dump(posterior, f) f.close()
def _get_posterior_samples(self, obs, n_samples, seed): def tegpd_logp(x, xi, sigma): #returns the sum of log-liklihoods if xi != 0: return tt.sum(-tt.log(sigma) - (1.0 / xi + 1) * tt.log(1 + xi / sigma * x)) else: return tt.sum(-tt.log(sigma) - x / sigma) obs = np.array(obs) x_max = np.max(obs) #Bayesian specification and inference gp_model = pm.Model() with gp_model: #xi, sigma = get_priors(prior_name) xi = pm.Normal('xi', mu=0, sigma=1) sigma = pm.HalfFlat('sigma') #sigma is remapped to values that prevent the loglikelihood to be -Inf; this happens if sigma is such that # the theoretical upper bound of the data distribution is lower than their observed values. X = pm.DensityDist("tegpd", tegpd_logp, observed={ "xi": xi, "sigma": (-xi * x_max).clip(0, np.Inf) + sigma, "x": obs }) trace = pm.sample(n_samples, random_seed=seed) #get sampled posteriors xi_samples = trace.get_values("xi") sigma_samples = trace.get_values("sigma") + (-xi_samples * x_max).clip( 0, np.Inf) mat = np.concatenate([ np.array(sigma_samples).reshape(-1, 1), np.array(xi_samples).reshape(-1, 1) ], axis=1) self.posterior_sigma = np.ascontiguousarray(mat[:, 0], dtype=np.float64) self.posterior_xi = np.ascontiguousarray(mat[:, 1], dtype=np.float64) self.n_posterior = len(self.posterior_sigma)
def mcmcBinomial(data): def hyper_prior(value): ''' prior density''' return tt.log(tt.pow(tt.sum(value), -5 / 2)) with pm.Model() as model: # Uninformative prior for alpha and beta #true_rates = pm.Beta('true_rates', a, b, size=5) ab = pm.HalfFlat('alpha_beta', shape=2, testval=np.asarray([1., 1.])) pm.Potential('p(alpha, beta)', hyper_prior(ab)) #Allows you to do algrebra with RVs X = pm.Deterministic('X', tt.log(ab[0] / ab[1])) Z = pm.Deterministic('Z', tt.log(tt.sum(ab))) theta = pm.Beta('theta', alpha=ab[0], beta=ab[1]) #p = pm.Binomial('y', p=theta, observed=y, n=n) p = pm.Bernoulli('y', theta, observed=data) trace = pm.sample(5000, tune=2000, target_accept=0.95) return (trace)
def fit_successes_model(successes, attempts): ## estimates a hierarchical binomial model for success rate data ## takes as input: ## successes, a numpy array of shape (num_players,) containing the total numbers of successful actions (across all games) ## attempts, a numpy array of shape (num_players,) containing the total numbers of attempted actions (across all games) ## returns: ## sl, a numpy array of shape (6000,N) containing 6000 posterior samples of success probabilites (N is the number of players in the ## original data frame who have actually attempted a pass) ## sb, a numpy array of shape (6000,2) containing 6000 posterior samples of the population-level beta parameters ## kk, boolean indicating which players have actually attempted a pass import numpy as np import pymc3 as pm import pymc3.distributions.transforms as tr import theano.tensor as tt kk = (attempts > 0) & np.isfinite(successes) attempts = attempts[kk] successes = successes[kk] N = attempts.shape[0] def logp_ab(value): ''' prior density''' return tt.log(tt.pow(tt.sum(value), -5 / 2)) with pm.Model() as model: # Uninformative prior for alpha and beta ab = pm.HalfFlat('ab', shape=2, testval=np.asarray([1., 1.])) pm.Potential('p(a, b)', logp_ab(ab)) lambdas = pm.Beta('lambdas', alpha=ab[0], beta=ab[1], shape=N) p = pm.Binomial('y', p=lambdas, observed=successes, n=attempts) approx = pm.fit(n=30000) sl = approx.sample(6000)['lambdas'] * 100 sb = approx.sample(6000)['ab'] return [sl, sb, kk, 'success']
BASE_NAME = '{}_{}_{}C_{}_{}'.format(DATE, RUN, TEMP, CARBON, OPERATOR) # ################################ # Nothing below here should change # ################################ if os.path.isdir('output') == False: os.mkdir('output') # Load and trim the data to start at 0D = 0.1 data = pd.read_csv('{}_growth.csv'.format(BASE_NAME)) data = data[(data['OD_600'] >= 0.1) & (data['OD_600'] <= 0.8)] with pm.Model() as model: a0 = pm.HalfNormal('a0', sd=1) lam = pm.HalfFlat('lambda') gamma = mwc.bayes.Jeffreys('gamma', lower=1E-9, upper=100) # Compute the expected value. time = data['elapsed_time_min'].values mu = np.log(a0) + time * lam # Define the likelihood and sample. like = pm.Cauchy('like', mu, gamma, observed=np.log(data['OD_600'].values)) trace = pm.sample(tune=5000, draws=5000) trace_df = mwc.stats.trace_to_dataframe(trace, model) stats = mwc.stats.compute_statistics(trace_df) # %% Compute the best fit and credible region modes = {} hpds = {}
def _to_pymc3_distribution(name, par): """ Create a pymc3 continuous distribution from a Bounds object. Parameters ---------- name : str Name of parameter par : refnx.analysis.Parameter The parameter to wrap Returns ------- d : pymc3.Distribution The pymc3 distribution """ import pymc3 as pm import theano.tensor as T from theano.compile.ops import as_op dist = par.bounds # interval and both lb, ub are finite if (isinstance(dist, Interval) and np.isfinite([dist.lb, dist.ub]).all()): return pm.Uniform(name, dist.lb, dist.ub) # no bounds elif (isinstance(dist, Interval) and np.isneginf(dist.lb) and np.isinf(dist.lb)): return pm.Flat(name) # half open uniform elif isinstance(dist, Interval) and not np.isfinite(dist.lb): return dist.ub - pm.HalfFlat(name) # half open uniform elif isinstance(dist, Interval) and not np.isfinite(dist.ub): return dist.lb + pm.HalfFlat(name) # it's a PDF if isinstance(dist, PDF): dist_gen = getattr(dist.rv, 'dist', None) if isinstance(dist.rv, stats.rv_continuous): dist_gen = dist.rv if isinstance(dist_gen, type(stats.uniform)): if hasattr(dist.rv, 'args'): p = pm.Uniform(name, dist.rv.args[0], dist.rv.args[1] + dist.rv.args[0]) else: p = pm.Uniform(name, 0, 1) return p # norm from scipy.stats if isinstance(dist_gen, type(stats.norm)): if hasattr(dist.rv, 'args'): p = pm.Normal(name, mu=dist.rv.args[0], sd=dist.rv.args[1]) else: p = pm.Normal(name, mu=0, sd=1) return p # not open, uniform, or normal, so fall back to DensityDist. d = as_op(itypes=[T.dscalar], otypes=[T.dscalar])(dist.logp) r = as_op(itypes=[T.dscalar], otypes=[T.dscalar])(dist.rvs) p = pm.DensityDist(name, d, random=r) return p
def fit(self, X, y, y_error=1, x_error=None, *, sample_kwargs={ 'draws': 1000, 'target_accept': 0.9 }): kwds = {} if self.kwds is not None: kwds.update(self.kwds) kwds['fit_intercept'] = False model = self._choose_regressor() self.clf_ = model(**kwds) self.fit_intercept = False if x_error is not None: x_error = np.atleast_2d(x_error) with pm.Model(): # slope and intercept of eta-ksi relation slope = pm.Flat('slope', shape=(X.shape[0], )) inter = pm.Flat('inter') # intrinsic scatter of eta-ksi relation int_std = pm.HalfFlat('int_std') # standard deviation of Gaussian that ksi are drawn from (assumed mean zero) tau = pm.HalfFlat('tau', shape=(X.shape[0], )) # intrinsic ksi mu = pm.Normal('mu', mu=0, sd=tau, shape=(X.shape[0], )) # Some wizzarding with the dimensions all around. ksi = pm.Normal('ksi', mu=mu, tau=tau, shape=X.T.shape) # intrinsic eta-ksi linear relation + intrinsic scatter eta = pm.Normal('eta', mu=(tt.dot(slope.T, ksi.T) + inter), sd=int_std, shape=y.shape) # observed xi, yi x = pm.Normal('xi', mu=ksi.T, sd=x_error, observed=X, shape=X.shape) y = pm.Normal('yi', mu=eta, sd=y_error, observed=y, shape=y.shape) self.trace = pm.sample(**sample_kwargs) # TODO big: make it optional to choose a way to define best # TODO quick: use np.histogramdd H2D, bins1, bins2 = np.histogram2d(self.trace['slope'][:, 0], self.trace['inter'], bins=50) w = np.where(H2D == H2D.max()) # choose the maximum posterior slope and intercept slope_best = bins1[w[0][0]] intercept_best = bins2[w[1][0]] self.clf_.coef_ = np.array([intercept_best, slope_best]) return self
def linear_bayesian_flat_prior(x, y, number_samples = 3000): '''Generates a Bayesian linear regression with half-flat priors gaussian likelihood Returns a dict with the model that can be used to compare, the trace and main plots''' # Set container result = dict.fromkeys(["model", "trace", "posterior_pred", "plot_param", "plot_data", "plot_uncertainty"], None) try : with pm.Model() as model: # Define priors # sigma = pm.HalfFlat('sigma') # intercept = pm.distributions.continuous.HalfFlat('Intercept') # beta_1 = pm.distributions.continuous.HalfFlat('x') sigma = pm.HalfFlat('sigma') intercept = pm.HalfFlat('Intercept') beta_1 = pm.HalfFlat('x') # Define likelihood likelihood = pm.Normal('y', mu = intercept + beta_1 * x, sigma=sigma, observed=y) # Inference! trace = pm.sample(number_samples , cores=2) # draw 3000 posterior samples using NUTS sampling result["trace"] = trace posterior_pred = pm.sample_posterior_predictive(trace) result["posterior_pred"] = posterior_pred result["model"] = model plot_param = plt.figure(figsize=(7, 7)) pm.traceplot(trace) plt.tight_layout() result["plot_param"] = plot_param plot_data = plt.figure(figsize=(7, 7)) plt.plot(x, y, 'x', label = 'data') pm.plot_posterior_predictive_glm(trace, samples=number_samples, label='posterior predictive regression lines', eval = np.linspace(0, np.max(x), 50)) plt.title('Posterior predictive regression lines') plt.legend(loc=0) plt.xlabel('x') plt.ylabel('y'); result["plot_data"] = plot_data return(result) except RuntimeError: return(np.NaN)
shape=len(N_samples)) #y = pm.Bernoulli('y', p=θ[group_idx], observed=data) y = pm.Binomial('y', p=theta, observed=G_samples, n=N_samples) trace = pm.sample(1000) #https://docs.pymc.io/notebooks/GLM-hierarchical-binominal-model.html def logp_ab(value): ''' prior density''' return tt.log(tt.pow(tt.sum(value), -5 / 2)) with pm.Model() as model: # Uninformative prior for alpha and beta ab = pm.HalfFlat('ab', shape=2, testval=np.asarray([1., 1.])) pm.Potential('p(a, b)', logp_ab(ab)) alpha = pm.Deterministic('alpha', ab[0]) beta = pm.Deterministic('beta', ab[1]) theta = pm.Beta('θ', alpha=alpha, beta=beta, shape=len(N_samples)) y = pm.Binomial('y', p=theta, observed=G_samples, n=N_samples) trace = pm.sample(1000) az.plot_trace(trace) plt.savefig('hbayes_binom_covid_trace.pdf', dpi=300) print(az.summary(trace)) axes = az.plot_forest(trace, var_names='θ', hdi_prob=0.95,
def main(input_dir, output_dir, dataset, model_type, n_samples, n_tune, target_accept, n_cores, seed, init, profile): '''Fit log-parabola model to DATASET. Parameters ---------- input_dir : [type] input directory containing subdirs for each instrument with dl3 data output_dir : [type] where to save the results. traces and two plots dataset : string telescope name model_type : string whether to use the profile likelihood ('wstat' or 'profile') or not ('full') n_samples : int number of samples to draw n_tune : int number of tuning steps target_accept : float target accept fraction for the pymc sampler n_cores : int number of cpu cores to use seed : int random seed init : string pymc init string profile : bool whether to output debugging/profiling information to the console Raises ------ NotImplementedError This does not yet work on the joint dataset. but thats good enough for me. ''' np.random.seed(seed) if dataset == 'joint': #TODO need to calculate mu_b for each observation independently. raise NotImplementedError('This is not implemented for the joint dataset yet.') # observations, lo, hi = load_joint_spectrum_observation(input_dir) else: p = os.path.join(input_dir, dataset) observations, lo, hi = load_spectrum_observations(p) prepare_output(output_dir) # TODO: this has to happen for every observation independently exposure_ratio = observations[0].alpha[0] # print(exposure_ratio) on_data, off_data = get_observed_counts(observations) integrator = init_integrators(observations) print('On Data') display_data(on_data) print('Off Data') display_data(off_data) print('--' * 30) print(f'Fitting data for {dataset} in {len(observations)} observations. ') print(f'Using {len(on_data)} bins with { on_data.sum()} counts in on region and {off_data.sum()} counts in off region.') print(f'Fit range is: {(lo, hi) * u.TeV}.') model = pm.Model(theano_config={'compute_test_value': 'ignore'}) with model: # amplitude = pm.TruncatedNormal('amplitude', mu=4, sd=1, lower=0.01, testval=4) # alpha = pm.TruncatedNormal('alpha', mu=2.5, sd=1, lower=0.00, testval=2.5) # beta = pm.TruncatedNormal('beta', mu=0.5, sd=0.5, lower=0.00000, testval=0.5) amplitude = pm.HalfFlat('amplitude', testval=4) alpha = pm.HalfFlat('alpha', testval=2.5) beta = pm.HalfFlat('beta', testval=0.5) mu_s = forward_fold_log_parabola_symbolic(integrator, amplitude, alpha, beta, observations) # mu_s = forward_fold_log_parabola_analytic(amplitude, alpha, beta, observations) if model_type == 'wstat': print('Building profiled likelihood model') mu_b = pm.Deterministic('mu_b', calc_mu_b(mu_s, on_data, off_data, exposure_ratio)) else: print('Building full likelihood model') mu_b = pm.HalfFlat('mu_b', shape=len(off_data)) pm.Poisson('background', mu=mu_b, observed=off_data, shape=len(off_data)) pm.Poisson('signal', mu=mu_s + exposure_ratio * mu_b, observed=on_data, shape=len(on_data)) print('--' * 30) print('Model debug information:') for RV in model.basic_RVs: print(RV.name, RV.logp(model.test_point)) if profile: model.profile(model.logpt).summary() print(model.check_test_point()) print('--' * 30) print('Plotting landscape:') fig, _ = plot_landscape(model, off_data) fig.savefig(os.path.join(output_dir, 'landscape.pdf')) print('--' * 30) print('Printing graphs:') theano.printing.pydotprint(mu_s, outfile=os.path.join(output_dir, 'graph_mu_s.pdf'), format='pdf', var_with_name_simple=True) theano.printing.pydotprint(mu_s + exposure_ratio * mu_b, outfile=os.path.join(output_dir, 'graph_n_on.pdf'), format='pdf', var_with_name_simple=True) print('--' * 30) print('Sampling likelihood:') with model: trace = pm.sample(n_samples, cores=n_cores, tune=n_tune, init=init, seed=[seed] * n_cores) print('--' * 30) print(f'Fit results for {dataset}') print(trace['amplitude'].mean(), trace['alpha'].mean(), trace['beta'].mean()) print(np.median(trace['amplitude']), np.median(trace['alpha']), np.median(trace['beta'])) print('--' * 30) # print('Plotting traces') # plt.figure() # varnames = ['amplitude', 'alpha', 'beta'] if model_type != 'full' else ['amplitude', 'alpha', 'beta', 'mu_b'] # pm.traceplot(trace, varnames=varnames) # plt.savefig(os.path.join(output_dir, 'traces.pdf')) p = os.path.join(output_dir, 'num_samples.txt') with open(p, "w") as text_file: text_file.write(f'\\num{{{n_samples}}}') p = os.path.join(output_dir, 'num_chains.txt') with open(p, "w") as text_file: text_file.write(f'\\num{{{n_cores}}}') p = os.path.join(output_dir, 'num_tune.txt') with open(p, "w") as text_file: text_file.write(f'\\num{{{n_tune}}}') plt.figure() pm.energyplot(trace) plt.savefig(os.path.join(output_dir, 'energy.pdf')) # plt.figure() # pm.autocorrplot(trace, burn=n_tune) # plt.savefig(os.path.join(output_dir, 'autocorr.pdf')) plt.figure() pm.forestplot(trace, varnames=['amplitude', 'alpha', 'beta']) plt.savefig(os.path.join(output_dir, 'forest.pdf')) trace_output = os.path.join(output_dir, 'traces') print(f'Saving traces to {trace_output}') with model: pm.save_trace(trace, trace_output, overwrite=True)
def test_half_flat(self): with pm.Model(): f = pm.HalfFlat('f') with pytest.raises(ValueError): f.random(1)
def dummy_model_unfold(): model = pm.Model(theano_config={"compute_test_value": "ignore"}) with model: pm.HalfFlat("mu_b", shape=2) pm.Lognormal("expected_counts", shape=2) return model
def main(input_dir, config_file, output_dir, dataset, model_type, tau, n_samples, n_tune, target_accept, n_cores, seed, init): prepare_output(output_dir) config = load_config(config_file, dataset) fit_range = config['fit_range'] path = os.path.join(input_dir, dataset) observations = load_data(path, config) e_true_bins = config['e_true_bins'] e_reco_bins = config['e_reco_bins'] # exposure_ratio = observations[0].alpha # from IPython import embed; embed() on_data, off_data, excess, exposure_ratio = get_observed_counts( observations, fit_range=fit_range, bins=e_reco_bins) print(f'Exposure ratio {exposure_ratio}') # from IPython import embed; embed() # print(f'On Data {on_data.shape}\n') # display_data(on_data) # print(f'\n\n Off Data {off_data.shape}\n') # display_data(off_data) print(f'Excess {excess.shape} \n') idx = np.searchsorted(e_reco_bins.to_value(u.TeV), fit_range.to_value(u.TeV)) lo, up = idx[0], idx[1] + 1 indices = np.argwhere(excess > 5) display_data(excess, mark_indices=indices, low_index=lo, high_index=up) print('--' * 30) print(f'Unfolding data for: {dataset.upper()}. ') # print(f'IRF with {len( config['e_true_bins'] ) - 1, len( config['e_reco_bins'] ) - 1}') print( f'Using {len(on_data)} bins with { on_data.sum()} counts in on region and {off_data.sum()} counts in off region.' ) area_scaling = 1 print(observations[0].aeff.data.data.to_value(u.km**2).astype(np.float32) * area_scaling) model = pm.Model(theano_config={'compute_test_value': 'ignore'}) with model: # mu_b = pm.TruncatedNormal('mu_b', shape=len(off_data), sd=5, mu=off_data, lower=0.01) # expected_counts = pm.Lognormal('expected_counts', shape=len(config['e_true_bins']) - 1, testval=10, sd=1) expected_counts = pm.TruncatedNormal('expected_counts', shape=len(e_true_bins) - 1, testval=0.5, mu=2, sd=50, lower=0.0001) # expected_counts = pm.HalfFlat('expected_counts', shape=len(e_true_bins) - 1, testval=10) # c = expected_counts / area_scaling mu_s = forward_fold(expected_counts, observations, fit_range=fit_range, area_scaling=area_scaling) if model_type == 'wstat': print('Building profiled likelihood model') mu_b = pm.Deterministic( 'mu_b', calc_mu_b(mu_s, on_data, off_data, exposure_ratio)) else: print('Building full likelihood model') mu_b = pm.HalfFlat('mu_b', shape=len(off_data)) # mu_b = pm.Lognormal('mu_b', shape=len(off_data), sd=5) pm.Poisson('background', mu=mu_b + 1E-5, observed=off_data) pm.Poisson('signal', mu=mu_s + exposure_ratio * mu_b + 1E-5, observed=on_data) print('--' * 30) print('Model debug information:') for RV in model.basic_RVs: print(RV.name, RV.logp(model.test_point)) print('--' * 30) print('Sampling likelihood:') with model: trace = pm.sample(n_samples, cores=n_cores, tune=n_tune, init=init, seed=[seed] * n_cores) trace_output = os.path.join(output_dir, 'traces') print(f'Saving traces to {trace_output}') with model: pm.save_trace(trace, trace_output, overwrite=True) print('--' * 30) print('Plotting result') # print(area_scaling) fig, [ax1, ax2] = plt.subplots(2, 1, figsize=(10, 7), sharex=True, gridspec_kw={'height_ratios': [3, 1]}) plot_unfolding_result(trace, bins=e_true_bins, area_scaling=area_scaling, fit_range=fit_range, ax=ax1) plot_excees(excess, bins=config['e_reco_bins'], ax=ax2) plt.savefig(os.path.join(output_dir, 'result.pdf')) print('--' * 30) print('Plotting Diagnostics') print(pm.summary(trace).round(2)) # plt.figure() # pm.traceplot(trace) # plt.savefig(os.path.join(output_dir, 'traces.pdf')) plt.figure() pm.energyplot(trace) plt.savefig(os.path.join(output_dir, 'energy.pdf')) # try: # plt.figure() # pm.autocorrplot(trace, burn=n_tune) # plt.savefig(os.path.join(output_dir, 'autocorr.pdf')) # except: # print('Could not plot auttocorrelation') plt.figure() pm.forestplot(trace) plt.savefig(os.path.join(output_dir, 'forest.pdf')) p = os.path.join(output_dir, 'num_samples.txt') with open(p, "w") as text_file: text_file.write(f'\\num{{{n_samples}}}') p = os.path.join(output_dir, 'num_chains.txt') with open(p, "w") as text_file: text_file.write(f'\\num{{{n_cores}}}') p = os.path.join(output_dir, 'num_tune.txt') with open(p, "w") as text_file: text_file.write(f'\\num{{{n_tune}}}')