Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
    def test_nested_initvals(self):
        # See issue #5168
        with pm.Model() as pmodel:
            one = pm.LogNormal("one",
                               mu=np.log(1),
                               sigma=1e-5,
                               initval="prior")
            two = pm.Lognormal("two",
                               mu=np.log(one * 2),
                               sigma=1e-5,
                               initval="prior")
            three = pm.LogNormal("three",
                                 mu=np.log(two * 2),
                                 sigma=1e-5,
                                 initval="prior")
            four = pm.LogNormal("four",
                                mu=np.log(three * 2),
                                sigma=1e-5,
                                initval="prior")
            five = pm.LogNormal("five",
                                mu=np.log(four * 2),
                                sigma=1e-5,
                                initval="prior")
            six = pm.LogNormal("six",
                               mu=np.log(five * 2),
                               sigma=1e-5,
                               initval="prior")

        ip_vals = list(
            make_initial_point_fn(model=pmodel,
                                  return_transformed=True)(0).values())
        assert np.allclose(np.exp(ip_vals), [1, 2, 4, 8, 16, 32], rtol=1e-3)

        ip_vals = list(
            make_initial_point_fn(model=pmodel,
                                  return_transformed=False)(0).values())
        assert np.allclose(ip_vals, [1, 2, 4, 8, 16, 32], rtol=1e-3)

        pmodel.initial_values[four] = 1

        ip_vals = list(
            make_initial_point_fn(model=pmodel,
                                  return_transformed=True)(0).values())
        assert np.allclose(np.exp(ip_vals), [1, 2, 4, 1, 2, 4], rtol=1e-3)

        ip_vals = list(
            make_initial_point_fn(model=pmodel,
                                  return_transformed=False)(0).values())
        assert np.allclose(ip_vals, [1, 2, 4, 1, 2, 4], rtol=1e-3)
Пример #4
0
def test_model_logp(jacobian):
    with pm.Model() as m:
        x = pm.Normal("x", 0, 1, size=2)
        y = pm.LogNormal("y", 0, 1, size=2)

    test_vals = np.array([0.0, 1.0])

    expected_x_logp = st.norm().logpdf(test_vals)
    expected_y_logp = expected_x_logp.copy()
    if not jacobian:
        expected_y_logp -= np.array([0.0, 1.0])

    x_logp, y_logp = m.compile_logp(sum=False, jacobian=jacobian)(
        {"x": test_vals, "y_log__": test_vals}
    )
    assert np.all(np.isclose(x_logp, expected_x_logp))
    assert np.all(np.isclose(y_logp, expected_y_logp))

    x_logp2 = m.compile_logp(vars=[x], sum=False, jacobian=jacobian)({"x": test_vals})
    assert np.all(np.isclose(x_logp2, expected_x_logp))

    y_logp2 = m.compile_logp(vars=[y], sum=False, jacobian=jacobian)({"y_log__": test_vals})
    assert np.all(np.isclose(y_logp2, expected_y_logp))

    logp_sum = m.compile_logp(sum=True, jacobian=jacobian)({"x": test_vals, "y_log__": test_vals})
    assert np.isclose(logp_sum, expected_x_logp.sum() + expected_y_logp.sum())
Пример #5
0
def test_model_logpt_deprecation_warning():
    with pm.Model() as m:
        x = pm.Normal("x", 0, 1, size=2)
        y = pm.LogNormal("y", 0, 1, size=2)

    with pytest.warns(FutureWarning):
        m.logpt()

    with pytest.warns(FutureWarning):
        m.dlogpt()

    with pytest.warns(FutureWarning):
        m.d2logpt()

    with pytest.warns(FutureWarning):
        m.datalogpt

    with pytest.warns(FutureWarning):
        m.varlogpt

    with pytest.warns(FutureWarning):
        m.observedlogpt

    with pytest.warns(FutureWarning):
        m.potentiallogpt

    with pytest.warns(FutureWarning):
        m.varlogp_nojact
Пример #6
0
    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),
                             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["R"].shape == (1, 50)
        assert idata.posterior["sigma"].shape == (1, 50, 2)
