This vignette focuses on graphical posterior predictive checks (PPC).Plots of parameter estimates from MCMC draws are covered in the separatevignettePlottingMCMC draws, and MCMC diagnostics are covered in theVisualMCMC diagnostics vignette.
Thebayesplot package provides various plottingfunctions forgraphical posterior predictive checking, that is,creating graphical displays comparing observed data to simulated datafrom the posterior predictive distribution (Gabryet al, 2019).
The idea behind posterior predictive checking is simple: if a modelis a good fit then we should be able to use it to generate data thatlooks a lot like the data we observed. To generate the data used forposterior predictive checks (PPCs) we simulate from theposteriorpredictive distribution. This is the distribution of the outcomevariable implied by a model after using the observed data\(y\) (a vector of\(N\) outcome values) to update our beliefsabout unknown model parameters\(\theta\). The posterior predictivedistribution for observation\(\widetilde{y}\) can be written as\[p(\widetilde{y} \,|\, y) = \intp(\widetilde{y} \,|\, \theta) \, p(\theta \,|\, y) \, d\theta.\]Typically we will also condition on\(X\) (a matrix of predictor variables).
For each draw (simulation)\(s = 1, \ldots,S\) of the parameters from the posterior distribution,\(\theta^{(s)} \sim p(\theta \,|\, y)\), wedraw an entire vector of\(N\) outcomes\(\widetilde{y}^{(s)}\) from theposterior predictive distribution by simulating from the data modelconditional on parameters\(\theta^{(s)}\). The result is an\(S \times N\) matrix of draws\(\widetilde{y}\).
When simulating from the posterior predictive distribution we can useeither the same values of the predictors\(X\) that we used when fitting the model ornew observations of those predictors. When we use the same values of\(X\) we denote the resultingsimulations by\(y^{rep}\), as they canbe thought of as replications of the outcome\(y\) rather than predictions for futureobservations (\(\widetilde{y}\) usingpredictors\(\widetilde{X}\)). Thiscorresponds to the notation from Gelman et al. (2013) and is thenotation used throughout the package documentation.
Using the replicated datasets drawn from the posterior predictivedistribution, the functions in thebayesplot packagecreate various graphical displays comparing the observed data\(y\) to the replications. The names of thebayesplot plotting functions for posterior predictivechecking all have the prefixppc_.
In addition tobayesplot we’ll load the followingpackages:
To demonstrate some of the various PPCs that can be created with thebayesplot package we’ll use an example of comparingPoisson and Negative binomial regression models from one of therstanarmpackagevignettes (Gabry and Goodrich, 2017).
We want to make inferences about the efficacy of a certain pestmanagement system at reducing the number of roaches in urban apartments.[…] The regression predictors for the model are the pre-treatment numberof roaches
roach1, the treatment indicatortreatment, and a variableseniorindicatingwhether the apartment is in a building restricted to elderly residents.Because the number of days for which the roach traps were used is notthe same for all apartments in the sample, we include it as an exposure[…].
First we fit a Poisson regression model with outcome variabley representing the roach count in each apartment at the endof the experiment.
y roach1 treatment senior exposure21 153 308.00 1 0 0.8000002 127 331.25 1 0 0.6000003 7 1.67 1 0 1.0000004 7 3.00 1 0 1.0000005 0 2.00 1 0 1.1428576 0 0.00 1 0 1.000000# using rstanarm's default priors. For details see the section on default# weakly informative priors at https://mc-stan.org/rstanarm/articles/priors.htmlfit_poisson<-stan_glm( y~ roach100+ treatment+ senior,offset =log(exposure2),family =poisson(link ="log"),data = roaches,seed =1111,refresh =0# suppresses all output as of v2.18.1 of rstan)stan_glm family: poisson [log] formula: y ~ roach100 + treatment + senior observations: 262 predictors: 4------ Median MAD_SD(Intercept) 3.1 0.0 roach100 0.7 0.0 treatment -0.5 0.0 senior -0.4 0.0 ------* For help interpreting the printed output see ?print.stanreg* For info on the priors used see ?prior_summary.stanregWe’ll also fit the negative binomial model that we’ll compare to thePoisson:
stan_glm family: neg_binomial_2 [log] formula: y ~ roach100 + treatment + senior observations: 262 predictors: 4------ Median MAD_SD(Intercept) 2.8 0.2 roach100 1.3 0.3 treatment -0.8 0.2 senior -0.3 0.3 Auxiliary parameter(s): Median MAD_SDreciprocal_dispersion 0.3 0.0 ------* For help interpreting the printed output see ?print.stanreg* For info on the priors used see ?prior_summary.stanregy andyrepIn order to use the PPC functions from thebayesplotpackage we need a vectory of outcome values,
and a matrixyrep of draws from the posterior predictivedistribution,
yrep_poisson<-posterior_predict(fit_poisson,draws =500)yrep_nb<-posterior_predict(fit_nb,draws =500)dim(yrep_poisson)[1] 500 262[1] 500 262Each row of the matrix is a draw from the posterior predictivedistribution, i.e. a vector with one element for each of the data pointsiny.
Since we fit the models usingrstanarm we used itsspecialposterior_predict function, but if we were using amodel fit with therstan package we could createyrep in thegenerated quantities block of theStan program or by doing simulations in R after fitting the model. Drawsfrom the posterior predictive distribution can be used withbayesplot regardless of whether or not the model wasfit using an interface to Stan.bayesplot just requiresayrep matrix that hasnumber_of_draws rowsandnumber_of_observations columns.
The first PPC we’ll look at is a comparison of the distribution ofy and the distributions of some of the simulated datasets(rows) in theyrep matrix.
In the plot above, the dark line is the distribution of the observedoutcomesy and each of the 50 lighter lines is the kerneldensity estimate of one of the replications ofy from theposterior predictive distribution (i.e., one of the rows inyrep). This plot makes it easy to see that this model failsto account for the large proportion of zeros iny. That is,the model predicts fewer zeros than were actually observed.
To see the discrepancy at the lower values of more clearly we can usethexlim function fromggplot2 to restrictthe range of the x-axis:
See Figure 6 inGabry et al. (2019) foranother example of usingppc_dens_overlay.
We could see the same thing from a different perspective by lookingat separate histograms ofy and some of theyrep datasets using theppc_hist function:
The same plot for the negative binomial model looks muchdifferent:
The negative binomial model does better handling the number of zerosin the data, but it occasionally predicts values that are way too large,which is why the x-axes extend to such high values in the plot and makeit difficult to read. To see the predictions for the smaller values moreclearly we can zoom in:
Another way to see that the Poisson model predicts too few zeros isto look at the distribution of the proportion of zeros over thereplicated datasets from the posterior predictive distribution inyrep and compare to the proportion of observed zeros iny.
First we define a function that takes a vector as input and returnsthe proportion of zeros:
[1] 0.3587786Thestat argument toppc_stat accepts afunction or the name of a function for computing a test statistic from avector of data. In our case we can specifystat = "prop_zero" since we’ve already defined theprop_zero function, but we also could have usedstat = function(x) mean(x == 0).
The dark line is at the value\(T(y)\), i.e. the value of the teststatistic computed from the observed\(y\), in this caseprop_zero(y). The lighter area on the left is actually ahistogram of the proportion of zeros in in theyrepsimulations, but it can be hard to see because almost none of thesimulated datasets inyrep have any zeros.
Here’s the same plot for the negative binomial model:
Again we see that the negative binomial model does a much better jobpredicting the proportion of observed zeros than the Poisson.
However, if we look instead at the distribution of the maximum valuein the replications, we can see that the Poisson model makes morerealistic predictions than the negative binomial:
See Figure 7 inGabry et al. (2019) foranother example of usingppc_stat.
There are many additional PPCs available, including plots ofpredictive intervals, distributions of predictive errors, and more. Forlinks to the documentation for all of the various PPC plots seehelp("PPC-overview") from R or theonlinedocumentation on the Stan website.
Theavailable_ppc function can also be used to list thenames of all PPC plotting functions:
bayesplot PPC module: ppc_bars ppc_bars_grouped ppc_boxplot ppc_dens ppc_dens_overlay ppc_dens_overlay_grouped ppc_dots ppc_ecdf_overlay ppc_ecdf_overlay_grouped ppc_error_binned ppc_error_hist ppc_error_hist_grouped ppc_error_scatter ppc_error_scatter_avg ppc_error_scatter_avg_grouped ppc_error_scatter_avg_vs_x ppc_freqpoly ppc_freqpoly_grouped ppc_hist ppc_intervals ppc_intervals_grouped ppc_km_overlay ppc_km_overlay_grouped ppc_loo_intervals ppc_loo_pit_ecdf ppc_loo_pit_overlay ppc_loo_pit_qq ppc_loo_ribbon ppc_pit_ecdf ppc_pit_ecdf_grouped ppc_ribbon ppc_ribbon_grouped ppc_rootogram ppc_scatter ppc_scatter_avg ppc_scatter_avg_grouped ppc_stat ppc_stat_2d ppc_stat_freqpoly ppc_stat_freqpoly_grouped ppc_stat_grouped ppc_violin_groupedMany of the available PPCs can also be carried out within levels of agrouping variable. Any function for PPCs by group will have a nameending in_grouped and will accept an additional argumentgroup. The full list of currently available_grouped functions is:
bayesplot PPC module:(matching pattern '_grouped') ppc_bars_grouped ppc_dens_overlay_grouped ppc_ecdf_overlay_grouped ppc_error_hist_grouped ppc_error_scatter_avg_grouped ppc_freqpoly_grouped ppc_intervals_grouped ppc_km_overlay_grouped ppc_pit_ecdf_grouped ppc_ribbon_grouped ppc_scatter_avg_grouped ppc_stat_freqpoly_grouped ppc_stat_grouped ppc_violin_groupedFor example,ppc_stat_grouped is the same asppc_stat except that the test statistic is computed withinlevels of the grouping variable and a separate plot is made for eachlevel:
See Figure 8 inGabry et al. (2019) foranother example of usingppc_stat_grouped.
Thebayesplot package provides the S3 genericfunctionpp_check. Authors of R packages for Bayesianinference are encouraged to define methods for the fitted model objectscreated by their packages. This will hopefully be convenient for bothusers and developers and contribute to the use of the same namingconventions across many of the R packages for Bayesian dataanalysis.
To provide an interface tobayesplot from yourpackage, you can very easily define app_check method (ormultiplepp_check methods) for the fitted model objectscreated by your package. All app_check method needs to dois provide they vector andyrep matrixarguments to the various plotting functions included inbayesplot.
pp_check methodHere is an example for how to define a simplepp_checkmethod in a package that creates fitted model objects of class"foo". We will define a methodpp_check.foothat extracts the datay and the draws from the posteriorpredictive distributionyrep from an object of class"foo" and then calls one of the plotting functions frombayesplot.
Suppose that objects of class"foo" are lists with namedcomponents, two of which arey andyrep.Here’s a simple methodpp_check.foo that offers the userthe option of two different plots:
# @param object An object of class "foo".# @param type The type of plot.# @param ... Optional arguments passed on to the bayesplot plotting function.pp_check.foo<-function(object,type =c("multiple","overlaid"), ...) { type<-match.arg(type) y<- object[["y"]] yrep<- object[["yrep"]]stopifnot(nrow(yrep)>=50) samp<-sample(nrow(yrep),size =ifelse(type=="overlaid",50,5)) yrep<- yrep[samp, ]if (type=="overlaid") {ppc_dens_overlay(y, yrep, ...) }else {ppc_hist(y, yrep, ...) }}To try outpp_check.foo we can just make a list withy andyrep components and give it classfoo:
Buerkner, P. (2017). brms: Bayesian Regression Models using Stan. Rpackage version 1.7.0.https://CRAN.R-project.org/package=brms
Gabry, J., and Goodrich, B. (2017). rstanarm: Bayesian AppliedRegression Modeling via Stan. R package version 2.15.3.https://mc-stan.org/rstanarm/,https://CRAN.R-project.org/package=rstanarm
Gabry, J. , Simpson, D. , Vehtari, A. , Betancourt, M. and Gelman, A.(2019), Visualization in Bayesian workflow.J. R. Stat. Soc. A,182: 389-402. :10.1111/rssa.12378. (journalversion,arXivpreprint,codeon GitHub)
Gelman, A., Carlin, J. B., Stern, H. S., Dunson, D. B., Vehtari, A.,and Rubin, D. B. (2013).Bayesian Data Analysis. Chapman &Hall/CRC Press, London, third edition.
Stan Development Team.Stan Modeling Language Users Guide andReference Manual.https://mc-stan.org/users/documentation/