Example #1
0
    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
Example #2
0
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']
Example #3
0
 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
Example #4
0
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
Example #5
0
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
Example #7
0
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()
Example #8
0
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
Example #9
0
        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
Example #10
0
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
Example #11
0
    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)
Example #12
0
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)
Example #15
0
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']
Example #16
0
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 = {}
Example #17
0
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)
Example #20
0
                        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)
Example #23
0
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
Example #24
0
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}}}')