def test_convert_rv_to_dist_shape():

    # Make sure we use the `ShapeFeature` to get the shape info
    X_rv = NormalRV(np.r_[1, 2], 2.0, name="X_rv")
    fgraph = FunctionGraph(tt_inputs([X_rv]), [X_rv],
                           features=[tt.opt.ShapeFeature()])

    with pm.Model():
        res = convert_rv_to_dist(fgraph.outputs[0].owner, None)

    assert isinstance(res.distribution, pm.Normal)
    assert np.array_equal(res.distribution.shape, np.r_[2])
def test_tex_print():

    tt_normalrv_noname_expr = tt.scalar("b") * NormalRV(
        tt.scalar("\\mu"), tt.scalar("\\sigma"))
    expected = textwrap.dedent(r"""
    \begin{equation}
      \begin{gathered}
      b \in \mathbb{R}, \,\mu \in \mathbb{R}, \,\sigma \in \mathbb{R}
      \\
      a \sim \operatorname{N}\left(\mu, {\sigma}^{2}\right)\,  \in \mathbb{R}
      \end{gathered}
      \\
      (b \odot a)
    \end{equation}
    """)
    assert tt_tprint(tt_normalrv_noname_expr) == expected.strip()

    tt_normalrv_name_expr = tt.scalar("b") * NormalRV(
        tt.scalar("\\mu"), tt.scalar("\\sigma"), size=[2, 1], name="X")
    expected = textwrap.dedent(r"""
    \begin{equation}
      \begin{gathered}
      b \in \mathbb{R}, \,\mu \in \mathbb{R}, \,\sigma \in \mathbb{R}
      \\
      X \sim \operatorname{N}\left(\mu, {\sigma}^{2}\right)\,  \in \mathbb{R}^{2 \times 1}
      \end{gathered}
      \\
      (b \odot X)
    \end{equation}
    """)
    assert tt_tprint(tt_normalrv_name_expr) == expected.strip()

    tt_2_normalrv_noname_expr = tt.matrix("M") * NormalRV(
        tt.scalar("\\mu_2"), tt.scalar("\\sigma_2"))
    tt_2_normalrv_noname_expr *= tt.scalar("b") * NormalRV(
        tt_2_normalrv_noname_expr, tt.scalar("\\sigma")) + tt.scalar("c")
    expected = textwrap.dedent(r"""
    \begin{equation}
      \begin{gathered}
      M \in \mathbb{R}^{N^{M}_{0} \times N^{M}_{1}}
      \\
      \mu_2 \in \mathbb{R}, \,\sigma_2 \in \mathbb{R}
      \\
      b \in \mathbb{R}, \,\sigma \in \mathbb{R}, \,c \in \mathbb{R}
      \\
      a \sim \operatorname{N}\left(\mu_2, {\sigma_2}^{2}\right)\,  \in \mathbb{R}
      \\
      d \sim \operatorname{N}\left((M \odot a), {\sigma}^{2}\right)\,  \in \mathbb{R}^{N^{d}_{0} \times N^{d}_{1}}
      \end{gathered}
      \\
      ((M \odot a) \odot ((b \odot d) + c))
    \end{equation}
    """)
    assert tt_tprint(tt_2_normalrv_noname_expr) == expected.strip()

    expected = textwrap.dedent(r"""
    \begin{equation}
      \begin{gathered}
      b \in \mathbb{Z}, \,c \in \mathbb{Z}, \,M \in \mathbb{R}^{N^{M}_{0} \times N^{M}_{1}}
      \end{gathered}
      \\
      M\left[b, \,c\right]
    \end{equation}
    """)
    # TODO: "c" should be "1".
    assert (tt_tprint(
        tt.matrix("M")[tt.iscalar("a"),
                       tt.constant(1, dtype="int")]) == expected.strip())

    expected = textwrap.dedent(r"""
    \begin{equation}
      \begin{gathered}
      M \in \mathbb{R}^{N^{M}_{0} \times N^{M}_{1}}
      \end{gathered}
      \\
      M\left[1\right]
    \end{equation}
    """)
    assert tt_tprint(tt.matrix("M")[1]) == expected.strip()

    expected = textwrap.dedent(r"""
    \begin{equation}
      \begin{gathered}
      M \in \mathbb{N}^{N^{M}_{0}}
      \end{gathered}
      \\
      M\left[2:4:0\right]
    \end{equation}
    """)
    assert tt_tprint(tt.vector("M", dtype="uint32")[0:4:2]) == expected.strip()

    norm_rv = NormalRV(tt.scalar("\\mu"), tt.scalar("\\sigma"))
    rv_obs = observed(tt.constant(1.0, dtype=norm_rv.dtype), norm_rv)

    expected = textwrap.dedent(r"""
    \begin{equation}
      \begin{gathered}
      \mu \in \mathbb{R}, \,\sigma \in \mathbb{R}
      \\
      a \sim \operatorname{N}\left(\mu, {\sigma}^{2}\right)\,  \in \mathbb{R}
      \end{gathered}
      \\
      a = 1.0
    \end{equation}
        """)
    assert tt_tprint(rv_obs) == expected.strip()
