|
13 | 13 | from .test_distributions import (
|
14 | 14 | build_model, Domain, product, R, Rplus, Rplusbig, Rplusdunif,
|
15 | 15 | Unit, Nat, NatSmall, I, Simplex, Vector, PdMatrix,
|
16 |
| - PdMatrixChol, PdMatrixCholUpper, RealMatrix |
| 16 | + PdMatrixChol, PdMatrixCholUpper, RealMatrix, RandomPdMatrix |
17 | 17 | )
|
18 | 18 |
|
19 | 19 |
|
20 | 20 | def pymc3_random(dist, paramdomains, ref_rand, valuedomain=Domain([0]),
|
21 |
| - size=10000, alpha=0.05, fails=10, extra_args=None): |
| 21 | + size=10000, alpha=0.05, fails=10, extra_args=None, |
| 22 | + model_args=None): |
| 23 | + if model_args is None: |
| 24 | + model_args = {} |
22 | 25 | model = build_model(dist, valuedomain, paramdomains, extra_args)
|
23 | 26 | domains = paramdomains.copy()
|
24 | 27 | for pt in product(domains, n_samples=100):
|
25 | 28 | pt = pm.Point(pt, model=model)
|
| 29 | + pt.update(model_args) |
26 | 30 | p = alpha
|
27 | 31 | # Allow KS test to fail (i.e., the samples be different)
|
28 | 32 | # a certain number of times. Crude, but necessary.
|
@@ -586,6 +590,54 @@ def ref_rand_uchol(size, mu, rowchol, colchol):
|
586 | 590 | # extra_args={'lower': False}
|
587 | 591 | # )
|
588 | 592 |
|
| 593 | + def test_kronecker_normal(self): |
| 594 | + def ref_rand(size, mu, covs, sigma): |
| 595 | + cov = pm.math.kronecker(covs[0], covs[1]).eval() |
| 596 | + cov += sigma**2 * np.identity(cov.shape[0]) |
| 597 | + return st.multivariate_normal.rvs(mean=mu, cov=cov, size=size) |
| 598 | + |
| 599 | + def ref_rand_chol(size, mu, chols, sigma): |
| 600 | + covs = [np.dot(chol, chol.T) for chol in chols] |
| 601 | + return ref_rand(size, mu, covs, sigma) |
| 602 | + |
| 603 | + def ref_rand_evd(size, mu, evds, sigma): |
| 604 | + covs = [] |
| 605 | + for eigs, Q in evds: |
| 606 | + covs.append(np.dot(Q, np.dot(np.diag(eigs), Q.T))) |
| 607 | + return ref_rand(size, mu, covs, sigma) |
| 608 | + |
| 609 | + sizes = [2, 3] |
| 610 | + sigmas = [0, 1] |
| 611 | + for n, sigma in zip(sizes, sigmas): |
| 612 | + N = n**2 |
| 613 | + covs = [RandomPdMatrix(n), RandomPdMatrix(n)] |
| 614 | + chols = list(map(np.linalg.cholesky, covs)) |
| 615 | + evds = list(map(np.linalg.eigh, covs)) |
| 616 | + dom = Domain([np.random.randn(N)*0.1], edges=(None, None), shape=N) |
| 617 | + mu = Domain([np.random.randn(N)*0.1], edges=(None, None), shape=N) |
| 618 | + |
| 619 | + std_args = {'mu': mu} |
| 620 | + cov_args = {'covs': covs} |
| 621 | + chol_args = {'chols': chols} |
| 622 | + evd_args = {'evds': evds} |
| 623 | + if sigma is not None and sigma != 0: |
| 624 | + std_args['sigma'] = Domain([sigma], edges=(None, None)) |
| 625 | + else: |
| 626 | + for args in [cov_args, chol_args, evd_args]: |
| 627 | + args['sigma'] = sigma |
| 628 | + |
| 629 | + pymc3_random( |
| 630 | + pm.KroneckerNormal, std_args, valuedomain=dom, |
| 631 | + ref_rand=ref_rand, extra_args=cov_args, model_args=cov_args) |
| 632 | + pymc3_random( |
| 633 | + pm.KroneckerNormal, std_args, valuedomain=dom, |
| 634 | + ref_rand=ref_rand_chol, extra_args=chol_args, |
| 635 | + model_args=chol_args) |
| 636 | + pymc3_random( |
| 637 | + pm.KroneckerNormal, std_args, valuedomain=dom, |
| 638 | + ref_rand=ref_rand_evd, extra_args=evd_args, |
| 639 | + model_args=evd_args) |
| 640 | + |
589 | 641 | def test_mv_t(self):
|
590 | 642 | def ref_rand(size, nu, Sigma, mu):
|
591 | 643 | normal = st.multivariate_normal.rvs(cov=Sigma, size=size).T
|
|
0 commit comments