============================================================================================================
MORE: heteroscedastic error covariance matrix, https://rpubs.com/sherloconan/1075410
THIS: weakly informative prior for covariance matrices, https://rpubs.com/sherloconan/1081051
In Loftus and Masson (1994), some to-be-recalled 20-word lists are presented at a rate of 1, 2, or 5 sec per word. Suppose that the hypothetical experiment is run as a one-way within-subject (repeated-measures) design with three conditions.
dat <- matrix(c(10,6,11,22,16,15,1,12,9,8,
13,8,14,23,18,17,1,15,12,9,
13,8,14,25,20,17,4,17,12,12), ncol=3,
dimnames=list(paste0("s",1:10), paste0("Level",1:3))) #wide data format
# dat <- dat * 100
df <- data.frame("ID"=factor(rep(paste0("s",1:10), 3)),
"Level"=factor(rep(paste0("Level",1:3), each=10)),
"Response"=c(dat)) #long data format
Or, testing a simulated data set.
mu.b <- 100; sigma.b <- 20; n <- 24
delta.mu <- 6.7; sigma.e <- 6.67 #rho=.9, power=.8
set.seed(277)
TrueScore <- rnorm(n, mu.b, sigma.b)
eij1 <- rnorm(n, 0, sigma.e)
eij2 <- rnorm(n, 0, sigma.e)
dat <- cbind("Level1"=TrueScore+eij1+delta.mu,
"Level2"=TrueScore+eij2)
# dat <- dat * 100
df <- data.frame("ID"=factor(rep(paste0("s",1:n), 2)),
"Level"=factor(rep(c("Level1", "Level2"), each=n)),
"Response"=c(dat))
## The Bayes factors will be computed for the simulated data (in the second chunk).
Method: Constructing the Jeffreys-Zellner-Siow (JZS) Bayes factor.
\[\begin{align*} \tag{1} \mathcal{M}_1:\ Y_{ij}&=\mu+\sigma_\epsilon(d_i+b_j)+\epsilon_{ij}\\ \text{versus}\quad\mathcal{M}_0:\ Y_{ij}&=\mu+\sigma_\epsilon b_j+\epsilon_{ij},\qquad\epsilon_{ij}\overset{\text{i.i.d.}}{\sim}\mathcal{N}(0,\sigma_\epsilon^2) \text{ for } i=1,\dotsb,a;\ j=1,\dotsb,n. \end{align*}\]
\[\begin{equation} \tag{2} \pi(\mu,\sigma_\epsilon^2)\propto 1/\ \sigma_\epsilon^{2} \end{equation}\]
\[\begin{equation} \tag{3} d_i^\star\mid g\overset{\text{i.i.d.}}{\sim}\mathcal{N}(0,g) \end{equation}\]
\[\begin{equation} \tag{4} g\sim\text{Scale-inv-}\chi^2(1,h^2) \end{equation}\]
\[\begin{equation} \tag{5} (d_1^\star,\dotsb,d_{a-1}^\star)=(d_1,\dotsb,d_a)\cdot\mathbf{Q} \end{equation}\]
\[\begin{equation} \tag{6} \mathbf{I}_a-\frac{1}{a}\mathbf{J}_a=\mathbf{Q}\cdot\mathbf{Q}^\top \end{equation}\]
\[\begin{equation} \tag{7} b_j\mid g_b\overset{\text{i.i.d.}}{\sim}\mathcal{N}(0,g_b) \end{equation}\]
\[\begin{equation} \tag{8} g_b\sim\text{Scale-inv-}\chi^2(1,h_b^2) \end{equation}\]
\(\mathbf{Q}\) is an \(a\times(a-1)\) matrix of the \(a-1\) eigenvectors of unit length corresponding to the nonzero eigenvalues of the left side term in (6). For example, the projected main effect \(d^\star=(d_1-d_2)/\sqrt{2}\) when \(a=2\). In the other direction (given \(d_1+d_2=0\)), \(d_1=d^\star/\sqrt{2}\) and \(d_2=-d^\star/\sqrt{2}\).
set.seed(277)
(JZS_BF <- anovaBF(Response~Level+ID, data=df, whichRandom="ID", progress=F))
## Bayes factor analysis
## --------------
## [1] Level + ID : 11.02461 ±0.67%
##
## Against denominator:
## Response ~ ID
## ---
## Bayes factor type: BFlinearModel, JZS
Note: Fixed effects are assumed. See the discussion here.
Markov chain Monte Carlo (MCMC) diagnostics. Plots of iterations versus sampled values for each variable in the chain.
set.seed(277)
draws <- posterior(JZS_BF, iterations=1e5, progress=F)
summary(draws)
##
## Iterations = 1:1e+05
## Thinning interval = 1
## Number of chains = 1
## Sample size per chain = 1e+05
##
## 1. Empirical mean and standard deviation for each variable,
## plus standard error of the mean:
##
## Mean SD Naive SE Time-series SE
## mu 108.7277 5.172 0.016354 0.016354
## Level-Level1 3.2648 1.197 0.003786 0.004314
## Level-Level2 -3.2648 1.197 0.003786 0.004314
## ID-s1 30.4422 7.557 0.023898 0.025012
## ID-s10 -19.4938 7.550 0.023875 0.023875
## ID-s11 -0.8085 7.493 0.023695 0.023576
## ID-s12 8.1456 7.522 0.023788 0.023788
## ID-s13 45.9977 7.635 0.024143 0.026187
## ID-s14 -28.2025 7.538 0.023838 0.024622
## ID-s15 -12.8174 7.539 0.023840 0.023840
## ID-s16 23.6346 7.549 0.023872 0.024428
## ID-s17 4.3252 7.521 0.023784 0.023784
## ID-s18 -3.2712 7.523 0.023791 0.023791
## ID-s19 14.9474 7.555 0.023890 0.024280
## ID-s2 10.1977 7.531 0.023814 0.023814
## ID-s20 -13.9946 7.550 0.023874 0.023874
## ID-s21 -21.1130 7.571 0.023942 0.024498
## ID-s22 -19.3361 7.549 0.023873 0.024044
## ID-s23 35.0892 7.594 0.024015 0.025727
## ID-s24 7.3267 7.553 0.023886 0.023886
## ID-s3 -18.7996 7.534 0.023825 0.024219
## ID-s4 31.0016 7.584 0.023983 0.024427
## ID-s5 -33.4762 7.580 0.023969 0.025458
## ID-s6 22.1565 7.528 0.023805 0.024781
## ID-s7 -29.3490 7.573 0.023948 0.024707
## ID-s8 -0.2011 7.526 0.023800 0.023937
## ID-s9 -32.1534 7.573 0.023946 0.024887
## sig2 70.0214 23.074 0.072968 0.185488
## g_Level 5.4399 478.834 1.514206 1.514206
## g_ID 9.5521 4.501 0.014235 0.029968
##
## 2. Quantiles for each variable:
##
## 2.5% 25% 50% 75% 97.5%
## mu 98.51260 105.3381 108.7324 112.119 118.9246
## Level-Level1 0.91212 2.4740 3.2605 4.052 5.6351
## Level-Level2 -5.63512 -4.0518 -3.2605 -2.474 -0.9121
## ID-s1 15.59911 25.3911 30.4842 35.481 45.2401
## ID-s10 -34.41346 -24.4874 -19.4985 -14.513 -4.5370
## ID-s11 -15.50512 -5.8010 -0.8069 4.185 13.8785
## ID-s12 -6.60409 3.1258 8.1533 13.152 22.9883
## ID-s13 30.90195 40.9262 46.0031 51.035 60.9876
## ID-s14 -43.06944 -33.2252 -28.2251 -23.183 -13.3536
## ID-s15 -27.65613 -17.8460 -12.8154 -7.811 2.0251
## ID-s16 8.76354 18.6665 23.6514 28.628 38.5223
## ID-s17 -10.47225 -0.6513 4.3171 9.299 19.1054
## ID-s18 -17.93953 -8.2818 -3.2555 1.701 11.5917
## ID-s19 0.01507 9.9408 14.9718 19.959 29.7518
## ID-s2 -4.62003 5.1722 10.2083 15.219 25.0096
## ID-s20 -28.87834 -19.0018 -13.9904 -8.952 0.8958
## ID-s21 -36.06758 -26.1364 -21.1057 -16.090 -6.1758
## ID-s22 -34.18702 -24.4105 -19.3543 -14.309 -4.4714
## ID-s23 20.04937 30.0764 35.0963 40.140 49.9902
## ID-s24 -7.58871 2.3097 7.3593 12.320 22.2375
## ID-s3 -33.67105 -23.8061 -18.7900 -13.807 -3.9780
## ID-s4 15.99679 25.9912 31.0130 36.031 45.9018
## ID-s5 -48.36228 -38.5250 -33.5321 -28.437 -18.4998
## ID-s6 7.28988 17.1852 22.1697 27.173 36.9708
## ID-s7 -44.14209 -34.4148 -29.3593 -24.302 -14.3894
## ID-s8 -14.97812 -5.1907 -0.2325 4.780 14.6205
## ID-s9 -47.01976 -37.1770 -32.1381 -27.148 -17.1065
## sig2 38.37888 53.9211 65.7141 81.237 127.3316
## g_Level 0.06451 0.2002 0.4255 1.057 12.2281
## g_ID 3.45870 6.4077 8.6860 11.696 20.7292
plot(draws, cex.lab=1.5, cex.axis=1.5, cex.main=1.5, cex.sub=1.5)
\[\begin{align*} \tag{a} \mathcal{M}_1:\ Y_{ij}&=\mu+t_i+\epsilon_{ij}\\ \text{versus}\quad\mathcal{M}_0:\ Y_{ij}&=\mu+\epsilon_{ij}\\ (\epsilon_{1j},\dotsb,\epsilon_{aj})^\top&\overset{\text{i.i.d.}}{\sim}\mathbf{\mathcal{N}}_a(\mathbf{0},\mathbf{\Sigma})\qquad\text{for } i=1,\dotsb,a;\ j=1,\dotsb,n. \end{align*}\]
\[\begin{equation} \tag{b} \pi(\mu)\propto 1 \end{equation}\]
\[\begin{equation} \tag{c} \mathbf{\Sigma}\sim\mathcal{W}\left(\frac{\mathbf{I}_{a}}{2\theta},\ a+2\right),\quad\theta=10^{-4} \end{equation}\]
\[\begin{equation} \tag{3} t_i^\star\mid g\overset{\text{i.i.d.}}{\sim}\mathcal{N}(0,g) \end{equation}\]
\[\begin{equation} \tag{4} g\sim\text{Scale-inv-}\chi^2(1,h^2) \end{equation}\]
\[\begin{equation} \tag{5} (t_1^\star,\dotsb,t_{a-1}^\star)=(t_1,\dotsb,t_a)\cdot\mathbf{Q} \end{equation}\]
\[\begin{equation} \tag{6} \mathbf{I}_a-\frac{1}{a}\mathbf{J}_a=\mathbf{Q}\cdot\mathbf{Q}^\top \end{equation}\]
\(\mathbf{Q}\) is an \(a\times(a-1)\) matrix of the \(a-1\) eigenvectors of unit length corresponding to the nonzero eigenvalues of the left side term in (6). For example, the projected main effect \(t^\star=(t_1-t_2)/\sqrt{2}\) when \(a=2\). In the other direction (given \(t_1+t_2=0\)), \(t_1=t^\star/\sqrt{2}\) and \(t_2=-t^\star/\sqrt{2}\).
computeQ <- function(C) {
#' reduced parametrization for the fixed treatment effects
S <- diag(C) - matrix(1, nrow = C, ncol = C) / C
e <- qr(S)
Q <- qr.Q(e) %*% diag(sign(diag(qr.R(e))))
Q[, which(abs(e$qraux) > 1e-3), drop = FALSE]
}
Specify the full model \(\mathcal{M}_1\) in (a).
stancodeM1 initially declares the reduced fixed treatment
effects tf. Note that the effects are not
standardized (\(d_i=t_i/\sigma_\epsilon\)) but the data are
scaled. Compile and fit the model in Stan.
Note that to compute the (log) marginal likelihood
for a Stan model, we need to specify the model in a certain way. Instead
of using “~” signs for specifying distributions, we need to directly use
the (log) density functions. The reason for this is that when using the
“~” sign, constant terms are dropped which are not needed for sampling
from the posterior. However, for computing the marginal likelihood,
these constants need to be retained. For instance, instead of writing
y ~ normal(mu, sigma); we would need to write
target += normal_lpdf(y | mu, sigma); (Gronau,
2021). See also the discussion regarding the implicit
uniform prior for computing the log marginal likelihood.
stancodeM1 <- "
data {
int<lower=1> N; // number of subjects
int<lower=2> C; // number of conditions
// vector[C] Y[N]; // responses [removed features]
array[N] vector[C] Y; // responses [Stan 2.26+ syntax for array declarations]
matrix[C,C-1] P; // projecting C-1 fixed effects into C
real<lower=0> ht; // scale parameter of the variance of the reduced treatment effect
matrix[C,C] V; // scale matrix of the Wishart prior
real lwr; // lower bound for the grand mean
real upr; // upper bound for the grand mean
}
parameters {
real<lower=lwr, upper=upr> mu; // grand mean
cov_matrix[C] Sigma; // error covariance matrix
real<lower=0> gt; // variance of the reduced treatment effect
vector[C-1] tf; // reduced treatment effect
}
transformed parameters {
vector[C] t; // treatment effect
t = P * tf;
}
model {
target += uniform_lpdf(mu | lwr, upr);
target += wishart_lpdf(Sigma | C+2, V); // Chung et al. (2015)
target += scaled_inv_chi_square_lpdf(gt | 1, ht);
target += normal_lpdf(tf | 0, sqrt(gt));
for (k in 1:N) {
target += multi_normal_lpdf(Y[k] | mu + t, Sigma);
}
}"
stanmodelM1 <- stan_model(model_code=stancodeM1)
datalistM1 <- list("N"=nrow(dat), "C"=ncol(dat),
"Y"=dat/sd(dat), #scale the data
"P"=computeQ(ncol(dat)), "ht"=.5,
"V"=diag(ncol(dat))*5E3)
datalistM1$lwr <- mean(datalistM1[["Y"]])-6*sd(datalistM1[["Y"]]) # -6 * 1
datalistM1$upr <- mean(datalistM1[["Y"]])+6*sd(datalistM1[["Y"]])
stanfitM1 <- sampling(stanmodelM1, data=datalistM1,
iter=50000, warmup=10000, chains=4, seed=277, refresh=0)
rstan::summary(stanfitM1)[[1]] %>% kable(digits=4) %>% kable_classic(full_width=F)
| mean | se_mean | sd | 2.5% | 25% | 50% | 75% | 97.5% | n_eff | Rhat | |
|---|---|---|---|---|---|---|---|---|---|---|
| mu | 4.2847 | 0.0007 | 0.2395 | 3.8098 | 4.1292 | 4.2842 | 4.4402 | 4.7564 | 129317.57 | 1 |
| Sigma[1,1] | 1.4030 | 0.0020 | 0.5306 | 0.7124 | 1.0389 | 1.2956 | 1.6402 | 2.7177 | 70584.72 | 1 |
| Sigma[1,2] | 1.3021 | 0.0020 | 0.5175 | 0.6281 | 0.9473 | 1.1964 | 1.5355 | 2.5851 | 67199.80 | 1 |
| Sigma[2,1] | 1.3021 | 0.0020 | 0.5175 | 0.6281 | 0.9473 | 1.1964 | 1.5355 | 2.5851 | 67199.80 | 1 |
| Sigma[2,2] | 1.4703 | 0.0021 | 0.5577 | 0.7463 | 1.0881 | 1.3564 | 1.7211 | 2.8531 | 69917.23 | 1 |
| gt | 1.7221 | 0.2270 | 56.3103 | 0.0393 | 0.1061 | 0.2134 | 0.5135 | 5.8548 | 61547.46 | 1 |
| tf[1] | 0.1992 | 0.0002 | 0.0740 | 0.0518 | 0.1510 | 0.1995 | 0.2478 | 0.3441 | 131586.40 | 1 |
| t[1] | 0.1409 | 0.0001 | 0.0523 | 0.0366 | 0.1067 | 0.1410 | 0.1753 | 0.2433 | 131586.40 | 1 |
| t[2] | -0.1409 | 0.0001 | 0.0523 | -0.2433 | -0.1753 | -0.1410 | -0.1067 | -0.0366 | 131586.40 | 1 |
| lp__ | -91.0545 | 0.0080 | 1.9080 | -95.6979 | -92.0644 | -90.6942 | -89.6523 | -88.4253 | 56227.93 | 1 |
mean(dat/sd(dat))
## [1] 4.283763
cov(dat/sd(dat))
## Level1 Level2
## Level1 0.9757775 0.9058127
## Level2 0.9058127 1.0230817
Chung, Y., Gelman, A., Rabe-Hesketh, S., Liu, J., & Dorie, V. (2015). Weakly informative prior for point estimation of covariance matrices in hierarchical models. Journal of Educational and Behavioral Statistics, 40, 136-157. https://doi.org/10.3102/1076998615570945
\[\begin{align*} \tag{a} \mathcal{M}_1:\ Y_{ij}&=\mu+t_i+\epsilon_{ij}\\ \text{versus}\quad\mathcal{M}_0:\ Y_{ij}&=\mu+\epsilon_{ij}\\ (\epsilon_{1j},\dotsb,\epsilon_{aj})^\top&\overset{\text{i.i.d.}}{\sim}\mathbf{\mathcal{N}}_a(\mathbf{0},\mathbf{\Sigma})\qquad\text{for } i=1,\dotsb,a;\ j=1,\dotsb,n. \end{align*}\]
\[\begin{equation} \tag{b} \pi(\mu)\propto 1 \end{equation}\]
\[\begin{equation} \tag{c} \mathbf{\Sigma}\sim\mathcal{W}\left(\frac{\mathbf{I}_{a}}{2\theta},\ a+2\right),\quad\theta=10^{-4} \end{equation}\]
\[\begin{equation} \tag{3} t_i^\star\mid g\overset{\text{i.i.d.}}{\sim}\mathcal{N}(0,g) \end{equation}\]
\[\begin{equation} \tag{4} g\sim\text{Scale-inv-}\chi^2(1,h^2) \end{equation}\]
\[\begin{equation} \tag{5} (t_1^\star,\dotsb,t_{a-1}^\star)=(t_1,\dotsb,t_a)\cdot\mathbf{Q} \end{equation}\]
\[\begin{equation} \tag{6} \mathbf{I}_a-\frac{1}{a}\mathbf{J}_a=\mathbf{Q}\cdot\mathbf{Q}^\top \end{equation}\]
\(\mathbf{Q}\) is an \(a\times(a-1)\) matrix of the \(a-1\) eigenvectors of unit length corresponding to the nonzero eigenvalues of the left side term in (6). For example, the projected main effect \(t^\star=(t_1-t_2)/\sqrt{2}\) when \(a=2\). In the other direction (given \(t_1+t_2=0\)), \(t_1=t^\star/\sqrt{2}\) and \(t_2=-t^\star/\sqrt{2}\).
Specify the null model \(\mathcal{M}_0\) in (a). Compile and fit the model in Stan.
stancodeM0 <- "
data {
int<lower=1> N; // number of subjects
int<lower=2> C; // number of conditions
// vector[C] Y[N]; // responses [removed features]
array[N] vector[C] Y; // responses [Stan 2.26+ syntax for array declarations]
matrix[C,C] V; // scale matrix of the Wishart prior
real lwr; // lower bound for the grand mean
real upr; // upper bound for the grand mean
}
parameters {
real<lower=lwr, upper=upr> mu; // grand mean
cov_matrix[C] Sigma; // error covariance matrix
}
transformed parameters {
vector[C] muS; // grand mean vector
for (i in 1:C) {
muS[i] = mu;
}
}
model {
target += uniform_lpdf(mu | lwr, upr);
target += wishart_lpdf(Sigma | C+2, V); // Chung et al. (2015)
for (k in 1:N) {
target += multi_normal_lpdf(Y[k] | muS, Sigma);
}
}"
stanmodelM0 <- stan_model(model_code=stancodeM0)
stanfitM0 <- sampling(stanmodelM0, data=datalistM1[-c(4,5)],
iter=50000, warmup=10000, chains=4, seed=277, refresh=0)
rstan::summary(stanfitM0)[[1]] %>% kable(digits=4) %>% kable_classic(full_width=F)
| mean | se_mean | sd | 2.5% | 25% | 50% | 75% | 97.5% | n_eff | Rhat | |
|---|---|---|---|---|---|---|---|---|---|---|
| mu | 4.3193 | 0.0010 | 0.2810 | 3.7633 | 4.1363 | 4.3197 | 4.5019 | 4.8739 | 83212.88 | 1 |
| Sigma[1,1] | 1.4514 | 0.0024 | 0.5728 | 0.7237 | 1.0620 | 1.3316 | 1.7005 | 2.8900 | 58230.87 | 1 |
| Sigma[1,2] | 1.3107 | 0.0024 | 0.5467 | 0.6070 | 0.9390 | 1.1985 | 1.5522 | 2.6772 | 53452.35 | 1 |
| Sigma[2,1] | 1.3107 | 0.0024 | 0.5467 | 0.6070 | 0.9390 | 1.1985 | 1.5522 | 2.6772 | 53452.35 | 1 |
| Sigma[2,2] | 1.5444 | 0.0026 | 0.6138 | 0.7630 | 1.1282 | 1.4153 | 1.8111 | 3.0858 | 55762.98 | 1 |
| muS[1] | 4.3193 | 0.0010 | 0.2810 | 3.7633 | 4.1363 | 4.3197 | 4.5019 | 4.8739 | 83212.88 | 1 |
| muS[2] | 4.3193 | 0.0010 | 0.2810 | 3.7633 | 4.1363 | 4.3197 | 4.5019 | 4.8739 | 83212.88 | 1 |
| lp__ | -92.3540 | 0.0066 | 1.5162 | -96.1960 | -93.0836 | -92.0091 | -91.2473 | -90.4749 | 52910.61 | 1 |
mean(dat/sd(dat))
## [1] 4.283763
cov(dat/sd(dat))
## Level1 Level2
## Level1 0.9757775 0.9058127
## Level2 0.9058127 1.0230817
The newly proposed models in (a): (i) do not include an explicit subject random effects term, (ii) introduce a more general structure of the error term, (iii) do not standardize the treatment effects, and (iv) scale the data.
Compute log marginal likelihoods for full and null models via bridge sampling. Then, \(\textit{BF}_{10}=\frac{p(\text{Data}\ \mid\ \mathcal{M}_1)}{p(\text{Data}\ \mid\ \mathcal{M}_0)}\).
M1 <- bridge_sampler(stanfitM1, silent=T)
summary(M1)
##
## Bridge sampling log marginal likelihood estimate
## (method = "normal", repetitions = 1):
##
## -93.32558
##
## Error Measures:
##
## Relative Mean-Squared Error: 1.887701e-06
## Coefficient of Variation: 0.001373936
## Percentage Error: 0%
##
## Note:
## All error measures are approximate.
M0 <- bridge_sampler(stanfitM0, silent=T)
summary(M0)
##
## Bridge sampling log marginal likelihood estimate
## (method = "normal", repetitions = 1):
##
## -94.69036
##
## Error Measures:
##
## Relative Mean-Squared Error: 9.999568e-07
## Coefficient of Variation: 0.0009999784
## Percentage Error: 0%
##
## Note:
## All error measures are approximate.
bf(M1, M0)
## Estimated Bayes factor in favor of M1 over M0: 3.91487
Do we expect the Bayes factor estimates to vary significantly despite different model specifications?
Check the Monte Carlo error of estimating the Bayes factor.
num <- 50; BF <- PerErr.M1 <- PerErr.M0 <- numeric(num)
system.time(
for (i in 1:num) { #roughly 74 min of run time
result <- BFBS(seed=i) #defined in All-in-One R Script
BF[i] <- result$bf
PerErr.M1[i] <- result$pererr.M1
PerErr.M0[i] <- result$pererr.M0
})
range(PerErr.M1); range(PerErr.M0)
hist(BF,prob=T,col="white",yaxt="n",ylab="",
xlab="Bayes factor estimates",main="")
lines(density(BF),col="red",lwd=2)
## [1] 0.001344015 0.001392706
## [1] 0.0009759583 0.0010113908
library(rstan)
# devtools::install_github("quentingronau/bridgesampling@master")
library(bridgesampling)
library(BayesFactor)
run.this=F #if TRUE, test the hypothetical data; if FALSE, test the simulated data
if (run.this) {
dat <- matrix(c(10,6,11,22,16,15,1,12,9,8,
13,8,14,23,18,17,1,15,12,9,
13,8,14,25,20,17,4,17,12,12), ncol=3,
dimnames=list(paste0("s",1:10), paste0("Level",1:3))) #wide data format
df <- data.frame("ID"=factor(rep(paste0("s",1:10), 3)),
"Level"=factor(rep(paste0("Level",1:3), each=10)),
"Response"=c(dat)) #long data format
} else {
mu.b <- 100; sigma.b <- 20; n <- 24
delta.mu <- 6.7; sigma.e <- 6.67 #rho=.9, power=.8
set.seed(277)
TrueScore <- rnorm(n, mu.b, sigma.b)
eij1 <- rnorm(n, 0, sigma.e)
eij2 <- rnorm(n, 0, sigma.e)
dat <- cbind("Level1" = TrueScore + eij1 + delta.mu,
"Level2" = TrueScore + eij2)
df <- data.frame("ID" = factor(rep(paste0("s",1:n), 2)),
"Level" = factor(rep(c("Level1", "Level2"), each = n)),
"Response" = as.vector(dat))
}
set.seed(277)
(JZS_BF <- anovaBF(Response~Level+ID, data=df, whichRandom="ID", progress=F))
# set.seed(277)
# draws <- posterior(JZS_BF, iterations=1e5, progress=F)
# summary(draws)
# plot(draws, cex.lab=1.5, cex.axis=1.5, cex.main=1.5, cex.sub=1.5)
computeQ <- function(C) {
#' reduced parametrization for the fixed treatment effects
S <- diag(C) - matrix(1, nrow = C, ncol = C) / C
e <- qr(S)
Q <- qr.Q(e) %*% diag(sign(diag(qr.R(e))))
Q[, which(abs(e$qraux) > 1e-3), drop = FALSE]
}
{
stancodeM1 <- "
data {
int<lower=1> N; // number of subjects
int<lower=2> C; // number of conditions
// vector[C] Y[N]; // responses [removed features]
array[N] vector[C] Y; // responses [Stan 2.26+ syntax for array declarations]
matrix[C,C-1] P; // projecting C-1 fixed effects into C
real<lower=0> ht; // scale parameter of the variance of the reduced treatment effect
matrix[C,C] V; // scale matrix of the Wishart prior
real lwr; // lower bound for the grand mean
real upr; // upper bound for the grand mean
}
parameters {
real<lower=lwr, upper=upr> mu; // grand mean
cov_matrix[C] Sigma; // error covariance matrix
real<lower=0> gt; // variance of the reduced treatment effect
vector[C-1] tf; // reduced treatment effect
}
transformed parameters {
vector[C] t; // treatment effect
t = P * tf;
}
model {
target += uniform_lpdf(mu | lwr, upr);
target += wishart_lpdf(Sigma | C+2, V); // Chung et al. (2015)
target += scaled_inv_chi_square_lpdf(gt | 1, ht);
target += normal_lpdf(tf | 0, sqrt(gt));
for (k in 1:N) {
target += multi_normal_lpdf(Y[k] | mu + t, Sigma);
}
}"
stanmodelM1 <- stan_model(model_code=stancodeM1)
stancodeM0 <- "
data {
int<lower=1> N; // number of subjects
int<lower=2> C; // number of conditions
// vector[C] Y[N]; // responses [removed features]
array[N] vector[C] Y; // responses [Stan 2.26+ syntax for array declarations]
matrix[C,C] V; // scale matrix of the Wishart prior
real lwr; // lower bound for the grand mean
real upr; // upper bound for the grand mean
}
parameters {
real<lower=lwr, upper=upr> mu; // grand mean
cov_matrix[C] Sigma; // error covariance matrix
}
transformed parameters {
vector[C] muS; // grand mean vector
for (i in 1:C) {
muS[i] = mu;
}
}
model {
target += uniform_lpdf(mu | lwr, upr);
target += wishart_lpdf(Sigma | C+2, V); // Chung et al. (2015)
for (k in 1:N) {
target += multi_normal_lpdf(Y[k] | muS, Sigma);
}
}"
stanmodelM0 <- stan_model(model_code=stancodeM0)
} #Stan models
datalistM1 <- list("N"=nrow(dat), "C"=ncol(dat),
"Y"=dat/sd(dat), #scale the data
"P"=computeQ(ncol(dat)), "ht"=.5,
"V"=diag(ncol(dat))*5E3)
datalistM1$lwr <- mean(datalistM1[["Y"]])-6*sd(datalistM1[["Y"]])
datalistM1$upr <- mean(datalistM1[["Y"]])+6*sd(datalistM1[["Y"]])
BFBS <- function(seed=277, diagnostics=F) {
stanfitM0 <- sampling(stanmodelM0, data=datalistM1[-c(4,5)],
iter=50000, warmup=10000, chains=4, seed=seed, refresh=0)
stanfitM1 <- sampling(stanmodelM1, data=datalistM1,
iter=50000, warmup=10000, chains=4, seed=seed, refresh=0)
set.seed(seed)
M0 <- bridge_sampler(stanfitM0, silent=T)
set.seed(seed)
M1 <- bridge_sampler(stanfitM1, silent=T)
if (diagnostics) {
list("bf"=exp(M1$logml - M0$logml),
"pererr.M1"=error_measures(M1)$cv,
"pererr.M0"=error_measures(M0)$cv,
"stan.M1"=stanfitM1, "stan.M0"=stanfitM0)
} else {
list("bf"=exp(M1$logml - M0$logml),
"pererr.M1"=error_measures(M1)$cv,
"pererr.M0"=error_measures(M0)$cv)
}
}
BFBS()
# MCMC <- BFBS(diag=T)
# rstan::summary(MCMC$stan.M1)[[1]]
# rstan::summary(MCMC$stan.M0)[[1]]
All the responses multiplied 100 times.
if (run.this) { #hypothetical
dat <- dat * 100
df <- data.frame("ID"=factor(rep(paste0("s",1:10), 3)),
"Level"=factor(rep(paste0("Level",1:3), each=10)),
"Response"=c(dat))
} else { #simulated
dat <- dat * 100
df <- data.frame("ID"=factor(rep(paste0("s",1:n), 2)),
"Level"=factor(rep(c("Level1", "Level2"), each=n)),
"Response"=c(dat))
}
## The Bayes factors will be computed for the simulated data (in the else-statement).
set.seed(277)
(JZS_BF <- anovaBF(Response~Level+ID, data=df, whichRandom="ID", progress=F))
## Bayes factor analysis
## --------------
## [1] Level + ID : 11.02461 ±0.67%
##
## Against denominator:
## Response ~ ID
## ---
## Bayes factor type: BFlinearModel, JZS
Compute log marginal likelihoods for full and null models via bridge sampling.
datalistM1$Y <- dat/sd(dat)
datalistM1$lwr <- mean(datalistM1[["Y"]])-6*sd(datalistM1[["Y"]])
datalistM1$upr <- mean(datalistM1[["Y"]])+6*sd(datalistM1[["Y"]])
stanfitM1 <- sampling(stanmodelM1, data=datalistM1,
iter=50000, warmup=10000, chains=4, seed=277, refresh=0)
rstan::summary(stanfitM1)[[1]] %>% kable(digits=4) %>% kable_classic(full_width=F)
| mean | se_mean | sd | 2.5% | 25% | 50% | 75% | 97.5% | n_eff | Rhat | |
|---|---|---|---|---|---|---|---|---|---|---|
| mu | 4.2848 | 0.0007 | 0.2378 | 3.8134 | 4.1301 | 4.2850 | 4.4393 | 4.7547 | 125730.55 | 1 |
| Sigma[1,1] | 1.4023 | 0.0020 | 0.5302 | 0.7119 | 1.0385 | 1.2935 | 1.6398 | 2.7295 | 68770.45 | 1 |
| Sigma[1,2] | 1.3012 | 0.0020 | 0.5149 | 0.6262 | 0.9469 | 1.1954 | 1.5326 | 2.5950 | 65687.00 | 1 |
| Sigma[2,1] | 1.3012 | 0.0020 | 0.5149 | 0.6262 | 0.9469 | 1.1954 | 1.5326 | 2.5950 | 65687.00 | 1 |
| Sigma[2,2] | 1.4692 | 0.0021 | 0.5523 | 0.7451 | 1.0897 | 1.3559 | 1.7190 | 2.8543 | 68715.60 | 1 |
| gt | 1.2876 | 0.1180 | 33.3903 | 0.0390 | 0.1056 | 0.2124 | 0.5153 | 5.9464 | 80005.44 | 1 |
| tf[1] | 0.1992 | 0.0002 | 0.0736 | 0.0531 | 0.1513 | 0.1992 | 0.2474 | 0.3441 | 125501.26 | 1 |
| t[1] | 0.1409 | 0.0001 | 0.0520 | 0.0375 | 0.1070 | 0.1409 | 0.1749 | 0.2433 | 125501.26 | 1 |
| t[2] | -0.1409 | 0.0001 | 0.0520 | -0.2433 | -0.1749 | -0.1409 | -0.1070 | -0.0375 | 125501.26 | 1 |
| lp__ | -91.0471 | 0.0080 | 1.9025 | -95.6780 | -92.0667 | -90.6896 | -89.6482 | -88.4230 | 55903.08 | 1 |
M1 <- bridge_sampler(stanfitM1, silent=T)
summary(M1)
##
## Bridge sampling log marginal likelihood estimate
## (method = "normal", repetitions = 1):
##
## -93.32272
##
## Error Measures:
##
## Relative Mean-Squared Error: 1.845126e-06
## Coefficient of Variation: 0.001358354
## Percentage Error: 0%
##
## Note:
## All error measures are approximate.
stanfitM0 <- sampling(stanmodelM0, data=datalistM1[-c(4,5)],
iter=50000, warmup=10000, chains=4, seed=277, refresh=0)
rstan::summary(stanfitM0)[[1]] %>% kable(digits=4) %>% kable_classic(full_width=F)
| mean | se_mean | sd | 2.5% | 25% | 50% | 75% | 97.5% | n_eff | Rhat | |
|---|---|---|---|---|---|---|---|---|---|---|
| mu | 4.3207 | 0.0010 | 0.2807 | 3.7644 | 4.1389 | 4.3218 | 4.5043 | 4.8731 | 85370.05 | 1.0000 |
| Sigma[1,1] | 1.4496 | 0.0024 | 0.5711 | 0.7208 | 1.0626 | 1.3308 | 1.6980 | 2.8686 | 55709.08 | 1.0001 |
| Sigma[1,2] | 1.3095 | 0.0024 | 0.5441 | 0.6063 | 0.9401 | 1.1982 | 1.5518 | 2.6650 | 51429.12 | 1.0001 |
| Sigma[2,1] | 1.3095 | 0.0024 | 0.5441 | 0.6063 | 0.9401 | 1.1982 | 1.5518 | 2.6650 | 51429.12 | 1.0001 |
| Sigma[2,2] | 1.5434 | 0.0026 | 0.6101 | 0.7632 | 1.1286 | 1.4172 | 1.8093 | 3.0645 | 54262.92 | 1.0001 |
| muS[1] | 4.3207 | 0.0010 | 0.2807 | 3.7644 | 4.1389 | 4.3218 | 4.5043 | 4.8731 | 85370.05 | 1.0000 |
| muS[2] | 4.3207 | 0.0010 | 0.2807 | 3.7644 | 4.1389 | 4.3218 | 4.5043 | 4.8731 | 85370.05 | 1.0000 |
| lp__ | -92.3445 | 0.0064 | 1.4972 | -96.0943 | -93.0803 | -92.0088 | -91.2452 | -90.4770 | 55573.66 | 1.0000 |
M0 <- bridge_sampler(stanfitM0, silent=T)
summary(M0)
##
## Bridge sampling log marginal likelihood estimate
## (method = "normal", repetitions = 1):
##
## -94.68977
##
## Error Measures:
##
## Relative Mean-Squared Error: 9.805829e-07
## Coefficient of Variation: 0.0009902438
## Percentage Error: 0%
##
## Note:
## All error measures are approximate.
bf(M1, M0) #Bayes factor
## Estimated Bayes factor in favor of M1 over M0: 3.92376