def test_pymc3_convert_dists():
    """Just a basic check that all PyMC3 RVs will convert to and from Theano RVs."""

    with pm.Model() as model:
        norm_rv = pm.Normal("norm_rv", 0.0, 1.0, observed=1.0)
        mvnorm_rv = pm.MvNormal("mvnorm_rv",
                                np.r_[0.0],
                                np.c_[1.0],
                                shape=1,
                                observed=np.r_[1.0])
        cauchy_rv = pm.Cauchy("cauchy_rv", 0.0, 1.0, observed=1.0)
        halfcauchy_rv = pm.HalfCauchy("halfcauchy_rv", 1.0, observed=1.0)
        uniform_rv = pm.Uniform("uniform_rv", observed=1.0)
        gamma_rv = pm.Gamma("gamma_rv", 1.0, 1.0, observed=1.0)
        invgamma_rv = pm.InverseGamma("invgamma_rv", 1.0, 1.0, observed=1.0)
        exp_rv = pm.Exponential("exp_rv", 1.0, observed=1.0)
        halfnormal_rv = pm.HalfNormal("halfnormal_rv", 1.0, observed=1.0)
        beta_rv = pm.Beta("beta_rv", 2.0, 2.0, observed=1.0)
        binomial_rv = pm.Binomial("binomial_rv", 10, 0.5, observed=5)
        dirichlet_rv = pm.Dirichlet("dirichlet_rv",
                                    np.r_[0.1, 0.1],
                                    observed=np.r_[0.1, 0.1])
        poisson_rv = pm.Poisson("poisson_rv", 10, observed=5)
        bernoulli_rv = pm.Bernoulli("bernoulli_rv", 0.5, observed=0)
        betabinomial_rv = pm.BetaBinomial("betabinomial_rv",
                                          0.1,
                                          0.1,
                                          10,
                                          observed=5)
        categorical_rv = pm.Categorical("categorical_rv",
                                        np.r_[0.5, 0.5],
                                        observed=1)
        multinomial_rv = pm.Multinomial("multinomial_rv",
                                        5,
                                        np.r_[0.5, 0.5],
                                        observed=np.r_[2])
        negbinomial_rv = pm.NegativeBinomial("negbinomial_rv",
                                             10.2,
                                             0.5,
                                             observed=5)

    # Convert to a Theano `FunctionGraph`
    fgraph = model_graph(model)

    rvs_by_name = {
        n.owner.inputs[1].name: n.owner.inputs[1]
        for n in fgraph.outputs
    }

    pymc_rv_names = {n.name for n in model.observed_RVs}
    assert all(
        isinstance(rvs_by_name[n].owner.op, RandomVariable)
        for n in pymc_rv_names)

    # Now, convert back to a PyMC3 model
    pymc_model = graph_model(fgraph)

    new_pymc_rv_names = {n.name for n in pymc_model.observed_RVs}
    pymc_rv_names == new_pymc_rv_names

    with pytest.raises(TypeError):
        graph_model(NormalRV(0, 1), generate_names=False)

    res = graph_model(NormalRV(0, 1), generate_names=True)
    assert res.vars[0].name == "normal_0"
