@@ -395,7 +395,7 @@ names(ymiss) <- names(logret)[missing]
395395For simplicity, we employ our improper prior and sample iteratively.
396396
397397``` {r}
398- ndraws <- 5000
398+ ndraws <- 500000
399399nburn <- 1000
400400ind <- missing - 2
401401
@@ -720,31 +720,15 @@ for (m in seq_len(ndraws + nburn)) {
720720 phis[m - nburn] <- phi
721721 }
722722}
723- res1 <- data.frame(y0 = y0s, sigma2 = sigma2s, zeta = zetas, phi = phis )
723+ stationary1 <- data.frame(zeta = zetas, phi = phis, sigma2 = sigma2s, y0 = y0s )
724724naccepts1 <- naccepts
725725```
726726
727- Let us investigate traceplots and empirical autocorrelation functions of the
728- draws. In addition, we check the percentage of accepted draws in MH-step (d).
727+ We repeat the exercise with a more informative beta prior.
729728
730729``` {r}
731- plot.ts(res1, xlab = "Draws after burn-in",
732- main = paste0("MH acceptance rate: ", 100 * naccepts1 / ndraws, "%"))
733- acf(res1, ylab = "")
734- ```
735-
736- We now repeat this exercise, but use the conditional posterior resulting
737- from an auxiliary moment-matched prior in Step (d).
738-
739- ``` {r}
740- # Compute mean and variance of the actual prior using properties of the beta
741- priormean <- 2 * aphi / (aphi + bphi) - 1
742- priorvar <- 4 * (aphi * bphi) / ((aphi + bphi)^2 * (aphi + bphi + 1))
743-
744- # Define the design matrix and y
745- X <- matrix(NA_real_, nrow = length(y), 2)
746- X[, 1] <- 1
747- X[, 2] <- c(NA_real_, y[-length(y)])
730+ aphi <- 20
731+ bphi <- 1.5
748732
749733# Allocate some space for the posterior draws and initialize the parameters:
750734y0s <- sigma2s <- zetas <- phis <- rep(NA_real_, ndraws)
@@ -772,18 +756,15 @@ for (m in seq_len(ndraws + nburn)) {
772756
773757 # Step (d): Draw the persistence
774758 tmp <- y0^2 + sum(y[-length(y)]^2)
775- propvar <- 1 / (1 / priorvar + tmp / sigma2)
776- propmean <- propvar * (priormean / priorvar + (y0 * (y[1] - zeta) +
777- sum(y[-length(y)] * (y[-1] - zeta))) / sigma2)
759+ propmean <- (y0 * (y[1] - zeta) + sum(y[-length(y)] * (y[-1] - zeta))) / tmp
760+ propvar <- sigma2 / tmp
778761 phiprop <- rnorm(1, propmean, sqrt(propvar))
779762 if (-1 < phiprop & phiprop < 1) {
780763 logR <- dbetarescaled(phiprop, aphi, bphi, log = TRUE) -
781764 dbetarescaled(phi, aphi, bphi, log = TRUE) +
782765 dnorm(y0, zeta / (1 - phiprop), sqrt(sigma2 / (1 - phiprop^2)),
783766 log = TRUE) -
784- dnorm(y0, zeta / (1 - phi), sqrt(sigma2 / (1 - phi^2)), log = TRUE) +
785- dnorm(phi, priormean, sqrt(priorvar), log = TRUE) -
786- dnorm(phiprop, priormean, sqrt(priorvar), log = TRUE)
767+ dnorm(y0, zeta / (1 - phi), sqrt(sigma2 / (1 - phi^2)), log = TRUE)
787768 if (log(runif(1)) < logR) {
788769 phi <- phiprop
789770 if (m > nburn) naccepts <- naccepts + 1L
@@ -798,58 +779,111 @@ for (m in seq_len(ndraws + nburn)) {
798779 phis[m - nburn] <- phi
799780 }
800781}
801- res2 <- data.frame(y0 = y0s, sigma2 = sigma2s, zeta = zetas, phi = phis )
782+ stationary2 <- data.frame(zeta = zetas, phi = phis, sigma2 = sigma2s, y0 = y0s )
802783naccepts2 <- naccepts
803784```
804785
805- Again, we investigate traceplots and empirical autocorrelation functions of the
806- draws. In addition, we check the percentage of accepted draws in MH-step (d).
786+ To conclude, we compare the posteriors of $\phi$ under the improper prior,
787+ the posterior obtained after post-processing draws to obtain stationarity,
788+ and the posterior under the stationary-enforcing shifted beta priors.
807789
808- ``` {r}
809- plot.ts(res2, xlab = "Draws after burn-in",
810- main = paste0("MH acceptance rate: ", 100 * naccepts2 / ndraws, "%"))
811- acf(res2, ylab = "")
790+ ``` {r, echo = -c(1:2)}
791+ if (pdfplots) {
792+ pdf("7-2_12.pdf", width = 8, height = 5)
793+ }
794+ par(mfrow = c(1, 1), mar = c(2.5, 2.5, 1.5, .1), mgp = c(1.5, .5, 0), lwd = 1.5)
795+ mybreaks <- seq(floor(100 * .99 * min(stationary2$phi)) / 100,
796+ ceiling(100 * 1.01 * max(ar1draws)) / 100,
797+ by = .0025)
798+ hist(ar1draws[!nonstationary[, 1]], breaks = mybreaks, col = rgb(0, 0, 1, .2),
799+ main = "Histogram of posterior draws", xlab = expression(phi),
800+ freq = FALSE)
801+ hist(ar1draws, breaks = mybreaks, col = rgb(0, 1, 0, .2),
802+ freq = FALSE, add = TRUE)
803+ hist(stationary1$phi, breaks = mybreaks, col = rgb(1, 0, 0, .2),
804+ freq = FALSE, add = TRUE)
805+ hist(stationary2$phi, breaks = mybreaks, col = rgb(1, 1, 0, .2),
806+ freq = FALSE, add = TRUE)
807+ lines(mybreaks[mybreaks <= 1], lty = 3, lwd = 3,
808+ dbetarescaled(mybreaks[mybreaks <= 1], 1, 1))
809+ lines(mybreaks[mybreaks <= 1], lty = 2, lwd = 3,
810+ dbetarescaled(mybreaks[mybreaks <= 1], aphi, bphi))
811+ legend("topright",
812+ c("Unrestricted posterior", "Post-processed posterior",
813+ "Beta prior posterior (flat)", "Beta prior posterior (informative)"),
814+ fill = rgb(c(0, 0, 1, 1), c(1, 0, 0, 1), c(0, 1, 0, 0), .2))
815+ legend("topleft", c("Beta prior (flat)", "Beta prior (informative)"),
816+ col = 1, lty = 3:2, lwd = 3)
812817```
813818
814- We now compare the draws from the two samplers; they should yield
815- draws from the same distribution, irrespective of the acceptance rate and thus
816- the mixing of the Markov chain. We graphically
817- check this by comparing histograms and quantiles of draws from the marginal
818- posterior of $\phi$.
819+ ## Section 7.2.5: Evaluating the Efficiency of an MCMC Sampler
820+ ### Example 7.11: Improving the independence MH step
819821
820- ``` {r, echo = -c(1:2), fig.width = 8, fig.height = 4}
822+ Let us investigate traceplots and empirical autocorrelation functions of the
823+ posterior draws under the informative stationarity-inducing prior.
824+
825+ ``` {r, echo = -c(1:2)}
821826if (pdfplots) {
822- pdf("7-2_11.pdf", width = 8, height = 4)
827+ pdf("7-2_13.pdf", width = 8, height = 5)
828+ }
829+ labels <- expression(zeta, phi, sigma^2, y[0])
830+ par(mfrow = c(4, 2), mar = c(2.5, 2.8, 1.5, .1), mgp = c(1.5, .5, 0), lwd = 1.5)
831+ for (i in seq_along(stationary2)) {
832+ plot.ts(stationary2[i], xlab = "Draws after burn-in", ylab = labels[i])
833+ if (i == 1) title("Traceplot")
834+ acf(stationary2[i], ylab = "", main = "ACF")
835+ if (i == 1) title("Empirical ACF")
823836}
824- par(mfrow = c(1, 2), mar = c(2.5, 2.5, 1.5, .1), mgp = c(1.5, .5, 0), lwd = 2)
825- mybreaks <- seq(min(res1$phi, res2$phi), max(res1$phi, res2$phi),
826- length.out = 50)
827- hist(res1$phi, breaks = mybreaks, col = rgb(0, 0, 1, .3),
828- main = "Histogram", xlab = expression(phi), freq = FALSE)
829- hist(res2$phi, breaks = mybreaks, col = rgb(1, 0, 0, .3), freq = FALSE,
830- add = TRUE)
831- qqplot(res1$phi, res2$phi, xlab = "Sampler 1", ylab = "Sampler 2",
832- main = "QQ plot")
833- abline(0, 1, col = 2)
834837```
835- We can see that the draws appear to come from the same distribution. Note,
836- however, that the first sampler gets "stuck" slightly below 0.93 for a few
837- draws, which isn't the case for the second sampler.
838838
839- We now re-run the second sampler with a more informative beta prior.
839+ We now compute an estimate of the effective sample size (ESS) and the
840+ inefficiency factor (IF) use the coda package.
840841
841842``` {r}
842- aphi <- 20
843- bphi <- 1.5
843+ library(coda)
844+ ess1 <- effectiveSize(data.frame(zeta = res2[[1]]$betas[, 1],
845+ phi = res2[[1]]$betas[, 2],
846+ sigma2 = res2[[1]]$sigma2s))
847+ ess2 <- effectiveSize(data.frame(zeta = res2[[1]]$betas[!nonstationary[, 1], 1],
848+ phi = res2[[1]]$betas[!nonstationary[, 1], 2],
849+ sigma2 = res2[[1]]$sigma2s[!nonstationary[, 1]]))
850+ ess3 <- effectiveSize(stationary1)
851+ ess4 <- effectiveSize(stationary2)
852+ ess <- rbind(unrestricted = c(ess1, y0 = NA),
853+ postprocessed = c(ess2, y0 = NA),
854+ betapriorflat = ess3,
855+ betapriorinformative = ess4)
856+ knitr::kable(round(ess))
857+ knitr::kable(round(ndraws / ess, 2))
858+ ```
844859
845- # Compute mean and variance of the actual prior using properties of the beta
846- priormean <- 2 * aphi / (aphi + bphi) - 1
847- priorvar <- 4 * (aphi * bphi) / ((aphi + bphi)^2 * (aphi + bphi + 1))
860+ We now repeat the above exercise, but use the conditional posterior resulting
861+ from an auxiliary moment-matched prior in Step (d).
848862
849- # Define the design matrix and y
850- X <- matrix(NA_real_, nrow = length(y), 2)
851- X[, 1] <- 1
852- X[, 2] <- c(NA_real_, y[-length(y)])
863+ ``` {r}
864+ method <- "fancy"
865+ if (method == "simple") {
866+ # Add .5 to aphi and bphi (from the determinant of the initial state prior)
867+ aphiprop <- aphi + .5
868+ bphiprop <- bphi + .5
869+
870+ # Compute mean and variance of the proposal using properties of the beta
871+ priormean <- 2 * aphiprop / (aphiprop + bphiprop) - 1
872+ priorvar <- 4 * (aphiprop * bphiprop) /
873+ ((aphiprop + bphiprop)^2 * (aphiprop + bphiprop + 1))
874+
875+ } else if (method == "fancy") {
876+
877+ # Alternatively, mode-and-curvature-match:
878+ dprior <- function(phi, zeta, sigma2, y0, aphi, bphi, log = FALSE) {
879+ inside <- phi <= 1 & phi >= -1
880+ logdens <- -Inf
881+ logdens[inside] <- dbetarescaled(phi[inside], aphi, bphi, log = TRUE) +
882+ dnorm(y0, zeta / (1 - phi[inside]), sqrt(sigma2 / (1 - phi[inside]^2)),
883+ log = TRUE)
884+ if (log) logdens else exp(logdens)
885+ }
886+ }
853887
854888# Allocate some space for the posterior draws and initialize the parameters:
855889y0s <- sigma2s <- zetas <- phis <- rep(NA_real_, ndraws)
@@ -876,10 +910,21 @@ for (m in seq_len(ndraws + nburn)) {
876910 zeta <- rnorm(1, bT, sqrt(BT))
877911
878912 # Step (d): Draw the persistence
913+
914+ if (method == "fancy") {
915+ mode <- optimize(dprior, c(-1, 1), zeta = zeta, sigma2 = sigma2, y0 = y0,
916+ aphi = aphi, bphi = bphi, log = TRUE, maximum = TRUE)$maximum
917+ dd <- numDeriv::hessian(dprior, mode, zeta = zeta, sigma2 = sigma2, y0 = y0,
918+ aphi = aphi, bphi = bphi)
919+ priormean <- mode
920+ priorvar <- -1 / as.numeric(dd)
921+ }
922+
879923 tmp <- y0^2 + sum(y[-length(y)]^2)
880924 propvar <- 1 / (1 / priorvar + tmp / sigma2)
881- propmean <- propvar * (priormean / priorvar +
882- (y0 * (y[1] - zeta) + sum(y[-length(y)] * (y[-1] - zeta))) / sigma2)
925+ propmean <- propvar * (priormean / priorvar + (y0 * (y[1] - zeta) +
926+ sum(y[-length(y)] * (y[-1] - zeta))) / sigma2)
927+
883928 phiprop <- rnorm(1, propmean, sqrt(propvar))
884929 if (-1 < phiprop & phiprop < 1) {
885930 logR <- dbetarescaled(phiprop, aphi, bphi, log = TRUE) -
@@ -903,43 +948,56 @@ for (m in seq_len(ndraws + nburn)) {
903948 phis[m - nburn] <- phi
904949 }
905950}
906- res3 <- data.frame(y0 = y0s, sigma2 = sigma2s, zeta = zetas, phi = phis )
951+ stationary3 <- data.frame(zeta = zetas, phi = phis, sigma2 = sigma2s, y0 = y0s )
907952naccepts3 <- naccepts
908953```
909954
910- To conclude, we compare the posteriors of $\phi$ under the improper prior,
911- the posterior obtained after post-processing draws to obtain stationarity,
912- and the posterior under the stationary-enforcing shifted beta priors.
955+ Again, we investigate traceplots and empirical autocorrelation functions of the
956+ draws. In addition, we check the percentage of accepted draws in MH-step (d).
913957
914- ``` {r, echo = -c(1:2)}
958+ ``` {r}
959+ par(mfrow = c(4, 2), mar = c(2.5, 2.8, 1.5, .1), mgp = c(1.5, .5, 0), lwd = 1.5)
960+ for (i in seq_along(stationary3)) {
961+ plot.ts(stationary3[i], xlab = "Draws after burn-in", ylab = labels[i])
962+ if (i == 1) title("Traceplot")
963+ acf(stationary3[i], ylab = "", main = "ACF")
964+ if (i == 1) title("Empirical ACF")
965+ }
966+ ```
967+
968+ We now compare the draws from the two samplers; they should yield
969+ draws from the same distribution, irrespective of the acceptance rate and thus
970+ the mixing of the Markov chain. We graphically
971+ check this by comparing histograms and quantiles of draws from the marginal
972+ posterior of $\phi$.
973+
974+ ``` {r, echo = -c(1:2), fig.width = 8, fig.height = 4}
915975if (pdfplots) {
916- pdf("7-2_12 .pdf", width = 8, height = 5 )
976+ pdf("7-2_14 .pdf", width = 8, height = 4 )
917977}
918- par(mfrow = c(1, 1), mar = c(2.5, 2.5, 1.5, .1), mgp = c(1.5, .5, 0), lwd = 1.5)
919- mybreaks <- seq(floor(100 * .99 * min(res2$phi)) / 100,
920- ceiling(100 * 1.01 * max(ar1draws)) / 100,
921- by = .0025)
922- hist(ar1draws[!nonstationary[, 1]], breaks = mybreaks, col = rgb(0, 0, 1, .2),
923- main = "Histogram of posterior draws", xlab = expression(phi),
924- freq = FALSE)
925- hist(ar1draws, breaks = mybreaks, col = rgb(0, 1, 0, .2),
926- freq = FALSE, add = TRUE)
927- hist(res2$phi, breaks = mybreaks, col = rgb(1, 0, 0, .2),
928- freq = FALSE, add = TRUE)
929- hist(res3$phi, breaks = mybreaks, col = rgb(1, 1, 0, .2),
930- freq = FALSE, add = TRUE)
931- lines(mybreaks[mybreaks <= 1], lty = 3, lwd = 3,
932- dbetarescaled(mybreaks[mybreaks <= 1], 1, 1))
933- lines(mybreaks[mybreaks <= 1], lty = 2, lwd = 3,
934- dbetarescaled(mybreaks[mybreaks <= 1], aphi, bphi))
935- legend("topright",
936- c("Unrestricted posterior", "Post-processed posterior",
937- "Beta prior posterior (flat)", "Beta prior posterior (informative)"),
938- fill = rgb(c(0, 0, 1, 1), c(1, 0, 0, 1), c(0, 1, 0, 0), .2))
939- legend("topleft", c("Beta prior (flat)", "Beta prior (informative)"),
940- col = 1, lty = 3:2, lwd = 3)
978+ par(mfrow = c(1, 2), mar = c(2.5, 2.5, 1.5, .1), mgp = c(1.5, .5, 0), lwd = 2)
979+ mybreaks <- seq(min(stationary2$phi, stationary3$phi),
980+ max(stationary2$phi, stationary3$phi),
981+ length.out = 50)
982+ hist(stationary2$phi, breaks = mybreaks, col = rgb(0, 0, 1, .3),
983+ main = "Histogram", xlab = expression(phi), freq = FALSE)
984+ hist(stationary3$phi, breaks = mybreaks, col = rgb(1, 0, 0, .3), freq = FALSE,
985+ add = TRUE)
986+ qqplot(stationary1$phi, stationary3$phi, xlab = "Sampler 1", ylab = "Sampler 2",
987+ main = "QQ plot")
988+ abline(0, 1, col = 2)
989+ ```
990+ We can see that the draws appear to come from the same distribution. Note,
991+ however, that the first sampler gets "stuck" slightly below 0.93 for a few
992+ draws, which isn't the case for the second sampler.
993+
994+ ``` {r}
995+ library(coda)
996+ ess <- effectiveSize(stationary3)
997+ knitr::kable(rbind(ESS = round(ess), IF = round(ndraws / ess, 2)))
941998```
942999
1000+
9431001# Section 7.3: Some Extensions
9441002## Section 7.3.1: AR Models with a Unit Root
9451003
0 commit comments