|
1 | 1 | import theano.tensor as tt |
2 | 2 | import numpy as np |
3 | 3 | from numpy.random import multivariate_normal |
4 | | - |
5 | 4 | import pymc3 as pm |
6 | 5 |
|
7 | 6 | # Generate some multivariate normal data: |
8 | 7 | n_obs = 1000 |
9 | 8 |
|
10 | 9 | # Mean values: |
11 | | -mu = np.linspace(0, 2, num=4) |
12 | | -n_var = len(mu) |
| 10 | +mu_r = np.linspace(0, 2, num=4) |
| 11 | +n_var = len(mu_r) |
13 | 12 |
|
14 | 13 | # Standard deviations: |
15 | 14 | stds = np.ones(4) / 2.0 |
16 | 15 |
|
17 | 16 | # Correlation matrix of 4 variables: |
18 | | -corr = np.array([[1., 0.75, 0., 0.15], |
19 | | - [0.75, 1., -0.06, 0.19], |
20 | | - [0., -0.06, 1., -0.04], |
21 | | - [0.15, 0.19, -0.04, 1.]]) |
22 | | -cov_matrix = np.diag(stds).dot(corr.dot(np.diag(stds))) |
23 | | - |
24 | | -dataset = multivariate_normal(mu, cov_matrix, size=n_obs) |
25 | | - |
| 17 | +corr_r = np.array([[1., 0.75, 0., 0.15], |
| 18 | + [0.75, 1., -0.06, 0.19], |
| 19 | + [0., -0.06, 1., -0.04], |
| 20 | + [0.15, 0.19, -0.04, 1.]]) |
| 21 | +cov_matrix = np.diag(stds).dot(corr_r.dot(np.diag(stds))) |
26 | 22 |
|
27 | | -# In order to convert the upper triangular correlation values to a complete |
28 | | -# correlation matrix, we need to construct an index matrix: |
29 | | -n_elem = int(n_var * (n_var - 1) / 2) |
30 | | -tri_index = np.zeros([n_var, n_var], dtype=int) |
31 | | -tri_index[np.triu_indices(n_var, k=1)] = np.arange(n_elem) |
32 | | -tri_index[np.triu_indices(n_var, k=1)[::-1]] = np.arange(n_elem) |
| 23 | +dataset = multivariate_normal(mu_r, cov_matrix, size=n_obs) |
33 | 24 |
|
34 | 25 | with pm.Model() as model: |
35 | 26 |
|
36 | 27 | mu = pm.Normal('mu', mu=0, sd=1, shape=n_var) |
37 | 28 |
|
38 | | - # We can specify separate priors for sigma and the correlation matrix: |
39 | | - sigma = pm.Uniform('sigma', shape=n_var) |
40 | | - corr_triangle = pm.LKJCorr('corr', n=1, p=n_var) |
41 | | - corr_matrix = corr_triangle[tri_index] |
42 | | - corr_matrix = tt.fill_diagonal(corr_matrix, 1) |
| 29 | + # Note that we access the distribution for the standard |
| 30 | + # deviations, and do not create a new random variable. |
| 31 | + sd_dist = pm.HalfCauchy.dist(beta=2.5) |
| 32 | + packed_chol = pm.LKJCholeskyCov('chol_cov', n=n_var, eta=1, sd_dist=sd_dist) |
| 33 | + # compute the covariance matrix |
| 34 | + chol = pm.expand_packed_triangular(n_var, packed_chol, lower=True) |
| 35 | + cov = tt.dot(chol, chol.T) |
43 | 36 |
|
44 | | - cov_matrix = tt.diag(sigma).dot(corr_matrix.dot(tt.diag(sigma))) |
| 37 | + # Extract the standard deviations etc |
| 38 | + sd = pm.Deterministic('sd', tt.sqrt(tt.diag(cov))) |
| 39 | + corr = tt.diag(sd**-1).dot(cov.dot(tt.diag(sd**-1))) |
| 40 | + r = pm.Deterministic('r', corr[np.triu_indices(n_var, k=1)]) |
45 | 41 |
|
46 | | - like = pm.MvNormal('likelihood', mu=mu, cov=cov_matrix, observed=dataset) |
| 42 | + like = pm.MvNormal('likelihood', mu=mu, chol=chol, observed=dataset) |
47 | 43 |
|
48 | 44 |
|
49 | 45 | def run(n=1000): |
50 | 46 | if n == "short": |
51 | 47 | n = 50 |
52 | 48 | with model: |
53 | | - start = pm.find_MAP() |
54 | | - step = pm.NUTS(scaling=start) |
55 | | - trace = pm.sample(n, step=step, start=start) |
56 | | - return trace |
| 49 | + trace = pm.sample(n) |
| 50 | + pm.traceplot(trace, varnames=['mu', 'r'], |
| 51 | + lines={'mu': mu_r, 'r': corr_r[np.triu_indices(n_var, k=1)]}) |
57 | 52 |
|
58 | 53 | if __name__ == '__main__': |
59 | 54 | run() |
0 commit comments