Exemple #4
0
def test_pymc_normals():
    tt.config.compute_test_value = 'ignore'

    rand_state = theano.shared(np.random.RandomState())
    mu_a = NormalRV(0., 100**2, name='mu_a', rng=rand_state)
    sigma_a = HalfCauchyRV(5, name='sigma_a', rng=rand_state)
    mu_b = NormalRV(0., 100**2, name='mu_b', rng=rand_state)
    sigma_b = HalfCauchyRV(5, name='sigma_b', rng=rand_state)
    county_idx = np.r_[1, 1, 2, 3]
    # We want the following for a, b:
    # N(m, S) -> m + N(0, 1) * S
    a = NormalRV(mu_a,
                 sigma_a,
                 size=(len(county_idx), ),
                 name='a',
                 rng=rand_state)
    b = NormalRV(mu_b,
                 sigma_b,
                 size=(len(county_idx), ),
                 name='b',
                 rng=rand_state)
    radon_est = a[county_idx] + b[county_idx] * 7
    eps = HalfCauchyRV(5, name='eps', rng=rand_state)
    radon_like = NormalRV(radon_est, eps, name='radon_like', rng=rand_state)
    radon_like_rv = observed(tt.as_tensor_variable(np.r_[1., 2., 3., 4.]),
                             radon_like)

    graph_mt = mt(radon_like_rv)
    expr_graph, = run(
        1, var('q'),
        non_obs_fixedp_graph_applyo(scale_loc_transform, graph_mt, var('q')))

    radon_like_rv_opt = expr_graph.reify()

    assert radon_like_rv_opt.owner.op == observed

    radon_like_opt = radon_like_rv_opt.owner.inputs[1]
    radon_est_opt = radon_like_opt.owner.inputs[0]

    # These should now be `tt.add(mu_*, ...)` outputs.
    a_opt = radon_est_opt.owner.inputs[0].owner.inputs[0]
    b_opt = radon_est_opt.owner.inputs[1].owner.inputs[0].owner.inputs[0]
    # Make sure NormalRV gets replaced with an addition
    assert a_opt.owner.op == tt.add
    assert b_opt.owner.op == tt.add

    # Make sure the first term in the addition is the old NormalRV mean
    mu_a_opt = a_opt.owner.inputs[0].owner.inputs[0]
    assert 'mu_a' == mu_a_opt.name == mu_a.name
    mu_b_opt = b_opt.owner.inputs[0].owner.inputs[0]
    assert 'mu_b' == mu_b_opt.name == mu_b.name

    # Make sure the second term in the addition is the standard NormalRV times
    # the old std. dev.
    assert a_opt.owner.inputs[1].owner.op == tt.mul
    assert b_opt.owner.inputs[1].owner.op == tt.mul

    sigma_a_opt = a_opt.owner.inputs[1].owner.inputs[0].owner.inputs[0]
    assert sigma_a_opt.owner.op == sigma_a.owner.op
    sigma_b_opt = b_opt.owner.inputs[1].owner.inputs[0].owner.inputs[0]
    assert sigma_b_opt.owner.op == sigma_b.owner.op

    a_std_norm_opt = a_opt.owner.inputs[1].owner.inputs[1]
    assert a_std_norm_opt.owner.op == NormalRV
    assert a_std_norm_opt.owner.inputs[0].data == 0.0
    assert a_std_norm_opt.owner.inputs[1].data == 1.0
    b_std_norm_opt = b_opt.owner.inputs[1].owner.inputs[1]
    assert b_std_norm_opt.owner.op == NormalRV
    assert b_std_norm_opt.owner.inputs[0].data == 0.0
    assert b_std_norm_opt.owner.inputs[1].data == 1.0
Exemple #5
0
 def scan_fn(mus_t, sigma_t, S_tm1, Gamma_t, rng):
     S_t = CategoricalRV(Gamma_t[S_tm1], rng=rng, name="S_t")
     Y_t = NormalRV(mus_t[S_t], sigma_t, rng=rng, name="Y_t")
     return S_t, Y_t