Esempio n. 1
0
def test_chain_jacob_det():
    chain_tranf = tr.Chain([tr.logodds, tr.ordered])
    check_jacobian_det(chain_tranf,
                       Vector(R, 4),
                       at.dvector,
                       np.zeros(4),
                       elemwise=False)
Esempio n. 2
0
 def test_exponential_ordered(self, lam, size):
     initval = np.sort(np.abs(np.random.randn(*size)))
     model = self.build_model(
         pm.Exponential,
         {"lam": lam},
         size=size,
         initval=initval,
         transform=tr.Chain([tr.log, tr.ordered]),
     )
     self.check_vectortransform_elementwise_logp(model)
Esempio n. 3
0
 def test_half_normal_ordered(self, sigma, size):
     initval = np.sort(np.abs(np.random.randn(*size)))
     model = self.build_model(
         pm.HalfNormal,
         {"sigma": sigma},
         size=size,
         initval=initval,
         transform=tr.Chain([tr.log, tr.ordered]),
     )
     self.check_vectortransform_elementwise_logp(model)
Esempio n. 4
0
 def test_vonmises_ordered(self, mu, kappa, size):
     initval = np.sort(np.abs(np.random.rand(*size)))
     model = self.build_model(
         pm.VonMises,
         {"mu": mu, "kappa": kappa},
         size=size,
         initval=initval,
         transform=tr.Chain([tr.circular, tr.ordered]),
     )
     self.check_vectortransform_elementwise_logp(model)
Esempio n. 5
0
 def test_beta_ordered(self, a, b, size):
     initval = np.sort(np.abs(np.random.rand(*size)))
     model = self.build_model(
         pm.Beta,
         {"alpha": a, "beta": b},
         size=size,
         initval=initval,
         transform=tr.Chain([tr.logodds, tr.ordered]),
     )
     self.check_vectortransform_elementwise_logp(model)
