def test_scalar_ode_1_param(self): """Test running model for a scalar ODE with 1 parameter""" def system(y, t, p): return np.exp(-t) - p[0] * y[0] times = np.array( [0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5] ) yobs = np.array( [0.31, 0.57, 0.51, 0.55, 0.47, 0.42, 0.38, 0.3, 0.26, 0.22, 0.22, 0.14, 0.14, 0.09, 0.1] )[:, np.newaxis] ode_model = DifferentialEquation(func=system, t0=0, times=times, n_states=1, n_theta=1) with pm.Model() as model: alpha = pm.HalfCauchy("alpha", 1) y0 = pm.LogNormal("y0", 0, 1) sigma = pm.HalfCauchy("sigma", 1) forward = ode_model(theta=[alpha], y0=[y0]) y = pm.LogNormal("y", mu=pm.math.log(forward), sigma=sigma, observed=yobs) with aesara.config.change_flags(mode=fast_unstable_sampling_mode): idata = pm.sample(50, tune=0, chains=1) assert idata.posterior["alpha"].shape == (1, 50) assert idata.posterior["y0"].shape == (1, 50) assert idata.posterior["sigma"].shape == (1, 50)
def test_scalar_ode_2_param(self): """Test running model for a scalar ODE with 2 parameters""" def system(y, t, p): return p[0] * np.exp(-p[0] * t) - p[1] * y[0] times = np.array( [0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5] ) yobs = np.array( [0.31, 0.57, 0.51, 0.55, 0.47, 0.42, 0.38, 0.3, 0.26, 0.22, 0.22, 0.14, 0.14, 0.09, 0.1] )[:, np.newaxis] ode_model = DifferentialEquation(func=system, t0=0, times=times, n_states=1, n_theta=2) with pm.Model() as model: alpha = pm.HalfCauchy("alpha", 1) beta = pm.HalfCauchy("beta", 1) y0 = pm.LogNormal("y0", 0, 1) sigma = pm.HalfCauchy("sigma", 1) forward = ode_model(theta=[alpha, beta], y0=[y0]) y = pm.LogNormal("y", mu=pm.math.log(forward), sd=sigma, observed=yobs) idata = pm.sample(100, tune=0, chains=1) assert idata.posterior["alpha"].shape == (1, 100) assert idata.posterior["beta"].shape == (1, 100) assert idata.posterior["y0"].shape == (1, 100) assert idata.posterior["sigma"].shape == (1, 100)
def setup_inference_mixture(self): #depending on the number of wavelengths #self.wavelengths = [self.wavelengths[len(self.wavelengths)-1]] wavelength_number = len(self.wavelengths) t = 1. / 2.5**2 C_sigs = pymc.Container([pymc.HalfCauchy("c_sigs_%i_%i" % (i, x), beta = 10, alpha=1) for i in range(1+2*self.N) for x in range(wavelength_number)]) C = pymc.Container([pymc.Normal("c_%i_%i" % (i, x), mu=0, tau = 1. / C_sigs[i*wavelength_number+x]**2) for i in range(1+2*self.N) for x in range(wavelength_number)]) i_ = pymc.Container([pymc.DiscreteUniform('i_%i' %i,lower=0,upper=1) for i in range(len(self.xdata))]) @pymc.stochastic(observed=False) def sigma(value=1): return -np.log(abs(value)) @pymc.stochastic(observed=False) def sigma3(value=1): return -np.log(abs(value)) qw_sigs = pymc.Container([pymc.HalfCauchy("qw_sigs_%i" % x, beta = 10, alpha=1) for x in range(wavelength_number)]) if self.wavelength_sd_defined: qw = pymc.Container([pymc.distributions.Lognormal('qw_%i' %x,mu=self.wavelengths[x], tau = 1. / self.wavelength_sd[x] ** 2) for x in range(wavelength_number)]) else: qw = pymc.Container([pymc.distributions.Uniform('qw_%i' %x,lower=0., upper=self.wavelengths[x]*2) for x in range(wavelength_number)]) def fourier_series(C,N,QW,x,wavelength_number,i_): v = np.array(x) v.fill(0.0) v = v.astype('float') for ii in range(len(x)): for w in range(wavelength_number): v += C[w] for i in range(1,N+1): v[ii] = v[ii] + C[(2*i-1)*wavelength_number+w]*np.cos(2*np.pi/QW[w] * i * (x[ii])) + C[(2*i)*wavelength_number+w]*np.sin(2*np.pi/QW[w] * i * (x[ii])) #if i_[ii] == 0: # v[ii] = -v[ii] return v#np.sum(v) self.vector_fourier_series = np.vectorize(fourier_series) # Define the form of the model and likelihood @pymc.deterministic def y_model(C=C,x=self.xdata,qw=qw,nn=self.N,wavelength_number=wavelength_number,i_=i_): return fourier_series(C,nn,qw,x,wavelength_number,i_) y = pymc.Normal('y', mu=y_model, tau=1. / sigma ** 2, observed=True, value=self.ydata) # package the full model in a dictionary self.model1 = dict(C=C, qw=qw, sigma=sigma,qw_sigs=qw_sigs, y_model=y_model, y=y,x_values=self.xdata,y_values=self.ydata,i_=i_) self.setup = True self.mcmc_uptodate = False return self.model1
def test_vector_ode_2_param(self): """Test running model for a vector ODE with 2 parameters""" def system(y, t, p): ds = -p[0] * y[0] * y[1] di = p[0] * y[0] * y[1] - p[1] * y[1] return [ds, di] times = np.array( [0.0, 0.8, 1.6, 2.4, 3.2, 4.0, 4.8, 5.6, 6.4, 7.2, 8.0]) yobs = np.array([ [1.02, 0.02], [0.86, 0.12], [0.43, 0.37], [0.14, 0.42], [0.05, 0.43], [0.03, 0.14], [0.02, 0.08], [0.02, 0.04], [0.02, 0.01], [0.02, 0.01], [0.02, 0.01], ]) ode_model = DifferentialEquation(func=system, t0=0, times=times, n_states=2, n_theta=2) with pm.Model() as model: beta = pm.HalfCauchy("beta", 1, initval=1) gamma = pm.HalfCauchy("gamma", 1, initval=1) sigma = pm.HalfCauchy("sigma", 1, shape=2, initval=[1, 1]) forward = ode_model(theta=[beta, gamma], y0=[0.99, 0.01]) y = pm.LogNormal("y", mu=pm.math.log(forward), sigma=sigma, observed=yobs) with aesara.config.change_flags(mode=fast_unstable_sampling_mode): idata = pm.sample(50, tune=0, chains=1) assert idata.posterior["beta"].shape == (1, 50) assert idata.posterior["gamma"].shape == (1, 50) assert idata.posterior["sigma"].shape == (1, 50, 2)
def radon_model(): """Similar in shape to the Radon model""" n_homes = 919 counties = 85 uranium = np.random.normal(-0.1, 0.4, size=n_homes) xbar = np.random.normal(1, 0.1, size=n_homes) floor_measure = np.random.randint(0, 2, size=n_homes) d, r = divmod(919, 85) county = np.hstack((np.tile(np.arange(counties, dtype=int), d), np.arange(r))) with pm.Model() as model: sigma_a = pm.HalfCauchy("sigma_a", 5) gamma = pm.Normal("gamma", mu=0.0, sigma=1e5, shape=3) mu_a = pm.Deterministic( "mu_a", gamma[0] + gamma[1] * uranium + gamma[2] * xbar) eps_a = pm.Normal("eps_a", mu=0, sigma=sigma_a, shape=counties) a = pm.Deterministic("a", mu_a + eps_a[county]) b = pm.Normal("b", mu=0.0, sigma=1e15) sigma_y = pm.Uniform("sigma_y", lower=0, upper=100) # Anonymous SharedVariables don't show up floor_measure = aesara.shared(floor_measure) floor_measure_offset = pm.MutableData("floor_measure_offset", 1) y_hat = a + b * floor_measure + floor_measure_offset log_radon = pm.MutableData("log_radon", np.random.normal(1, 1, size=n_homes)) y_like = pm.Normal("y_like", mu=y_hat, sigma=sigma_y, observed=log_radon) compute_graph = { # variable_name : set of named parents in the graph "sigma_a": set(), "gamma": set(), "mu_a": {"gamma"}, "eps_a": {"sigma_a"}, "a": {"mu_a", "eps_a"}, "b": set(), "sigma_y": set(), "y_like": {"a", "b", "sigma_y", "floor_measure_offset"}, "floor_measure_offset": set(), # observed data don't have parents in the model graph, but are shown as decendants # of the model variables that the observations belong to: "log_radon": {"y_like"}, } plates = { "": {"b", "sigma_a", "sigma_y", "floor_measure_offset"}, "3": {"gamma"}, "85": {"eps_a"}, "919": {"a", "mu_a", "y_like", "log_radon"}, } return model, compute_graph, plates
def glm_hierarchical_model(random_seed=123): """Sample glm hierarchical model to use in benchmarks""" np.random.seed(random_seed) data = pd.read_csv(pm.get_data("radon.csv")) data["log_radon"] = data["log_radon"].astype(aesara.config.floatX) county_idx = data.county_code.values n_counties = len(data.county.unique()) with pm.Model() as model: mu_a = pm.Normal("mu_a", mu=0.0, sd=100**2) sigma_a = pm.HalfCauchy("sigma_a", 5) mu_b = pm.Normal("mu_b", mu=0.0, sd=100**2) sigma_b = pm.HalfCauchy("sigma_b", 5) a = pm.Normal("a", mu=0, sd=1, shape=n_counties) b = pm.Normal("b", mu=0, sd=1, shape=n_counties) a = mu_a + sigma_a * a b = mu_b + sigma_b * b eps = pm.HalfCauchy("eps", 5) radon_est = a[county_idx] + b[county_idx] * data.floor.values pm.Normal("radon_like", mu=radon_est, sd=eps, observed=data.log_radon) return model
def data(self, eight_schools_params, draws, chains): with pm.Model() as model: mu = pm.Normal("mu", mu=0, sd=5) tau = pm.HalfCauchy("tau", beta=5) eta = pm.Normal("eta", mu=0, sd=1, size=eight_schools_params["J"]) theta = pm.Deterministic("theta", mu + tau * eta) pm.Normal( "obs", mu=theta, sd=eight_schools_params["sigma"], observed=eight_schools_params["y"], ) trace = pm.sample(draws, chains=chains, return_inferencedata=False) return self.Data(model, trace)
def track_1var_2par_ode_ess(self): def freefall(y, t, p): return 2.0 * p[1] - p[0] * y[0] # Times for observation times = np.arange(0, 10, 0.5) y = np.array([ -2.01, 9.49, 15.58, 16.57, 27.58, 32.26, 35.13, 38.07, 37.36, 38.83, 44.86, 43.58, 44.59, 42.75, 46.9, 49.32, 44.06, 49.86, 46.48, 48.18, ]).reshape(-1, 1) ode_model = pm.ode.DifferentialEquation(func=freefall, times=times, n_states=1, n_theta=2, t0=0) with pm.Model() as model: # Specify prior distributions for some of our model parameters sigma = pm.HalfCauchy("sigma", 1) gamma = pm.LogNormal("gamma", 0, 1) # If we know one of the parameter values, we can simply pass the value. ode_solution = ode_model(y0=[0], theta=[gamma, 9.8]) # The ode_solution has a shape of (n_times, n_states) Y = pm.Normal("Y", mu=ode_solution, sd=sigma, observed=y) t0 = time.time() idata = pm.sample(500, tune=1000, chains=2, cores=2, random_seed=0) tot = time.time() - t0 ess = az.ess(idata) return np.mean([ess.sigma, ess.gamma]) / tot
def test_edge_case(self): # Edge case discovered in #2948 ndim = 3 with pm.Model() as m: pm.LogNormal("sigma", mu=np.zeros(ndim), tau=np.ones(ndim), shape=ndim) # variance for the correlation matrix pm.HalfCauchy("nu", beta=10) step = pm.NUTS() func = step._logp_dlogp_func func.set_extra_values(m.initial_point) q = func.dict_to_array(m.initial_point) logp, dlogp = func(q) assert logp.size == 1 assert dlogp.size == 4 npt.assert_allclose(dlogp, 0.0, atol=1e-5)
def test_vector_ode_1_param(self): """Test running model for a vector ODE with 1 parameter""" def system(y, t, p): ds = -p[0] * y[0] * y[1] di = p[0] * y[0] * y[1] - y[1] return [ds, di] times = np.array( [0.0, 0.8, 1.6, 2.4, 3.2, 4.0, 4.8, 5.6, 6.4, 7.2, 8.0]) yobs = np.array([ [1.02, 0.02], [0.86, 0.12], [0.43, 0.37], [0.14, 0.42], [0.05, 0.43], [0.03, 0.14], [0.02, 0.08], [0.02, 0.04], [0.02, 0.01], [0.02, 0.01], [0.02, 0.01], ]) ode_model = DifferentialEquation(func=system, t0=0, times=times, n_states=2, n_theta=1) with pm.Model() as model: R = pm.LogNormal("R", 1, 5, initval=1) sigma = pm.HalfCauchy("sigma", 1, shape=2, initval=[0.5, 0.5]) forward = ode_model(theta=[R], y0=[0.99, 0.01]) y = pm.LogNormal("y", mu=pm.math.log(forward), sd=sigma, observed=yobs) idata = pm.sample(100, tune=0, chains=1) assert idata.posterior["R"].shape == (1, 100) assert idata.posterior["sigma"].shape == (1, 100, 2)
def make_poisson_hmm(y_data, X_data, initial_params): r""" Construct a PyMC2 scalar poisson-emmisions HMM model. TODO: Update to match normal model design. The model takes the following form: .. math:: y_t &\sim \operatorname{Poisson}(\exp(x_t^{(S_t)\top} \beta^{(S_t)})) \\ \beta^{(S_t)}_i &\sim \operatorname{N}(m^{(S_t)}, C^{(S_t)}), \quad i \in \{1,\dots,M\} \\ S_t \mid S_{t-1} &\sim \operatorname{Categorical}(\pi^{(S_{t-1})}) \\ \pi^{(S_t-1)} &\sim \operatorname{Dirichlet}(\alpha^{(S_{t-1})}) where :math:`C^{(S_t)} = \lambda_i^{(S_t) 2} \tau^{(S_t) 2}` and .. math:: \lambda^{(S_t)}_i &\sim \operatorname{Cauchy}^{+}(0, 1) \\ \tau^{(S_t)} &\sim \operatorname{Cauchy}^{+}(0, 1) for observations :math:`y_t` in :math:`t \in \{0, \dots, T\}`, features :math:`x_t^{(S_t)} \in \mathbb{R}^M`, regression parameters :math:`\beta^{(S_t)}`, state sequences :math:`\{S_t\}^T_{t=1}` and state transition probabilities :math:`\pi \in [0, 1]^{K}`. :math:`\operatorname{Cauchy}^{+}` is the standard half-Cauchy distribution and :math:`\operatorname{N}` is the normal/Gaussian distribution. The set of random variables, :math:`\mathcal{S} = \{\{\beta^{(k)}, \lambda^{(k)}, \tau^{(k)}, \tau^{(k)}, \pi^{(k)}\}_{k=1}^K, \{S_t\}^T_{t=1}\}`, are referred to as "stochastics" throughout the code. Parameters ========== y_data: pandas.DataFrame Usage/response observations :math:`y_t`. X_data: list of pandas.DataFrame List of design matrices for each state, i.e. :math:`x_t^{(S_t)}`. Each must span the entire length of observations (i.e. `y_data`). initial_params: NormalHMMInitialParams The initial parameters, which include :math:`\pi_0, m^{(k)}, \alpha^{(k)}, V^{(k)}`. Ignores `V` parameters. FIXME: using the "Normal" initial params objects is only temporary. Returns ======= A ``pymc.Model`` object used for sampling. """ N_states = len(X_data) N_obs = X_data[0].shape[0] alpha_trans = initial_params.alpha_trans trans_mat = TransProbMatrix("trans_mat", alpha_trans, value=initial_params.trans_mat) states = HMMStateSeq("states", trans_mat, N_obs, p0=initial_params.p0, value=initial_params.states) betas = [] etas = [] lambdas = [] for s in range(N_states): initial_beta = None if initial_params.betas is not None: initial_beta = initial_params.betas[s] size_s = X_data[s].shape[1] size_s = size_s if size_s > 1 else None lambda_s = pymc.HalfCauchy('lambda-{}'.format(s), 0., 1., size=size_s) eta_s = pymc.HalfCauchy('tau-{}'.format(s), 0., 1.) beta_s = pymc.Normal('beta-{}'.format(s), 0., (lambda_s * eta_s)**(-2), value=initial_beta, size=size_s) betas += [beta_s] etas += [eta_s] lambdas += [lambda_s] mu_reg = HMMLinearCombination('mu', X_data, betas, states, trace=False) @pymc.deterministic(trace=True, plot=False) def mu(mu_reg_=mu_reg): return np.exp(mu_reg_) if y_data is not None: y_data = np.ma.masked_invalid(y_data).astype(np.object) y_data.set_fill_value(None) y_rv = pymc.Poisson('y', mu, value=y_data, observed=True if y_data is not None else False) del initial_params, s, beta_s, size_s, lambda_s, eta_s return pymc.Model(locals())
def make_normal_hmm(y_data, X_data, initial_params=None, single_obs_var=False, include_ppy=False): r""" Construct a PyMC2 scalar normal-emmisions HMM model of the form .. math:: y_t &\sim \operatorname{N}^{+}(x_t^{(S_t)\top} \beta^{(S_t)}, V^{(S_t)}) \\ \beta^{(S_t)}_i &\sim \operatorname{N}(m^{(S_t)}, C^{(S_t)}), \quad i \in \{1,\dots, M\} \\ S_t \mid S_{t-1} &\sim \operatorname{Categorical}(\pi^{(S_{t-1})}) \\ \pi^{(S_t-1)} &\sim \operatorname{Dirichlet}(\alpha^{(S_{t-1})}) where :math:`\operatorname{N}_{+}` is the positive (truncated below zero) normal distribution, :math:`S_t \in \{1, \ldots, K\}`, :math:`C^{(S_t)} = \lambda_i^{(S_t) 2} \tau^{(S_t) 2}` and .. math:: \lambda^{k}_i &\sim \operatorname{Cauchy}^{+}(0, 1) \\ \tau^{(k)} &\sim \operatorname{Cauchy}^{+}(0, 1) \\ V^{(k)} &\sim \operatorname{Gamma}(n_0/2, n_0 S_0/2) for :math:`k \in \{1, \ldots, K\}`. for observations :math:`y_t` in :math:`t \in \{0, \dots, T\}`, features :math:`x_t^{(S_t)} \in \mathbb{R}^M`, regression parameters :math:`\beta^{(S_t)}`, state sequences :math:`\{S_t\}^T_{t=1}` and state transition probabilities :math:`\pi \in [0, 1]^{K}`. :math:`\operatorname{Cauchy}^{+}` is the standard half-Cauchy distribution and :math:`\operatorname{N}` is the normal/Gaussian distribution. The set of random variables, :math:`\mathcal{S} = \{\{\beta^{(k)}, \lambda^{(k)}, \tau^{(k)}, \tau^{(k)}, \pi^{(k)}\}_{k=1}^K, \{S_t\}^T_{t=1}\}`, are referred to as "stochastics" throughout the code. Parameters ========== y_data: pandas.DataFrame Usage/response observations :math:`y_t`. X_data: list of pandas.DataFrame List of design matrices for each state, i.e. :math:`x_t^{(S_t)}`. Each must span the entire length of observations (i.e. `y_data`). initial_params: NormalHMMInitialParams The initial parameters, which include :math:`\pi_0, m^{(k)}, \alpha^{(k)}, V^{(k)}`. single_obs_var: bool, optional Determines whether there are multiple observation variances or not. Only used when not given intial parameters. include_ppy: bool, optional If `True`, then include an unobserved observation Stochastic that can be used to produce posterior predicitve samples. The Stochastic will have the name `y_pp`. Returns ======= A ``pymc.Model`` object used for sampling. """ N_states = len(X_data) N_obs = X_data[0].shape[0] alpha_trans = getattr(initial_params, 'alpha_trans', None) trans_mat_0 = getattr(initial_params, 'trans_mat', None) states_p_0 = getattr(initial_params, 'p0', None) states_0 = getattr(initial_params, 'states', None) betas_0 = getattr(initial_params, 'betas', None) V_invs_n_0 = getattr(initial_params, 'Vs_n', None) V_invs_S_0 = getattr(initial_params, 'Vs_S', None) V_invs_0 = getattr(initial_params, 'Vs', None) # # Some parameters can be set to arguably generic values # when no initial parameters are explicitly given. # if alpha_trans is None: alpha_trans = np.ones((N_states, N_states)) if trans_mat_0 is None: trans_mat_0 = np.tile(1. / N_states, (N_states, N_states - 1)) if betas_0 is None: betas_0 = [np.zeros(X_.shape[1]) for X_ in X_data] if V_invs_n_0 is None or V_invs_S_0 is None: V_invs_shape = (1 if single_obs_var else N_states, ) if y_data is not None: V_invs_n_0 = np.tile(1, V_invs_shape) S_obs = np.clip(float(np.var(y_data)), 1e-4, np.inf) V_invs_S_0 = np.tile(S_obs, V_invs_shape) V_invs_0 = np.tile(S_obs, V_invs_shape) else: V_invs_n_0 = np.ones(1) V_invs_S_0 = np.tile(1e-3, V_invs_shape) V_invs_0 = np.tile(1e-3, V_invs_shape) # Transition probability stochastic: trans_mat = TransProbMatrix("trans_mat", alpha_trans, value=trans_mat_0) # State sequence stochastics: states = HMMStateSeq("states", trans_mat, N_obs, p0=states_p_0, value=states_0) # Observation precision distributions: V_inv_list = [ pymc.Gamma('V-{}'.format(k), n_0 / 2., n_0 * S_0 / 2., value=V_inv_0) for k, (V_inv_0, n_0, S_0) in enumerate(zip(V_invs_0, V_invs_n_0, V_invs_S_0)) ] V_invs = pymc.ArrayContainer(np.array(V_inv_list, dtype=np.object)) beta_list = () eta_list = () lambda_list = () beta_tau_list = () # This is a dynamic list of the time indices allocated to each state. # Very useful for breaking quantities mixtures into separate, # easy to handle problems. state_obs_idx = () # Now, initialize all the intra-state terms: for k in range(N_states): def k_idx_func(s_=states, k_=k): return np.flatnonzero(k_ == s_) # XXX: Can't trace these Deterministics, since they change shape. k_idx = pymc.Lambda("state-idx-{}".format(k), k_idx_func, trace=False) state_obs_idx += (k_idx, ) size_k = X_data[k].shape[1] size_k = size_k if size_k > 1 else None # Local shrinkage terms: lambda_k = pymc.HalfCauchy('lambdas-{}'.format(k), 0., 1., size=size_k) # We're initializing the scale of the global # shrinkage parameter's distribution with a decent, # asymptotically motivated value: if size_k is not None: k_V = k if len(V_invs) == N_states else 0 eta_k_scale = pymc.Lambda('eta-{}-scale'.format(k), lambda V_i=V_invs[k_V], s_=size_k: np. sqrt(1 / V_i) / np.sqrt(np.log(s_)), trace=False) # Global shrinkage term: eta_k = pymc.HalfCauchy('eta-{}'.format(k), 0., eta_k_scale) eta_list += (eta_k, ) beta_tau_k = (lambda_k * eta_k)**(-2) else: beta_tau_k = (lambda_k)**(-2) # Consider using just pymc.Cauchy; that way, there's # no support restriction that could make things difficult # for naive samplers, etc. beta_k = pymc.Normal('beta-{}'.format(k), 0., beta_tau_k, value=betas_0[k], size=size_k) #beta_k = pymc.TruncatedNormal('beta-{}'.format(k), # 0, beta_tau_k, # 0, np.inf, # value=betas_0[k], # size=size_k) beta_list += (beta_k, ) lambda_list += (lambda_k, ) beta_tau_list += (beta_tau_k, ) # These containers are handy, but not necessary. betas = pymc.TupleContainer(beta_list) etas = pymc.TupleContainer(eta_list) lambdas = pymc.TupleContainer(lambda_list) beta_taus = pymc.TupleContainer(beta_tau_list) mu = HMMLinearCombination('mu', X_data, betas, states) if np.alen(V_invs) == 1: V_inv = V_invs[0] else: # This is a sort of hack... for k, V_ in enumerate(V_invs): V_.obs_idx = state_obs_idx[k] @pymc.deterministic(trace=False, plot=False) def V_inv(states_=states, V_invs_=V_invs): return V_invs_[states_].astype(np.float) y_observed = False if y_data is not None: y_observed = True y_data = np.ma.masked_invalid(y_data).astype(np.object) y_data.set_fill_value(None) y_rv = pymc.Normal('y', mu, V_inv, value=y_data, observed=y_observed) #y_rv = pymc.TruncatedNormal('y', mu, V_inv, # 0., np.inf, # value=y_data, # observed=y_observed) if y_observed and include_ppy: y_pp_rv = pymc.Normal('y_pp', mu, V_inv, trace=True) return pymc.Model(locals())
def setup_inference(self): #depending on the number of wavelengths wavelength_number = len(self.wavelengths) l = [] i = 0 #add c0 t = 1. / 5.**2 #mu_ = np.mean(self.ydata) l.append(pymc.Normal("c_%i" % (i), mu=0, tau=t)) i += 1 for x in range(wavelength_number): for _ in range(2 * self.N): t = 1. / 5.**2 mu_ = 0 l.append(pymc.Normal("c_%i" % (i), mu=mu_, tau=t)) i += 1 C = pymc.Container(l) #\ #for i in range(1+2*self.N) for x in range(wavelength_number)]) #C[0] @pymc.stochastic(observed=False) def sigma(value=1): return -np.log(abs(value)) @pymc.stochastic(observed=False) def sigma3(value=1): return -np.log(abs(value)) qw_sigs = pymc.Container([pymc.HalfCauchy("qw_sigs_%i" % x, beta = 10, alpha=1) \ for x in range(wavelength_number)]) if self.wavelength_sd_defined: qw = pymc.Container([pymc.distributions.Lognormal('qw_%i' %x,mu=self.wavelengths[x], \ tau = 1. / self.wavelength_sd[x] ** 2) \ for x in range(wavelength_number)]) else: qw = pymc.Container([pymc.distributions.TruncatedNormal('qw_%i' %x,mu=self.wavelengths[x],\ tau = 1. / self.wavelengths[x]/3.,a=0,b=np.inf) \ for x in range(wavelength_number)]) def fourier_series(C, N, QW, x, wavelength_number): v = np.array(x) v.fill(0.0) v = v.astype('float') for ii in range(len(x)): v[ii] += C[0] for w in range(wavelength_number): for i in range(1, N + 1): v[ii] = v[ii] + C[(2*i-1)+2*N*w]*np.cos(2*np.pi/QW[w] * i * (x[ii])) + \ C[(2*i)+2*N*w]*np.sin(2*np.pi/QW[w] * i * (x[ii])) return v self.vector_fourier_series = np.vectorize(fourier_series) # Define the form of the model and likelihood @pymc.deterministic def y_model(C=C, x=self.xdata, qw=qw, nn=self.N, wavelength_number=wavelength_number): return fourier_series(C, nn, qw, x, wavelength_number) y = pymc.Normal('y', mu=y_model, tau=1. / sigma**2, observed=True, value=self.ydata) # package the full model in a dictionary self.model1 = dict(C=C, qw=qw, sigma=sigma, qw_sigs=qw_sigs, y_model=y_model, y=y, x_values=self.xdata, y_values=self.ydata) self.model_e = pymc.Model([C, qw, sigma, y]) if len(self.vergence) > 0: @pymc.deterministic def vergence_values(c=C, qw=qw, y=np.array(self.vergence)[:, 0]): return np.sign(fourier_series2(c, qw, y)) @pymc.stochastic(observed=True) def vergence(value=np.array(self.vergence)[:, 1], mu=vergence_values): loglike = 0. loglike += pymc.distributions.normal_like((mu[value == 1]), mu=1, tau=1.) loglike += pymc.distributions.normal_like((mu[value == -1]), mu=-1, tau=1.) if loglike < float(-1.7876931348623157e+308): return float(-1.7876931348623157e+308) return loglike self.model1.update({'vergence': vergence}) if len(self.asymmetry_likelihoods) > 0: @pymc.deterministic def y_model_asym(c=C, qw=qw): x = np.linspace(-np.max(qw), np.max(qw)) v = np.rad2deg(np.arctan(fourier_series2(c, qw, x))) m = np.median(v) #-np.min(v) return m #np.max(v)-np.min(v) @pymc.stochastic(observed=True) def y_asym(mu=y_model_asym, value=self.asymmetry_likelihoods[0], tau=1. / self.asymmetry_sigma**2): loglike = pymc.distributions.normal_like(x=value, mu=mu, tau=tau) return loglike * 10 #y_interlimb = pymc.Normal('y_interlimb',mu=y_model_interlimb,value=self.interlimb_likelihoods[0], #tau = 1. / self.interlimb_sigma**2 ) self.model1.update({'y_asym': y_asym}) if len(self.interlimb_likelihoods) > 0: @pymc.deterministic def y_model_interlimb(c=C, qw=qw): x = np.linspace(-np.max(qw), np.max(qw)) v = np.rad2deg(np.arctan(fourier_series2(c, qw, x))) d = np.max(v) - np.min(v) return d #np.max(v)-np.min(v) @pymc.stochastic(observed=True) def y_interlimb(mu=y_model_interlimb, value=self.interlimb_likelihoods[0], tau=1. / self.interlimb_sigma**2): loglike = pymc.distributions.normal_like(x=value, mu=y_model_interlimb, tau=tau) return loglike * 10 #y_interlimb = pymc.Normal('y_interlimb',mu=y_model_interlimb,value=self.interlimb_likelihoods[0], #tau = 1. / self.interlimb_sigma**2 ) self.model1.update({'y_interlimb': y_interlimb}) if len(self.axial_trace_likelihoods) > 0: d = self.wavelengths[ 0] #np.max(self.axial_trace_likelihoods_limb) - np.min(self.axial_trace_likelihoods_limb) x_at = np.linspace( np.min(self.axial_trace_likelihoods) - d, np.max(self.axial_trace_likelihoods) + d, 300) @pymc.stochastic(observed=False) def at_sigma(value=1): return -np.log(abs(value)) @pymc.deterministic def z_model_axial_t(c=C, wl=qw, z_at=x_at): return np.array(fourier_series_x_intercepts(c, wl, z_at)) @pymc.stochastic(observed=True) def z_at(mu=z_model_axial_t, sigma=at_sigma, value=self.axial_trace_likelihoods): loglike = 0. mu = np.array(mu) #print mu if not np.array(mu).size: return float(-1.7876931348623157e+308) #-99999#-np.2inf for v in value: m = 0. if mu.shape: dif = np.sort(np.abs(mu - v)) #if there are two hinges for the same axial trace penalise this! if dif[1] < sigma: loglike += -99999 m = mu[(np.abs(mu - v)).argmin()] #m = mu[(np.abs(mu-v)).argmin()] else: m = mu #print 'm', m loglike += pymc.distributions.normal_like(x=v, mu=m, tau=1. / sigma**2) loglike if loglike < float(-1.7876931348623157e+308): return float(-1.7876931348623157e+308) return loglike #z_at = pymc.Normal('z_at',mu=z_model_axial_t,tau = 1. / self.axial_trace_limb_sigma,value=self.axial_trace_likelihoods_limb) self.model1.update({'z_at': z_at, 'at_sigma': at_sigma}) self.setup = True self.mcmc_uptodate = False return True
def setup_inference_mixture(self): #depending on the number of wavelengths wavelength_number = len(self.wavelengths) l = [] i = 0 #add c0 t = 1. / 5.**2 mu_ = np.mean(self.ydata) l.append(pymc.Normal("c_%i" % (i), mu=mu_, tau=t)) i += 1 for x in range(wavelength_number): for _ in range(2 * self.N): t = 1. / 5.**2 mu_ = 0 l.append(pymc.Normal("c_%i" % (i), mu=mu_, tau=t)) i += 1 C = pymc.Container(l) #\ #for i in range(1+2*self.N) for x in range(wavelength_number)]) #C[0] i_ = pymc.Container([ pymc.DiscreteUniform('i_%i' % i, lower=0, upper=1) for i in range(len(self.xdata)) ]) @pymc.stochastic(observed=False) def sigma(value=1): return -np.log(abs(value)) @pymc.stochastic(observed=False) def sigma3(value=1): return -np.log(abs(value)) qw_sigs = pymc.Container([pymc.HalfCauchy("qw_sigs_%i" % x, beta = 10, alpha=1) \ for x in range(wavelength_number)]) if self.wavelength_sd_defined: qw = pymc.Container([pymc.distributions.Lognormal('qw_%i' %x,mu=self.wavelengths[x], \ tau = 1. / self.wavelength_sd[x] ** 2) \ for x in range(wavelength_number)]) else: qw = pymc.Container([pymc.distributions.Normal('qw_%i' %x,mu=self.wavelengths[x],\ tau = 1. / self.wavelengths[x]/3.) \ for x in range(wavelength_number)]) def fourier_series(C, N, QW, x, wavelength_number, i_): v = np.array(x) v.fill(0.0) v = v.astype('float') for ii in range(len(x)): v[ii] += C[0] for w in range(wavelength_number): for i in range(1, N + 1): v[ii] = v[ii] + C[(2*i-1)+2*N*w]*np.cos(2*np.pi/QW[w] * i * (x[ii])) + \ C[(2*i)+2*N*w]*np.sin(2*np.pi/QW[w] * i * (x[ii])) if i_[ii] == 0: v[ii] = -v[ii] return v self.vector_fourier_series = np.vectorize(fourier_series) # Define the form of the model and likelihood @pymc.deterministic def y_model(C=C, x=self.xdata, qw=qw, nn=self.N, wavelength_number=wavelength_number, i_=i_): return fourier_series(C, nn, qw, x, wavelength_number, i_) y = pymc.Normal('y', mu=y_model, tau=1. / sigma**2, observed=True, value=self.ydata) # package the full model in a dictionary self.model1 = dict(C=C, qw=qw, sigma=sigma, qw_sigs=qw_sigs, y_model=y_model, y=y, x_values=self.xdata, y_values=self.ydata, i_=i_) self.model_e = pymc.Model([C, qw, sigma, y]) self.setup = True self.mcmc_uptodate = False return True
import pandas as pd import pymc as pm d = pd.read_csv("data/gp.csv") d.shape D = np.array([ np.abs(xi - d.x) for xi in d.x]) I = (D == 0).astype("double") with pm.Model() as gp: nugget = pm.HalfCauchy("nugget", beta=5) sigma2 = pm.HalfCauchy("sigma2", beta=5) ls = pm.HalfCauchy("ls", beta=5) Sigma = I * nugget + sigma2 * np.exp(-0.5 * D**2 * ls**2) y = pm.MvNormal( "y", mu=np.zeros(d.shape[0]), cov=Sigma, observed=d.y ) with gp: post_nuts = pm.sample( return_inferencedata = True, chains = 2 )