Пример #7
0
def test_rvs_to_value_vars_nested():
    # Test that calling rvs_to_value_vars in models with nested transformations
    # does not change the original rvs in place. See issue #5172
    with pm.Model() as m:
        one = pm.LogNormal("one", mu=0)
        two = pm.LogNormal("two", mu=at.log(one))

        # We add potentials or deterministics that are not in topological order
        pm.Potential("two_pot", two)
        pm.Potential("one_pot", one)

        before = aesara.clone_replace(m.free_RVs)

        # This call would change the model free_RVs in place in #5172
        res, _ = rvs_to_value_vars(m.potentials, apply_transforms=True)

        after = aesara.clone_replace(m.free_RVs)

        assert equal_computations(before, after)
Пример #8
0
    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
Пример #9
0
 def test_eval_rv_shapes(self):
     with pm.Model(coords={
             "city": ["Sydney", "Las Vegas", "Düsseldorf"],
     }) as pmodel:
         pm.Data("budget", [1, 2, 3, 4], dims="year")
         pm.Normal("untransformed", size=(1, 2))
         pm.Uniform("transformed", size=(7, ))
         obs = pm.Uniform("observed", size=(3, ), observed=[0.1, 0.2, 0.3])
         pm.LogNormal("lognorm", mu=at.log(obs))
         pm.Normal("from_dims", dims=("city", "year"))
     shapes = pmodel.eval_rv_shapes()
     assert shapes["untransformed"] == (1, 2)
     assert shapes["transformed"] == (7, )
     assert shapes["transformed_interval__"] == (7, )
     assert shapes["lognorm"] == (3, )
     assert shapes["lognorm_log__"] == (3, )
     assert shapes["from_dims"] == (3, 4)
Пример #10
0
    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),
                             sd=sigma,
                             observed=yobs)

            idata = pm.sample(100, tune=0, chains=1)

        assert idata.posterior["beta"].shape == (1, 100)
        assert idata.posterior["gamma"].shape == (1, 100)
        assert idata.posterior["sigma"].shape == (1, 100, 2)
Пример #11
0
    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)
Пример #12
0
def test_sample_find_MAP_does_not_modify_start():
    # see https://github.com/pymc-devs/pymc/pull/4458
    with pm.Model():
        pm.LogNormal("untransformed")

        # make sure find_Map does not modify the start dict
        start = {"untransformed": 2}
        pm.find_MAP(start=start)
        assert start == {"untransformed": 2}

        # make sure sample does not modify the start dict
        start = {"untransformed": 0.2}
        pm.sample(draws=10, step=pm.Metropolis(), tune=5, start=start, chains=3)
        assert start == {"untransformed": 0.2}

        # make sure sample does not modify the start when passes as list of dict
        start = [{"untransformed": 2}, {"untransformed": 0.2}]
        pm.sample(draws=10, step=pm.Metropolis(), tune=5, start=start, chains=2)
        assert start == [{"untransformed": 2}, {"untransformed": 0.2}]
Пример #13
0
def test_model_d2logp(jacobian):
    with pm.Model() as m:
        x = pm.Normal("x", 0, 1, size=2)
        y = pm.LogNormal("y", 0, 1, size=2)

    test_vals = np.array([0.0, -1.0])
    state = {"x": test_vals, "y_log__": test_vals}

    expected_x_d2logp = expected_y_d2logp = np.eye(2)

    dlogps = m.compile_d2logp(jacobian=jacobian)(state)
    assert np.all(np.isclose(dlogps[:2, :2], expected_x_d2logp))
    assert np.all(np.isclose(dlogps[2:, 2:], expected_y_d2logp))

    x_dlogp2 = m.compile_d2logp(vars=[x], jacobian=jacobian)(state)
    assert np.all(np.isclose(x_dlogp2, expected_x_d2logp))

    y_dlogp2 = m.compile_d2logp(vars=[y], jacobian=jacobian)(state)
    assert np.all(np.isclose(y_dlogp2, expected_y_d2logp))