Esempio n. 6
0
    def test_uniform_ordered(self, lower, upper, size):
        def transform_params(*inputs):
            _, _, _, lower, upper = inputs
            lower = at.as_tensor_variable(lower) if lower is not None else None
            upper = at.as_tensor_variable(upper) if upper is not None else None
            return lower, upper

        interval = tr.Interval(bounds_fn=transform_params)

        initval = np.sort(np.abs(np.random.rand(*size)))
        model = self.build_model(
            pm.Uniform,
            {"lower": lower, "upper": upper},
            size=size,
            initval=initval,
            transform=tr.Chain([interval, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model)
Esempio n. 7
0
class TestElementWiseLogp(SeededTest):
    def build_model(self, distfam, params, size, transform, initval=None):
        if initval is not None:
            initval = pm.floatX(initval)
        with pm.Model() as m:
            distfam("x",
                    size=size,
                    transform=transform,
                    initval=initval,
                    **params)
        return m

    def check_transform_elementwise_logp(self, model):
        x = model.free_RVs[0]
        x_val_transf = x.tag.value_var

        pt = model.initial_point(0)
        test_array_transf = floatX(
            np.random.randn(*pt[x_val_transf.name].shape))
        transform = x_val_transf.tag.transform
        test_array_untransf = transform.backward(test_array_transf,
                                                 *x.owner.inputs).eval()

        # Create input variable with same dimensionality as untransformed test_array
        x_val_untransf = at.constant(test_array_untransf).type()

        jacob_det = transform.log_jac_det(test_array_transf, *x.owner.inputs)
        assert joint_logpt(x, sum=False)[0].ndim == x.ndim == jacob_det.ndim

        v1 = joint_logpt(x, x_val_transf, jacobian=False).eval(
            {x_val_transf: test_array_transf})
        v2 = joint_logpt(x, x_val_untransf, transformed=False).eval(
            {x_val_untransf: test_array_untransf})
        close_to(v1, v2, tol)

    def check_vectortransform_elementwise_logp(self, model):
        x = model.free_RVs[0]
        x_val_transf = x.tag.value_var

        pt = model.initial_point(0)
        test_array_transf = floatX(
            np.random.randn(*pt[x_val_transf.name].shape))
        transform = x_val_transf.tag.transform
        test_array_untransf = transform.backward(test_array_transf,
                                                 *x.owner.inputs).eval()

        # Create input variable with same dimensionality as untransformed test_array
        x_val_untransf = at.constant(test_array_untransf).type()

        jacob_det = transform.log_jac_det(test_array_transf, *x.owner.inputs)
        # Original distribution is univariate
        if x.owner.op.ndim_supp == 0:
            assert joint_logpt(
                x, sum=False)[0].ndim == x.ndim == (jacob_det.ndim + 1)
        # Original distribution is multivariate
        else:
            assert joint_logpt(
                x, sum=False)[0].ndim == (x.ndim - 1) == jacob_det.ndim

        a = joint_logpt(x, x_val_transf,
                        jacobian=False).eval({x_val_transf: test_array_transf})
        b = joint_logpt(x, x_val_untransf, transformed=False).eval(
            {x_val_untransf: test_array_untransf})
        # Hack to get relative tolerance
        close_to(a, b, np.abs(0.5 * (a + b) * tol))

    @pytest.mark.parametrize(
        "sigma,size",
        [
            (2.5, 2),
            (5.0, (2, 3)),
            (np.ones(3) * 10.0, (4, 3)),
        ],
    )
    def test_half_normal(self, sigma, size):
        model = self.build_model(pm.HalfNormal, {"sigma": sigma},
                                 size=size,
                                 transform=tr.log)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize("lam,size", [(2.5, 2), (5.0, (2, 3)),
                                          (np.ones(3), (4, 3))])
    def test_exponential(self, lam, size):
        model = self.build_model(pm.Exponential, {"lam": lam},
                                 size=size,
                                 transform=tr.log)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "a,b,size",
        [
            (1.0, 1.0, 2),
            (0.5, 0.5, (2, 3)),
            (np.ones(3), np.ones(3), (4, 3)),
        ],
    )
    def test_beta(self, a, b, size):
        model = self.build_model(pm.Beta, {
            "alpha": a,
            "beta": b
        },
                                 size=size,
                                 transform=tr.logodds)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "lower,upper,size",
        [
            (0.0, 1.0, 2),
            (0.5, 5.5, (2, 3)),
            (pm.floatX(np.zeros(3)), pm.floatX(np.ones(3)), (4, 3)),
        ],
    )
    def test_uniform(self, lower, upper, size):
        def transform_params(*inputs):
            _, _, _, lower, upper = inputs
            lower = at.as_tensor_variable(lower) if lower is not None else None
            upper = at.as_tensor_variable(upper) if upper is not None else None
            return lower, upper

        interval = tr.Interval(bounds_fn=transform_params)
        model = self.build_model(pm.Uniform, {
            "lower": lower,
            "upper": upper
        },
                                 size=size,
                                 transform=interval)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "lower, c, upper, size",
        [
            (0.0, 1.0, 2.0, 2),
            (-10, 0, 200, (2, 3)),
            (np.zeros(3), np.ones(3), np.ones(3), (4, 3)),
        ],
    )
    def test_triangular(self, lower, c, upper, size):
        def transform_params(*inputs):
            _, _, _, lower, _, upper = inputs
            lower = at.as_tensor_variable(lower) if lower is not None else None
            upper = at.as_tensor_variable(upper) if upper is not None else None
            return lower, upper

        interval = tr.Interval(bounds_fn=transform_params)
        model = self.build_model(pm.Triangular, {
            "lower": lower,
            "c": c,
            "upper": upper
        },
                                 size=size,
                                 transform=interval)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize("mu,kappa,size",
                             [(0.0, 1.0, 2), (-0.5, 5.5, (2, 3)),
                              (np.zeros(3), np.ones(3), (4, 3))])
    def test_vonmises(self, mu, kappa, size):
        model = self.build_model(pm.VonMises, {
            "mu": mu,
            "kappa": kappa
        },
                                 size=size,
                                 transform=tr.circular)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize("a,size", [(np.ones(2), None),
                                        (np.ones((2, 3)) * 0.5, None),
                                        (np.ones(3), (4, ))])
    def test_dirichlet(self, a, size):
        model = self.build_model(pm.Dirichlet, {"a": a},
                                 size=size,
                                 transform=tr.simplex)
        self.check_vectortransform_elementwise_logp(model)

    def test_normal_ordered(self):
        model = self.build_model(
            pm.Normal,
            {
                "mu": 0.0,
                "sigma": 1.0
            },
            size=3,
            initval=np.asarray([-1.0, 1.0, 4.0]),
            transform=tr.ordered,
        )
        self.check_vectortransform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "sigma,size",
        [
            (2.5, (2, )),
            (np.ones(3), (4, 3)),
        ],
    )
    def test_half_normal_ordered(self, sigma, size):
        initval = np.sort(np.abs(np.random.randn(*size)))
        model = self.build_model(
            pm.HalfNormal,
            {"sigma": sigma},
            size=size,
            initval=initval,
            transform=tr.Chain([tr.log, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model)

    @pytest.mark.parametrize("lam,size", [(2.5, (2, )), (np.ones(3), (4, 3))])
    def test_exponential_ordered(self, lam, size):
        initval = np.sort(np.abs(np.random.randn(*size)))
        model = self.build_model(
            pm.Exponential,
            {"lam": lam},
            size=size,
            initval=initval,
            transform=tr.Chain([tr.log, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "a,b,size",
        [
            (
                1.0,
                1.0,
                (2, ),
            ),
            (np.ones(3), np.ones(3), (4, 3)),
        ],
    )
    def test_beta_ordered(self, a, b, size):
        initval = np.sort(np.abs(np.random.rand(*size)))
        model = self.build_model(
            pm.Beta,
            {
                "alpha": a,
                "beta": b
            },
            size=size,
            initval=initval,
            transform=tr.Chain([tr.logodds, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "lower,upper,size",
        [(0.0, 1.0, (2, )),
         (pm.floatX(np.zeros(3)), pm.floatX(np.ones(3)), (4, 3))],
    )
    def test_uniform_ordered(self, lower, upper, size):
        def transform_params(*inputs):
            _, _, _, lower, upper = inputs
            lower = at.as_tensor_variable(lower) if lower is not None else None
            upper = at.as_tensor_variable(upper) if upper is not None else None
            return lower, upper

        interval = tr.Interval(bounds_fn=transform_params)

        initval = np.sort(np.abs(np.random.rand(*size)))
        model = self.build_model(
            pm.Uniform,
            {
                "lower": lower,
                "upper": upper
            },
            size=size,
            initval=initval,
            transform=tr.Chain([interval, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model)

    @pytest.mark.parametrize("mu,kappa,size",
                             [(0.0, 1.0, (2, )),
                              (np.zeros(3), np.ones(3), (4, 3))])
    def test_vonmises_ordered(self, mu, kappa, size):
        initval = np.sort(np.abs(np.random.rand(*size)))
        model = self.build_model(
            pm.VonMises,
            {
                "mu": mu,
                "kappa": kappa
            },
            size=size,
            initval=initval,
            transform=tr.Chain([tr.circular, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "lower,upper,size,transform",
        [
            (0.0, 1.0, (2, ), tr.simplex),
            (0.5, 5.5, (2, 3), tr.simplex),
            (np.zeros(3), np.ones(3),
             (4, 3), tr.Chain([tr.sum_to_1, tr.logodds])),
        ],
    )
    def test_uniform_other(self, lower, upper, size, transform):
        initval = np.ones(size) / size[-1]
        model = self.build_model(
            pm.Uniform,
            {
                "lower": lower,
                "upper": upper
            },
            size=size,
            initval=initval,
            transform=transform,
        )
        self.check_vectortransform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "mu,cov,size,shape",
        [
            (np.zeros(2), np.diag(np.ones(2)), None, (2, )),
            (np.zeros(3), np.diag(np.ones(3)), (4, ), (4, 3)),
        ],
    )
    def test_mvnormal_ordered(self, mu, cov, size, shape):
        initval = np.sort(np.random.randn(*shape))
        model = self.build_model(pm.MvNormal, {
            "mu": mu,
            "cov": cov
        },
                                 size=size,
                                 initval=initval,
                                 transform=tr.ordered)
        self.check_vectortransform_elementwise_logp(model)
Esempio n. 8
0
def test_chain_vector_transform():
    chain_tranf = tr.Chain([tr.logodds, tr.ordered])
    check_vector_transform(chain_tranf, UnitSortedVector(3))
Esempio n. 9
0
def test_chain_values():
    chain_tranf = tr.Chain([tr.logodds, tr.ordered])
    vals = get_values(chain_tranf, Vector(R, 5), at.dvector, np.zeros(5))
    close_to_logical(np.diff(vals) >= 0, True, tol)
Esempio n. 10
0
class TestElementWiseLogp(SeededTest):
    def build_model(self, distfam, params, size, transform, initval=None):
        if initval is not None:
            initval = pm.floatX(initval)
        with pm.Model() as m:
            distfam("x",
                    size=size,
                    transform=transform,
                    initval=initval,
                    **params)
        return m

    def check_transform_elementwise_logp(self, model):
        x = model.free_RVs[0]
        x0 = x.tag.value_var
        assert x.ndim == logpt(x, sum=False).ndim

        pt = model.initial_point
        array = np.random.randn(*pt[x0.name].shape)
        transform = x0.tag.transform
        logp_notrans = logpt(x,
                             transform.backward(array, *x.owner.inputs),
                             transformed=False)

        jacob_det = transform.log_jac_det(aesara.shared(array),
                                          *x.owner.inputs)
        assert logpt(x, sum=False).ndim == jacob_det.ndim

        v1 = logpt(x, array, jacobian=False).eval()
        v2 = logp_notrans.eval()
        close_to(v1, v2, tol)

    def check_vectortransform_elementwise_logp(self, model, vect_opt=0):
        x = model.free_RVs[0]
        x0 = x.tag.value_var
        # TODO: For some reason the ndim relations
        # dont hold up here. But final log-probablity
        # values are what we expected.
        # assert (x.ndim - 1) == logpt(x, sum=False).ndim

        pt = model.initial_point
        array = np.random.randn(*pt[x0.name].shape)
        transform = x0.tag.transform
        logp_nojac = logpt(x,
                           transform.backward(array, *x.owner.inputs),
                           transformed=False)

        jacob_det = transform.log_jac_det(aesara.shared(array),
                                          *x.owner.inputs)
        # assert logpt(x).ndim == jacob_det.ndim

        # Hack to get relative tolerance
        a = logpt(x, array.astype(aesara.config.floatX), jacobian=False).eval()
        b = logp_nojac.eval()
        close_to(a, b, np.abs(0.5 * (a + b) * tol))

    @pytest.mark.parametrize(
        "sd,size",
        [
            (2.5, 2),
            (5.0, (2, 3)),
            (np.ones(3) * 10.0, (4, 3)),
        ],
    )
    def test_half_normal(self, sd, size):
        model = self.build_model(pm.HalfNormal, {"sd": sd},
                                 size=size,
                                 transform=tr.log)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize("lam,size", [(2.5, 2), (5.0, (2, 3)),
                                          (np.ones(3), (4, 3))])
    def test_exponential(self, lam, size):
        model = self.build_model(pm.Exponential, {"lam": lam},
                                 size=size,
                                 transform=tr.log)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "a,b,size",
        [
            (1.0, 1.0, 2),
            (0.5, 0.5, (2, 3)),
            (np.ones(3), np.ones(3), (4, 3)),
        ],
    )
    def test_beta(self, a, b, size):
        model = self.build_model(pm.Beta, {
            "alpha": a,
            "beta": b
        },
                                 size=size,
                                 transform=tr.logodds)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "lower,upper,size",
        [
            (0.0, 1.0, 2),
            (0.5, 5.5, (2, 3)),
            (pm.floatX(np.zeros(3)), pm.floatX(np.ones(3)), (4, 3)),
        ],
    )
    def test_uniform(self, lower, upper, size):
        def transform_params(*inputs):
            _, _, _, lower, upper = inputs
            lower = at.as_tensor_variable(lower) if lower is not None else None
            upper = at.as_tensor_variable(upper) if upper is not None else None
            return lower, upper

        interval = tr.interval(transform_params)
        model = self.build_model(pm.Uniform, {
            "lower": lower,
            "upper": upper
        },
                                 size=size,
                                 transform=interval)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize(
        "lower, c, upper, size",
        [
            (0.0, 1.0, 2.0, 2),
            (-10, 0, 200, (2, 3)),
            (np.zeros(3), np.ones(3), np.ones(3), (4, 3)),
        ],
    )
    def test_triangular(self, lower, c, upper, size):
        def transform_params(*inputs):
            _, _, _, lower, _, upper = inputs
            lower = at.as_tensor_variable(lower) if lower is not None else None
            upper = at.as_tensor_variable(upper) if upper is not None else None
            return lower, upper

        interval = tr.interval(transform_params)
        model = self.build_model(pm.Triangular, {
            "lower": lower,
            "c": c,
            "upper": upper
        },
                                 size=size,
                                 transform=interval)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize("mu,kappa,size",
                             [(0.0, 1.0, 2), (-0.5, 5.5, (2, 3)),
                              (np.zeros(3), np.ones(3), (4, 3))])
    def test_vonmises(self, mu, kappa, size):
        model = self.build_model(pm.VonMises, {
            "mu": mu,
            "kappa": kappa
        },
                                 size=size,
                                 transform=tr.circular)
        self.check_transform_elementwise_logp(model)

    @pytest.mark.parametrize("a,size", [(np.ones(2), None),
                                        (np.ones((2, 3)) * 0.5, None),
                                        (np.ones(3), (4, ))])
    def test_dirichlet(self, a, size):
        model = self.build_model(pm.Dirichlet, {"a": a},
                                 size=size,
                                 transform=tr.simplex)
        self.check_vectortransform_elementwise_logp(model, vect_opt=1)

    def test_normal_ordered(self):
        model = self.build_model(
            pm.Normal,
            {
                "mu": 0.0,
                "sd": 1.0
            },
            size=3,
            initval=np.asarray([-1.0, 1.0, 4.0]),
            transform=tr.ordered,
        )
        self.check_vectortransform_elementwise_logp(model, vect_opt=0)

    @pytest.mark.parametrize(
        "sd,size",
        [
            (2.5, (2, )),
            (np.ones(3), (4, 3)),
        ],
    )
    def test_half_normal_ordered(self, sd, size):
        initval = np.sort(np.abs(np.random.randn(*size)))
        model = self.build_model(
            pm.HalfNormal,
            {"sd": sd},
            size=size,
            initval=initval,
            transform=tr.Chain([tr.log, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model, vect_opt=0)

    @pytest.mark.parametrize("lam,size", [(2.5, (2, )), (np.ones(3), (4, 3))])
    def test_exponential_ordered(self, lam, size):
        initval = np.sort(np.abs(np.random.randn(*size)))
        model = self.build_model(
            pm.Exponential,
            {"lam": lam},
            size=size,
            initval=initval,
            transform=tr.Chain([tr.log, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model, vect_opt=0)

    @pytest.mark.parametrize(
        "a,b,size",
        [
            (
                1.0,
                1.0,
                (2, ),
            ),
            (np.ones(3), np.ones(3), (4, 3)),
        ],
    )
    def test_beta_ordered(self, a, b, size):
        initval = np.sort(np.abs(np.random.rand(*size)))
        model = self.build_model(
            pm.Beta,
            {
                "alpha": a,
                "beta": b
            },
            size=size,
            initval=initval,
            transform=tr.Chain([tr.logodds, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model, vect_opt=0)

    @pytest.mark.parametrize(
        "lower,upper,size",
        [(0.0, 1.0, (2, )),
         (pm.floatX(np.zeros(3)), pm.floatX(np.ones(3)), (4, 3))],
    )
    def test_uniform_ordered(self, lower, upper, size):
        def transform_params(*inputs):
            _, _, _, lower, upper = inputs
            lower = at.as_tensor_variable(lower) if lower is not None else None
            upper = at.as_tensor_variable(upper) if upper is not None else None
            return lower, upper

        interval = tr.interval(transform_params)

        initval = np.sort(np.abs(np.random.rand(*size)))
        model = self.build_model(
            pm.Uniform,
            {
                "lower": lower,
                "upper": upper
            },
            size=size,
            initval=initval,
            transform=tr.Chain([interval, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model, vect_opt=1)

    @pytest.mark.parametrize("mu,kappa,size",
                             [(0.0, 1.0, (2, )),
                              (np.zeros(3), np.ones(3), (4, 3))])
    def test_vonmises_ordered(self, mu, kappa, size):
        initval = np.sort(np.abs(np.random.rand(*size)))
        model = self.build_model(
            pm.VonMises,
            {
                "mu": mu,
                "kappa": kappa
            },
            size=size,
            initval=initval,
            transform=tr.Chain([tr.circular, tr.ordered]),
        )
        self.check_vectortransform_elementwise_logp(model, vect_opt=0)

    @pytest.mark.parametrize(
        "lower,upper,size,transform",
        [
            (0.0, 1.0, (2, ), tr.simplex),
            (0.5, 5.5, (2, 3), tr.simplex),
            (np.zeros(3), np.ones(3),
             (4, 3), tr.Chain([tr.sum_to_1, tr.logodds])),
        ],
    )
    def test_uniform_other(self, lower, upper, size, transform):
        initval = np.ones(size) / size[-1]
        model = self.build_model(
            pm.Uniform,
            {
                "lower": lower,
                "upper": upper
            },
            size=size,
            initval=initval,
            transform=transform,
        )
        self.check_vectortransform_elementwise_logp(model, vect_opt=1)

    @pytest.mark.parametrize(
        "mu,cov,size,shape",
        [
            (np.zeros(2), np.diag(np.ones(2)), None, (2, )),
            (np.zeros(3), np.diag(np.ones(3)), (4, ), (4, 3)),
        ],
    )
    def test_mvnormal_ordered(self, mu, cov, size, shape):
        initval = np.sort(np.random.randn(*shape))
        model = self.build_model(pm.MvNormal, {
            "mu": mu,
            "cov": cov
        },
                                 size=size,
                                 initval=initval,
                                 transform=tr.ordered)
        self.check_vectortransform_elementwise_logp(model, vect_opt=1)