points = (5, 20) for idx, ps in enumerate(points): p_grid, posterior = posterior_grid_approx(ps, w, n) ax[idx].plot(p_grid, posterior, "o-", label=f"success = {w}\ntosses = {n}") ax[idx].set_xlabel("probability of water") ax[idx].set_ylabel("posterior probability") ax[idx].set_title(f"{ps} points") ax[idx].legend(loc=0) # %% data = np.repeat((0, 1), (3, 6)) # %% # %% with pm.Model() as normal_approximation: p = pm.Uniform("p", 0, 1) w = pm.Binomial("w", n=len(data), p=p, observed=data.sum()) mean_q = pm.find_MAP() std_q = ((1 / pm.find_hessian(mean_q, vars=[p]))**0.5)[0] mean_q["p"], std_q # %% w, n = 6, 9 x = np.linspace(0, 1, 100) plt.plot(x, stats.beta.pdf(x, w + 1, n - w + 1), label="True posterior") # quadratic approximation plt.plot(x, stats.norm.pdf(x, mean_q["p"], std_q), label="Quadratic approximation") plt.legend(loc=0)
def __init__(self, processes, input_defs, param_defs, flow_observations=None, input_observations=None, inflow_observations=None): self.processes = processes self.possible_inputs = possible_inputs = sorted(list( input_defs.keys())) input_max = [input_defs[k] for k in possible_inputs] self.param_defs = param_defs with pm.Model() as self.model: # Inputs # Lognormal seems too biased towards very small inputs; try half-Cauchy or similar? inputs = pm.Uniform('inputs', lower=np.zeros_like(input_max), upper=input_max, shape=len(input_max)) # Params for each process # params = pm.Normal('params', mu=param_means, sd=param_stds, shape=len(param_means)) process_params = { pid: process.param_rv(pid, param_defs.get(pid)) for pid, process in processes.items() } # transfer_coeffs transfer_coeffs, all_inputs = self._build_matrices( process_params, inputs) transfer_coeffs = pm.Deterministic('TCs_coeffs', transfer_coeffs) process_throughputs = pm.Deterministic( 'X', T.dot(matrix_inverse(T.eye(len(processes)) - transfer_coeffs), all_inputs)) # Flows flows = pm.Deterministic( 'F', transfer_coeffs.T * process_throughputs[:, None]) # Observations - flows if flow_observations is not None: flow_obs, flow_data, flow_stds = self._flow_observations( flow_observations) Fobs = pm.Deterministic('Fobs', T.tensordot(flow_obs, flows, 2)) pm.Normal('FD', mu=Fobs, sd=flow_stds, observed=flow_data) # Observations - inputs if input_observations is not None: input_obs, input_data, input_stds = self._input_observations( input_observations) Iobs = pm.Deterministic('Iobs', T.dot(input_obs, all_inputs)) pm.Normal('ID', mu=Iobs, sd=input_stds, observed=input_data) # Observations - ratios if inflow_observations is not None: inflow_obs, inflow_data, inflow_stds = self._flow_observations( inflow_observations) inflow_fractions = flows / process_throughputs[None, :] Iratioobs = pm.Deterministic( 'IFobs', T.tensordot(inflow_obs, inflow_fractions, 2)) pm.Normal('IFD', mu=Iratioobs, sd=inflow_stds, observed=inflow_data)
# Re-center data at mean, to reduce autocorrelation in MCMC sampling. # Standardize (divide by SD) to make initialization easier. x_m = np.mean(x) x_sd = np.std(x) y_m = np.mean(y) y_sd = np.std(y) zx = (x - x_m) / x_sd zy = (y - y_m) / y_sd tdf_gain = 1 # 1 for low-baised tdf, 100 for high-biased tdf # THE MODEL with pm.Model() as model: # define the priors udf = pm.Uniform('udf', 0, 1) tdf = 1 - tdf_gain * pm.log(1 - udf) # tdf in [1,Inf). tau = pm.Gamma('tau', 0.001, 0.001) beta0 = pm.Normal('beta0', mu=0, tau=1.0E-12) beta1 = pm.Normal('beta1', mu=0, tau=1.0E-12) mu = beta0 + beta1 * zx # define the likelihood yl = pm.T('yl', mu=mu, lam=tau, nu=tdf, observed=zy) # Generate a MCMC chain start = pm.find_MAP() step = pm.Metropolis() trace = pm.sample(20000, step, start, progressbar=False) # EXAMINE THE RESULTS burnin = 1000 thin = 10
def flatten_with_gp(lc, break_tolerance, min_period, bin_factor=None, return_trend=False): """ Detrend the flux from an alderaan LiteCurve using a celerite RotationTerm GP kernel The mean function of each uninterrupted segment of flux is modeled as an exponential Fmean = F0*(1+A*exp(-t/tau)) Parameters ---------- lc : alderaan.LiteCurve must have .time, .flux and .mask attributes break_tolerance : int number of cadences considered a large gap in time min_period : float lower bound on primary period for RotationTerm kernel return_trend : bool (default=False) if True, return the trend inferred from the GP fit Returns ------- lc : alderaan.LiteCurve LiteCurve with trend removed from lc.flux gp_trend : ndarray trend inferred from GP fit (only returned if return_trend == True) """ # find gaps/breaks/jumps in the data gaps = identify_gaps(lc, break_tolerance=break_tolerance) gaps[-1] -= 1 # initialize data arrays and lists of segments gp_time = np.array(lc.time, dtype="float64") gp_flux = np.array(lc.flux, dtype="float64") gp_mask = np.sum(lc.mask, 0) == 0 time_segs = [] flux_segs = [] mask_segs = [] for i in range(len(gaps) - 1): time_segs.append(gp_time[gaps[i]:gaps[i + 1]]) flux_segs.append(gp_flux[gaps[i]:gaps[i + 1]]) mask_segs.append(gp_mask[gaps[i]:gaps[i + 1]]) mean_flux = [] approx_var = [] for i in range(len(gaps) - 1): m = mask_segs[i] mean_flux.append(np.mean(flux_segs[i][m])) approx_var.append(np.var(flux_segs[i] - sig.medfilt(flux_segs[i], 13))) # put segments into groups of ten nseg = len(time_segs) ngroup = int(np.ceil(nseg / 10)) seg_groups = np.array(np.arange(ngroup + 1) * np.ceil(nseg / ngroup), dtype="int") seg_groups[-1] = len(gaps) - 1 # identify rotation period to initialize GP ls_estimate = exo.estimators.lomb_scargle_estimator(gp_time, gp_flux, max_peaks=1, \ min_period=min_period, max_period=91.0, \ samples_per_peak=50) peak_per = ls_estimate["peaks"][0]["period"] # set up lists to hold trend info trend_maps = [None] * ngroup # optimize the GP for each group of segments for j in range(ngroup): sg0 = seg_groups[j] sg1 = seg_groups[j + 1] nuse = sg1 - sg0 with pm.Model() as trend_model: log_amp = pm.Normal("log_amp", mu=np.log(np.std(gp_flux)), sd=5) log_per_off = pm.Normal("log_per_off", mu=0, sd=5, testval=np.log(peak_per - min_period)) log_Q0_off = pm.Normal("log_Q0_off", mu=0, sd=10) log_deltaQ = pm.Normal("log_deltaQ", mu=2, sd=10) mix = pm.Uniform("mix", lower=0, upper=1) P = pm.Deterministic("P", min_period + T.exp(log_per_off)) Q0 = pm.Deterministic("Q0", 1 / T.sqrt(2) + T.exp(log_Q0_off)) kernel = exo.gp.terms.RotationTerm(log_amp=log_amp, period=P, Q0=Q0, log_deltaQ=log_deltaQ, mix=mix) # exponential trend logtau = pm.Normal("logtau", mu=np.log(3) * np.ones(nuse), sd=5 * np.ones(nuse), shape=nuse) exp_amp = pm.Normal('exp_amp', mu=np.zeros(nuse), sd=np.std(gp_flux) * np.ones(nuse), shape=nuse) # nuissance parameters per segment flux0 = pm.Normal('flux0', mu=np.array(mean_flux[sg0:sg1]), sd=np.std(gp_flux) * np.ones(nuse), shape=nuse) logvar = pm.Normal('logvar', mu=np.log(approx_var[sg0:sg1]), sd=10 * np.ones(nuse), shape=nuse) # now set up the GP gp = [None] * nuse gp_pred = [None] * nuse for i in range(nuse): m = mask_segs[sg0 + i] t = time_segs[sg0 + i][m] - time_segs[sg0 + i][m][0] ramp = 1 + exp_amp[i] * np.exp(-t / np.exp(logtau[i])) gp[i] = exo.gp.GP( kernel, time_segs[sg0 + i][m], T.exp(logvar[i]) * T.ones(len(time_segs[sg0 + i][m]))) pm.Potential( 'obs_{0}'.format(i), gp[i].log_likelihood(flux_segs[sg0 + i][m] - flux0[i] * ramp)) with trend_model: trend_maps[j] = exo.optimize(start=trend_model.test_point) # set up mean and variance vectors gp_mean = np.ones_like(gp_flux) gp_var = np.ones_like(gp_flux) for i in range(nseg): j = np.argmin(seg_groups <= i) - 1 g0 = gaps[i] g1 = gaps[i + 1] F0_ = trend_maps[j]["flux0"][i - seg_groups[j]] A_ = trend_maps[j]["exp_amp"][i - seg_groups[j]] tau_ = np.exp(trend_maps[j]["logtau"][i - seg_groups[j]]) t_ = gp_time[g0:g1] - gp_time[g0] gp_mean[g0:g1] = F0_ * (1 + A_ * np.exp(-t_ / tau_)) gp_var[g0:g1] = np.ones(g1 - g0) * np.exp( trend_maps[j]["logvar"][i - seg_groups[j]]) # increase variance for cadences in transit (yes, this is hacky, but it works) # using gp.predict() inside the initial model was crashing jupyter, making debugging slow gp_var[~gp_mask] *= 1e12 # now evaluate the GP to get the final trend gp_trend = np.zeros_like(gp_flux) for j in range(ngroup): start = gaps[seg_groups[j]] end = gaps[seg_groups[j + 1]] m = gp_mask[start:end] with pm.Model() as trend_model: log_amp = trend_maps[j]["log_amp"] P = trend_maps[j]["P"] Q0 = trend_maps[j]["Q0"] log_deltaQ = trend_maps[j]["log_deltaQ"] mix = trend_maps[j]["mix"] kernel = exo.gp.terms.RotationTerm(log_amp=log_amp, period=P, Q0=Q0, log_deltaQ=log_deltaQ, mix=mix) gp = exo.gp.GP(kernel, gp_time[start:end], gp_var[start:end]) gp.log_likelihood(gp_flux[start:end] - gp_mean[start:end]) gp_trend[start:end] = gp.predict().eval() + gp_mean[start:end] # now remove the trend lc.flux = lc.flux - gp_trend + 1.0 # return results if return_trend: return lc, gp_trend else: return lc
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], sigma=dist.rv.args[1]) else: p = pm.Normal(name, mu=0, sigma=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
azi = data['azi'] * dg2rd UEast = np.cos(azi) * np.sin(inc) # East component of LOS UNorth = np.sin(azi) * np.sin(inc) # North unit vector UVert = np.cos(inc) # Vertical unit vector U = data['los'] #Setting some bounds xmin = np.min(x) xmax = np.max(x) ymin = np.min(y) ymax = np.max(y) #Setup inversion with pm.Model() as model: strExp = pm.Uniform('strExp', lower=12, upper=18) strSource = pm.Deterministic('strSource', -10**strExp) xSource = pm.Uniform('xSource', lower=xmin, upper=xmax) ySource = pm.Uniform('ySource', lower=ymin, upper=ymax) depthSource = pm.Uniform('depthSource', lower=1000, upper=5000) R = tt.sqrt((x - xSource)**2 + (y - ySource)**2 + depthSource**2) coeff_east = (x - xSource) / R**3 * elastic_constant coeff_north = (y - ySource) / R**3 * elastic_constant coeff_up = depthSource / R**3 * elastic_constant east = strSource * coeff_east north = strSource * coeff_north vert = strSource * coeff_up Ulos = east * UEast + north * UNorth + vert * UVert UObs = mv.MvNormal('Uobs', mu=Ulos, cov=covariance, observed=U) step = pm.Metropolis() trace = pm.sample(Niter, step)
def run(self): self.validateinput() data = self.data data = self.fluctuate(data) if self.rndseed >= 0 else data # unpack background dictionaries backgroundkeys = self.backgroundsyst.keys() nbckg = len(backgroundkeys) if nbckg > 0: backgrounds = array( [self.background[key] for key in backgroundkeys]) backgroundnormsysts = array( [self.backgroundsyst[key] for key in backgroundkeys]) # unpack object systematics dictionary objsystkeys = self.objsyst['signal'].keys() nobjsyst = len(objsystkeys) if nobjsyst > 0: signalobjsysts = array( [self.objsyst['signal'][key] for key in objsystkeys]) if nbckg > 0: backgroundobjsysts = array([]) backgroundobjsysts = array([[ self.objsyst['background'][syst][bckg] for syst in objsystkeys ] for bckg in backgroundkeys]) recodim = len(data) resmat = self.response truthdim = len(resmat) model = mc.Model() from .priors import wrapper with model: truth = wrapper(priorname=self.prior, low=self.lower, up=self.upper, other_args=self.priorparams) if nbckg > 0: bckgnuisances = [] for name, err in zip(backgroundkeys, backgroundnormsysts): if err < 0.: bckgnuisances.append( mc.Uniform('norm_%s' % name, lower=0., upper=3.)) else: BoundedNormal = mc.Bound( mc.Normal, lower=(-1.0 / err if err > 0.0 else -inf)) bckgnuisances.append( BoundedNormal('gaus_%s' % name, mu=0., tau=1.0)) bckgnuisances = mc.math.stack(bckgnuisances) if nobjsyst > 0: objnuisances = [ mc.Normal( 'gaus_%s' % name, mu=0., tau=1.0 #, #observed=(True if self.systfixsigma!=0 else False) ) for name in objsystkeys ] objnuisances = mc.math.stack(objnuisances) # define potential to constrain truth spectrum if self.regularization: truthpot = self.regularization.getpotential(truth) #This is where the FBU method is actually implemented def unfold(): smearbckg = 1. if nbckg > 0: bckgnormerr = [(-1. + nuis) / nuis if berr < 0. else berr for berr, nuis in zip( backgroundnormsysts, bckgnuisances)] bckgnormerr = mc.math.stack(bckgnormerr) smearedbackgrounds = backgrounds if nobjsyst > 0: smearbckg = smearbckg + theano.dot( objnuisances, backgroundobjsysts) smearedbackgrounds = backgrounds * smearbckg bckg = theano.dot(1. + bckgnuisances * bckgnormerr, smearedbackgrounds) tresmat = array(resmat) reco = theano.dot(truth, tresmat) out = reco if nobjsyst > 0: smear = 1. + theano.dot(objnuisances, signalobjsysts) out = reco * smear if nbckg > 0: out = bckg + out return out unfolded = mc.Poisson('unfolded', mu=unfold(), observed=array(data)) trace = mc.sample(self.nMCMC, tune=self.nTune, target_accept=self.target_accept) self.trace = [trace['truth%d' % bin][:] for bin in range(truthdim)] self.nuisancestrace = {} if nbckg > 0: for name, err in zip(backgroundkeys, backgroundnormsysts): if err < 0.: self.nuisancestrace[name] = trace['norm_%s' % name][:] if err > 0.: self.nuisancestrace[name] = trace['gaus_%s' % name][:] for name in objsystkeys: if self.systfixsigma == 0.: self.nuisancestrace[name] = trace['gaus_%s' % name][:] if self.monitoring: import monitoring monitoring.plot(self.name + '_monitoring', data, backgrounds, resmat, self.trace, self.nuisancestrace, self.lower, self.upper)
def get_abs_m(overwrite=0): # overwrite: whether to overwrite the pickle (~20s sampling) datestr = '20200624' cleanrvpath = os.path.join(DATADIR, 'spectra', 'RVs_{}_clean.csv'.format(datestr)) df = pd.read_csv(cleanrvpath) # NOTE: the FEROS data contain all the information about the long-term # trend. sel = (df.tel == "FEROS") df = df[sel] df = df.sort_values(by='time') delta_t = (df.time.max() - df.time.min()) t0 = df.time.min() + delta_t / 2 df['x'] = df['time'] - t0 # np.nanmean(df['time']) df['y'] = df['mnvel'] - np.nanmean(df['mnvel']) df['y_err'] = df['errvel'] force_err = 100 print('WRN: inflating error bars to account for rot jitter') print(f'{df.y_err.median()} to {force_err}') df.y_err = force_err pklpath = os.path.join(rdir, 'rvlim_method2.pkl') if os.path.exists(pklpath) and overwrite: os.remove(pklpath) # y = mx + c if not os.path.exists(pklpath): with pm.Model() as model: # Define priors c = pm.Uniform('c', lower=-100, upper=100) m = pm.Uniform('m', lower=-100, upper=100) abs_m = pm.Deterministic("abs_m", pm.math.abs_(m)) # Define likelihood # Here Y ~ N(Xβ, σ^2), for β the coefficients of the model. Note though # the error bars are not _observed_ in this case; they are part of the # model! likelihood = pm.Normal('y', mu=m * nparr(df.x) + c, sigma=nparr(df.y_err), observed=nparr(df.y)) # Inference! draw 1000 posterior samples using NUTS sampling n_samples = 6000 trace = pm.sample(n_samples, cores=16) with open(pklpath, 'wb') as buff: pickle.dump({'model': model, 'trace': trace}, buff) else: d = pickle.load(open(pklpath, 'rb')) model, trace = d['model'], d['trace'] # corner trace_df = trace_to_dataframe(trace) fig = corner.corner(trace_df, quantiles=[0.16, 0.5, 0.84], show_titles=True) fig.savefig(os.path.join(rdir, 'corner.png')) # data + model plt.close('all') plt.figure(figsize=(7, 7)) plt.scatter(df.x, df.y, label='data', zorder=2, color='k') plt.errorbar(df.x, df.y, yerr=df.y_err, ecolor='k', elinewidth=1, capsize=2, zorder=2, ls='none') N_samples = 100 lm = lambda x, sample: sample['m'] * x + sample['c'] for rand_loc in np.random.randint(0, len(trace), N_samples): rand_sample = trace[rand_loc] plt.plot(nparr(df.x), lm(nparr(df.x), rand_sample), zorder=1, alpha=0.5, color='C0') plt.legend(loc=0) plt.xlabel('time [d]') plt.ylabel('rv [m/s]') plt.savefig(os.path.join(rdir, 'datamodel.png')) plt.close('all') printparams = ['c', 'm', 'abs_m'] print(42 * '-') for p in printparams: med = np.percentile(trace[p], 50) up = np.percentile(trace[p], 84) low = np.percentile(trace[p], 36) threesig = np.percentile(trace[p], 99.7) print(f'{p} : {med:.3f} +{up-med:.3f} -{med-low:.3f}') print(f'{p} 99.7: {threesig:.3f}') print(42 * '-') absm_threesig = threesig * u.m / u.s / u.day delta_time = df.time.max() - df.time.min() return absm_threesig, delta_time
import pymc3 as pm import numpy as np import matplotlib.pyplot as plt import pandas as pd import theano.tensor as tt dataBB = pd.read_csv(pm.get_data('efron-morris-75-data.tsv'), sep="\t") at_bats, hits = dataBB[['At-Bats', 'Hits']].values.T #%% N = len(hits) with pm.Model() as baseball_model: phi = pm.Uniform('phi', lower=0.0, upper=1.0) kappa_log = pm.Exponential('kappa_log', lam=1.5) kappa = pm.Deterministic('kappa', tt.exp(kappa_log)) thetas = pm.Beta('thetas', alpha=phi * kappa, beta=(1.0 - phi) * kappa, shape=N) y = pm.Binomial('y', n=at_bats, p=thetas, observed=hits) #%% with baseball_model: theta_new = pm.Beta('theta_new',
def _test_pymc3_model(pymc3_model, x, y): named_vars = pymc3_model.named_vars for name in ["bperp", "theta", "logs"]: if name not in named_vars: raise ValueError("Variable {0} missing from model".format(name)) if name + "_interval__" not in named_vars: raise ValueError( "Variable {0} should be a pm.Uniform distribution".format( name)) for name in ["m", "b"]: if name not in named_vars: raise ValueError( "pm.Deterministic variable {0} missing from model".format( name)) observed = [] for k, v in named_vars.items(): if isinstance(v, pm.model.ObservedRV): observed.append((k, v)) if len(observed) != 1: raise ValueError( "There should be exactly one observed variable, not {0}".format( len(observed))) with pm.Model() as pymc3_model_ref: bperp = pm.Uniform("bperp", lower=-10, upper=10) theta = pm.Uniform("theta", lower=-0.5 * np.pi, upper=0.5 * np.pi) logs = pm.Uniform("logs", lower=-10, upper=10) m = pm.Deterministic("m", pm.math.tan(theta)) b = pm.Deterministic("b", bperp / pm.math.cos(theta)) model = m * x + b pm.Normal("loglike", mu=model, sd=pm.math.exp(logs), observed=y) varlist_ref = pymc3_model_ref.unobserved_RVs names_ref = [v.name for v in varlist_ref] func_ref = get_theano_function_for_var(varlist_ref, model=pymc3_model_ref) varlist_impl = pymc3_model.unobserved_RVs names_impl = [v.name for v in varlist_impl] func_impl = get_theano_function_for_var(varlist_impl, model=pymc3_model) for vec in product( np.linspace(-100, 100, 5), np.linspace(-100, 100, 10), np.linspace(-100, 100, 12), ): args_ref = get_args_for_theano_function( { "bperp_interval__": vec[0], "theta_interval__": vec[1], "logs_interval__": vec[2], }, model=pymc3_model_ref, ) args_impl = get_args_for_theano_function( { "bperp_interval__": vec[0], "theta_interval__": vec[1], "logs_interval__": vec[2], }, model=pymc3_model, ) ref = dict(zip(names_ref, func_ref(*args_ref))) impl = dict(zip(names_impl, func_impl(*args_impl))) for k, v in ref.items(): if k not in impl: raise ValueError("Parameter {0} not in model".format(k)) if not np.allclose(v, impl[k]): raise ValueError( "Invalid calculation of parameter {0}".format(k))
model3=DifferentialEquation( func = SI_diffeq, # what is the differential equation? times = time_range, # what is the time grid for numerical integration? n_states = 2, # what is the dimensionality of the system? n_theta = 1, # how many parameters are there? # t0 = 0 # are we starting at the beginning? ) for # First, fit for model w/o detection rate with pm.Model() as mod: # Set priors beta = pm.Uniform('beta', 0, upper=.000001) # from literature #beta=pm.Lognormal('beta', mu=.001, sigma=1) #beta=pm.Uniform('beta', lower=0, upper=.00001) #lam = pm.Uniform('lam', lower=0.05, upper = .15) # from literature #tau = pm.Uniform('tau', lower=1E-3, upper=100) # from literature... 1/tau is var = noise in data #sigma = pm.HalfCauchy('sigma', 1, shape=3) # Implement numerical integration solution = model3(y0=X.T[0], theta=[beta]) # Likelihood # May want to come back and use Negative Binomial distribution # May need to adjust the prior distribution for the mean... # Since Poisson distribution has mean=var, can't explore var of data with Bayesian Inf #x_obs =pm.Lognormal('x_obs', mu=solution), sd=sigma, observed = X.T) x_obs=pm.Poisson('x_obs', mu=solution, observed = X.T) # Trace and MC
def _fit_growth(self, prior: bool = True) -> any: """Fit the growth component.""" s = [ self.data.ix[(self.data["ds"] - i).abs().argsort()[:1]].index[0] for i in self.changepoints ] g = self.priors["growth"] if prior else self.trace[ self.priors_names["growth"]] x = (np.arange(len(self.data)) if prior else np.array([np.arange(len(self.data))] * len(g)).T) if len(self.changepoints): d = (self.priors["changepoints"] if prior else [ self.trace[self.priors_names["changepoints"]][:, i] for i in range(len(s)) ]) else: d = [] regression = x * g if s and d: if prior: total = len(self.data) if (self.auto_changepoints ): # Overwrite changepoints with a uniform prior with self.model: s = pm.Uniform("s", 0, total, shape=len(self.changepoints)) piecewise_regression, _ = theano.scan( fn=lambda x: tt.concatenate( [tt.arange(x) * 0, tt.arange(total - x)]), sequences=[s], ) piecewise_regression = (piecewise_regression.T * d.dimshuffle("x", 0)).sum(axis=-1) else: base_piecewise_regression = [] for i in s: if i > 0: local_x = x.copy()[:-i] local_x = np.concatenate([ np.zeros(i) if prior else np.zeros( (i, local_x.shape[1])), local_x, ]) base_piecewise_regression.append(local_x) piecewise_regression = np.array(base_piecewise_regression) piecewise_regression = (piecewise_regression.T * d.dimshuffle("x", 0)).sum(axis=-1) else: base_piecewise_regression = [] for i in s: local_x = x.copy()[:-i] local_x = np.concatenate([ np.zeros(i) if prior else np.zeros( (i, local_x.shape[1])), local_x, ]) base_piecewise_regression.append(local_x) piecewise_regression = np.array(base_piecewise_regression) d = np.array(d) regression_pieces = [ piecewise_regression[i] * d[i] for i in range(len(s)) ] piecewise_regression = np.sum( [piece for piece in regression_pieces if len(piece)], axis=0) regression = piecewise_regression return regression
def build_biallelic_model6(g, n, s): # EXPERIMENTAL: Observations overdispersed as a BetaBinom w/ concentrations # 10. a = 2 with pm.Model() as model: # Fraction pi = pm.Dirichlet( 'pi', a=np.ones(s), shape=(n, s), transform=stick_breaking, ) pi_hyper = pm.Data('pi_hyper', value=0.0) pm.Potential('heterogeneity_penalty', -(pm.math.sqrt(pi).sum(0).sum()**2) * pi_hyper) rho_hyper = pm.Data('rho_hyper', value=0.0) pm.Potential('diversity_penalty', -(pm.math.sqrt(pi.sum(0)).sum()**2) * rho_hyper) # Genotype gamma_ = pm.Uniform('gamma_', 0, 1, shape=(g * s, 1)) gamma = pm.Deterministic( 'gamma', (pm.math.concatenate([gamma_, 1 - gamma_], axis=1).reshape( (g, s, a)))) gamma_hyper = pm.Data('gamma_hyper', value=0.0) pm.Potential( 'ambiguity_penalty', -((pm.math.sqrt(gamma).sum(2)**2).sum(0) * pi.sum(0)).sum(0) * gamma_hyper) # Product of fraction and genotype true_p = pm.Deterministic('true_p', pm.math.dot(pi, gamma)) # Sequencing error epsilon_hyper = pm.Data('epsilon_hyper', value=100) epsilon = pm.Beta('epsilon', alpha=2, beta=epsilon_hyper, shape=n) epsilon_ = epsilon.reshape((n, 1, 1)) err_base_prob = tt.ones((n, g, a)) / a p_with_error = (true_p * (1 - epsilon_)) + (err_base_prob * epsilon_) # Observation _p = p_with_error.reshape((-1, a))[:, 0] # Overdispersion term # alpha = pm.Gamma('alpha', mu=100, sigma=5) # TODO: Figure out how to also fit this term. # FIXME: Do I want the default to be a valid value? # Realistic or close to asymptotic? alpha = pm.Data('alpha', value=1000) # alpha = pm.Gamma('alpha', mu=100, sigma=5) observed = pm.Data('observed', value=np.empty((g * n, a))) pm.BetaBinomial('data', alpha=_p * alpha, beta=(1 - _p) * alpha, n=observed.reshape((-1, a)).sum(1), observed=observed[:, 0]) return model
def build_biallelic_model4(g, n, s): # EXPERIMENTAL: Underlying allele freqs overdispersed before errors. a = 2 with pm.Model() as model: # Fraction pi = pm.Dirichlet( 'pi', a=np.ones(s), shape=(n, s), transform=stick_breaking, ) pi_hyper = pm.Data('pi_hyper', value=0.0) pm.Potential('heterogeneity_penalty', -(pm.math.sqrt(pi).sum(0).sum()**2) * pi_hyper) rho_hyper = pm.Data('rho_hyper', value=0.0) pm.Potential('diversity_penalty', -(pm.math.sqrt(pi.sum(0)).sum()**2) * rho_hyper) # Genotype gamma_ = pm.Uniform('gamma_', 0, 1, shape=(g * s, 1)) gamma = pm.Deterministic( 'gamma', (pm.math.concatenate([gamma_, 1 - gamma_], axis=1).reshape( (g, s, a)))) gamma_hyper = pm.Data('gamma_hyper', value=0.0) pm.Potential( 'ambiguity_penalty', -(pm.math.sqrt(gamma).sum(2)**2).sum(0).sum(0) * gamma_hyper) # Product of fraction and genotype true_p = pm.Deterministic('true_p', pm.math.dot(pi, gamma)) # Overdispersion term # TODO: Consider making it different between samples. How to shape? alpha = pm.ChiSquared('alpha', nu=50) _true_p = true_p.reshape((-1, a))[:, 0] _true_q = 1 - _true_p overdispersed_p_ = pm.Beta('overdispersed_p_', alpha=_true_p * alpha, beta=_true_q * alpha, shape=(n * g, )) overdispersed_p = pm.Deterministic( 'overdispersed_p', pm.math.concatenate([ overdispersed_p_.reshape( (-1, 1)), 1 - overdispersed_p_.reshape((-1, 1)) ], axis=1).reshape((n, g, a))) # Sequencing error # epsilon_hyper = pm.Gamma('epsilon_hyper', alpha=100, beta=1) epsilon_hyper = pm.Data('epsilon_hyper', value=100) epsilon = pm.Beta('epsilon', alpha=2, beta=epsilon_hyper, shape=n) epsilon_ = epsilon.reshape((n, 1, 1)) p_with_error = (overdispersed_p * (1 - epsilon_) + (1 - overdispersed_p) * (epsilon_ / (a - 1))) # Observation # _p = p_with_error.reshape((-1, a))[:,0] # _q = 1 - _p observed = pm.Data('observed', value=np.empty((g * n, a))) pm.Binomial('data', p=p_with_error.reshape((-1, a))[:, 0], n=observed.reshape((-1, a)).sum(1), observed=observed[:, 0]) return model
def nLost(data): lost = [0] for i in range(1, len(data)): lost.append(data[i - 1] - data[i]) return lost q = 10 exampleDataNLost = nLost(exampleData) n = len(exampleData[0:q]) data = np.asarray((exampleData[0:q], exampleDataNLost[0:q])) with pm.Model() as BdWwithcfromNorm: alpha = pm.Uniform('alpha', 0.0001, 1000.0, testval=1.0) beta = pm.Uniform('beta', 0.0001, 1000.0, testval=1.0) # If c=1, the dW collapses to a geometric distribution. We assume # that in a usual case, customer survival probability normally # stay the same over time. # If mu = 1.5 we get exactly the same sampling results as if # we had used a uniform prior. The result is slightly better than # defining a N(1,None) variable. c = pm.Normal('c', mu=0.5, testval=1.0) p = [0.] * n s = [1.] * n logB = tt.gamma(alpha + beta) / tt.gamma(beta) for t in range(1, n): pt1 = tt.gamma(beta + (t - 1)**c) / tt.gamma(beta + alpha + (t - 1)**c) pt2 = tt.gamma(beta + t**c) / tt.gamma(beta + alpha + t**c)
# MK1 = A # MK2 = B mk1 = 26751 mk1Kills = 183 mk1p = mk1Kills / mk1 mk2 = 27079 mk2Kills = 222 mk2p = mk2Kills / mk2 observations_mk1 = [0] * (mk1 - mk1Kills) + [1] * mk1Kills random.shuffle(observations_mk1) observations_mk2 = [0] * (mk2 - mk2Kills) + [1] * mk2Kills random.shuffle(observations_mk2) with pm.Model() as model: mk1dist = pm.Uniform("mk1", 0, 1) mk2dist = pm.Uniform("mk2", 0, 1) delta = pm.Deterministic("delta", mk1dist - mk2dist) obs_mk1 = pm.Bernoulli("obs_mk1", mk1dist, observed=observations_mk1) obs_mk2 = pm.Bernoulli("obs_mk2", mk2dist, observed=observations_mk2) step = pm.Metropolis() trace = pm.sample(20000, step=step) burned_trace = trace[1000:] p_mk1_samples = burned_trace["mk1"] p_mk2_samples = burned_trace["mk2"] delta_samples = burned_trace["delta"] pm.traceplot(trace) print("Probability MK2 is DEADLIER than MK1: %.3f" % np.mean(delta_samples < 0))
trace_thick = trace trace_thick_varnames = ['Thickness'] elif thick_obs == 0: displacement_samples = [] for i in range(numfaults): with pm.Model() as model: logb_dist = pm.Normal('logb_dist', mu=logb_mean, sd=logb_std) m_dist = pm.Normal('m_dist', mu=m_mean, sd=m_std) displacement_dist = pm.Uniform('Displacement', lower=displacement_lower, upper=displacement_upper) thickness_dist = pm.Deterministic( 'Thickness', 10**(m_dist * np.log10(displacement_dist) + logb_dist) * CoreVsZone) trace = pm.sample(samples, tune=2000, cores=1) thickness = trace['Thickness'][0:samples] displacement_samples.append(trace['Displacement'][0:samples]) thicknesses[:, i] = thickness trace_thick = trace
y = nsum(effects_a[group, :] * predictors, 1) + random.normal(size=(n_observed)) model = pm.Model() with model: # m_g ~ N(0, .1) group_effects = pm.Normal("group_effects", 0, .1, shape=(n_group_predictors, n_predictors)) gp = pm.Normal("gp", 0, .1, shape=(n_groups, 1)) # gp = group_predictors # sg ~ Uniform(.05, 10) sg = pm.Uniform("sg", .05, 10, testval=2.) # m ~ N(mg * pg, sg) effects = pm.Normal("effects", T.dot(gp, group_effects), sg**-2, shape=(n_groups, n_predictors)) s = pm.Uniform("s", .01, 10, shape=n_groups) g = T.constant(group) # y ~ Normal(m[g] * p, s) mu_est = pm.Deterministic("mu_est", T.sum(effects[g] * predictors, 1)) yd = pm.Normal('y', mu_est, s[g]**-2, observed=y)
#!/usr/bin/env python # encoding: utf-8 ''' @project : 'AlgPackage' @author : '张宗旺' @file : 'pymcTest3'.py @ide : 'PyCharm' @time : '2021'-'01'-'10' '16':'18':'55' @contact : [email protected] ''' """ 自定义似然函数 test1 """ import pymc3 as pm import random model = pm.Model() with model: p_prior = pm.Uniform("p_prior", 0.8, 1.0) # def likelihood(p_prior): # if random.random() < p_prior: # p = 0.9 # else: # p = 0.5 # # # pm.DensityDist("likelihood",likelihood) likelihood = pm.Bernoulli(name="test", p=p_prior)
# In[3]: f = np.angle( np.exp(1j * smoothing.datapack.get_phase([51], [0], -1, [0]).flatten())) directions, _ = smoothing.datapack.get_directions(-1) freqs = smoothing.datapack.get_freqs(-1) x, y = directions.ra.deg, directions.dec.deg x -= x.mean() y -= y.mean() X = np.array([x, y]).T import pymc3 as pm with pm.Model() as model: df = pm.Uniform('df', lower=0, upper=1, shape=[f.size]) f = (f + df * (2 * np.pi)) * (freqs[0] / -8.4480e9) f -= f.mean() f /= f.std() cov_func = pm.gp.cov.ExpQuad(2, ls=[0.5, 0.5]) gp = pm.gp.Marginal(cov_func=cov_func) y0_ = gp.marginal_likelihood('y0', X, f, 0.01) trace = pm.sample(10000, chains=4) pm.traceplot(trace, combined=True) plt.show() # In[4]: pm.summary(trace) # In[10]:
# Commented out IPython magic to ensure Python compatibility. import pymc3 as pm import numpy as np import seaborn as sns # create random variable which is normally distributed y = np.random.normal(10, 4, 1000) # Examine the density plot of y sns.kdeplot(y) # create a pymc3 model with pm.Model() as model: # an uninformative uniform prior between 0 and 100 mu = pm.Uniform('mu', 0, 100) # An uninformative uniform prior inbetween 0 and 4 sigma = pm.Uniform('sigma', 0, 4) # it takes the free parameters mu and sigma as input and output # the sum of logp of the observations conditioned on the input. likelihood = pm.Normal('likelihood', mu = mu, sigma = sigma, observed = y) trace = pm.sample(1000) pm.traceplot(trace) pm.plot_posterior(trace)
sns.kdeplot(data) plt.title('distribution of nav') plt.show() for r in ror: sns.kdeplot(r) plt.title('distribution of returns') plt.show() df = pd.DataFrame({'data_s': data_s, 'ror': ror[0]}) print(df.corr().round(2)) with pm.Model() as model: alpha = pm.Normal(name='alpha', mu=mean_data, sd=std_data) beta = pm.Normal(name='beta', mu=0, sd=10, shape=4) sigma = pm.Uniform(name='sigma', lower=0, upper=std_data) mu = pm.Deterministic( 'mu', alpha + beta[0] * data_s + beta[1] * data_s2 + beta[2] * data_s3 + beta[3] * data_s4) ret = pm.Normal(name='returns', mu=mu, sd=sigma, observed=ror) trace_model = pm.sample(1000, tune=2000) print(pm.summary(trace_model, ['alpha', 'beta', 'sigma'])) pm.traceplot(trace_model, varnames=['alpha', 'beta', 'sigma']) plt.title('model parameters') plt.show() mu_pred = trace_model['mu'] idx = np.argsort(data_s) mu_hpd = pm.hpd(mu_pred, alpha=0.11)[idx]
inc_des = data['inc'] * dg2rd heading_des = data['heading'] * dg2rd UEast_des = -np.cos(heading_des) * np.sin(inc_des) UNorth_des = np.sin(heading_des) * np.sin(inc_des) UVert_des = np.cos(inc_des) U_des = data['vel'] #Setting some bounds xmin_des = np.min(x_des) xmax_des = np.max(x_des) ymin_des = np.min(y_des) ymax_des = np.max(y_des) print('Starting inversion') #Setup inversion with pm.Model() as model: strExp1 = pm.Uniform('strExp1', lower=12, upper=18) strExp2 = pm.Uniform('strExp2', lower=12, upper=18) strSource1 = pm.Deterministic('strSource1', -10**strExp1) strSource2 = pm.Deterministic('strSource2', -10**strExp2) depthSource1 = pm.Uniform('depthSource1', lower=500, upper=2500) depthSource2 = pm.Uniform('depthSource2', lower=500, upper=5000) xSource1 = pm.Uniform('xSource1', lower=-10000, upper=10000) xSource2 = pm.Uniform('xSource2', lower=-10000, upper=10000) ySource1 = pm.Uniform('ySource1', lower=-10000, upper=10000) ySource2 = pm.Uniform('ySource2', lower=-10000, upper=10000) R_asc1 = tt.sqrt((x_asc - xSource1)**2 + (y_asc - ySource1)**2 + depthSource1**2) R_asc2 = tt.sqrt((x_asc - xSource2)**2 + (y_asc - ySource2)**2 + depthSource2**2)
def make_model(cls): model = pm.Model() with model: a = pm.Uniform("a", lower=-1, upper=1) return model
def param_rv(self, pid, defs): if defs is not None: raise ValueError('no parameters') uniforms = pm.Uniform('param_{}'.format(pid), 0, 1, shape=self.nparams) result = uniforms / uniforms.sum() return result
# switchpoint array s_arr = [] s_testvals = x.quantile(q=[i/k for i in range(1, k)]).values for i in range(k-1): s_arr.append( pm.DiscreteUniform( f's{i+1}', lower = x.iloc[0] if not s_arr else s_arr[-1], upper = x.iloc[-1], testval = s_testvals[i])) # priors for the pre and post switch intercepts and gradients w_arr = [] b_arr = [] for i in range(k): w_arr.append(pm.Uniform(f'w{i+1}', lower=-10, upper=10)) b_arr.append(pm.Normal(f'b{i+1}', 0, sd=20)) w_switch_arr = [] b_switch_arr = [] for i in range(k-1): w_switch_arr.append( pm.math.switch( s_arr[-(i+1)] < x, w_arr[-1] if not w_switch_arr else w_switch_arr[-1], w_arr[-(i+2)])) b_switch_arr.append( pm.math.switch( s_arr[-(i+1)] < x, b_arr[-1] if not b_switch_arr else b_switch_arr[-1], b_arr[-(i+2)]))
for g2idx in range(g1idx + 1, NxLvl): cmpVec = np.repeat(0, NxLvl) cmpVec[g1idx] = -1 cmpVec[g2idx] = 1 contrast_dict = (contrast_dict, cmpVec) z = (y - np.mean(y)) / np.std(y) ## THE MODEL. with pm.Model() as model: # define the hyperpriors a_SD_unabs = pm.T('a_SD_unabs', mu=0, lam=0.001, nu=1) a_SD = abs(a_SD_unabs) + 0.1 atau = 1 / a_SD**2 # define the priors sigma = pm.Uniform('sigma', 0, 10) # y values are assumed to be standardized tau = 1 / sigma**2 a0 = pm.Normal('a0', mu=0, tau=0.001) # y values are assumed to be standardized a = pm.Normal('a', mu=0, tau=atau, shape=NxLvl) mu = a0 + a # define the likelihood yl = pm.Normal('yl', mu[x], tau=tau, observed=z) # Generate a MCMC chain start = pm.find_MAP() steps = pm.Metropolis() trace = pm.sample(20000, steps, start, progressbar=False) # EXAMINE THE RESULTS burnin = 2000 thin = 50
import pymc3 as pm import matplotlib.pyplot as plt import numpy as np basic_model = pm.Model() with basic_model: mu = pm.Uniform('mu', -1, 1) sigma = pm.Uniform('sigma', 0, 1) x = pm.Normal('x', mu=mu, sigma=sigma, observed=[0.1, 0.2, 0.3, 0.4, 0.5]) with basic_model: data = pm.sample(1000) pm.traceplot(data) plt.show() print("mu: ", data['mu'].mean()) print("sigma: ", data['sigma'].mean())
old_faithful_df = pd.read_csv('old_faithful.csv') old_faithful_df['std_waiting'] = ( old_faithful_df.waiting - old_faithful_df.waiting.mean()) / old_faithful_df.waiting.std() N = old_faithful_df.shape[0] K = 30 with pm.Model() as model: alpha = pm.Gamma('alpha', 1., 1.) v = pm.Beta('v', 1., alpha, shape=K - 1) w = pm.Deterministic('w', stick_breaking(v)) # what is the lambda * tau parameterization doing for us? tau = pm.Gamma('tau', 1., 1., shape=K) lambda_ = pm.Uniform('lambda', 0, 5, shape=K) mu = pm.Normal('mu', 0, tau=lambda_ * tau, shape=K) obs = pm.NormalMixture('obs', w, mu, tau=lambda_ * tau, observed=old_faithful_df.std_waiting.values) # I've changed this to Metropolis with burnin of 1000 instead of NUTS # Metropolis is faster step = pm.Metropolis() trace = pm.sample(1000, step, tune=1000, random_seed=SEED) # I haven't fully worked through what's going on with the axes here yet, # but basically I think expand across mixture components, multiply by weights, # and sum again?
return bn.node[BN.predecessors(node)[num]]['pymc3_obj'] def print_bayes_net(bn): for node in bayes_net.nodes.items(): print(node) bayes_net = nx.DiGraph() for k, v in moo_problem.design_variables.items(): bayes_net.add_node(k, dtype="Uniform", lower=v.min, upper=v.max) for k, v in moo_problem.objective_functions.items(): bayes_net.add_node(k, dtype="Deterministic", variables=v.variables, string=v.function_string) print_bayes_net(bn=bayes_net) bayes_model = pm.Model() with bayes_model: for k, v in moo_problem.design_variables.items(): if bayes_net.node[k]['dtype'] == 'Uniform': bayes_net.node[k]['pymc3_obj'] = pm.Uniform( k, lower=bayes_net.node[k]['lower'], upper=bayes_net.node[k]['upper']) f1 = 4*bayes_net.node['x1']['pymc3_obj']**2\ + 4*bayes_net.node['x2']['pymc3_obj']**2 f2 = (bayes_net.node['x1']['pymc3_obj']-8)**2\ + (bayes_net.node['x1']['pymc3_obj']+3)**2-7.7