1
1
# ' Effective Sample Size (ESS)
2
2
# '
3
- # ' This function returns the effective sample size (ESS).
3
+ # ' Effective Sample Size (ESS) is a measure of how much independent information
4
+ # ' there is in autocorrelated chains. It is used to assess the quality of MCMC
5
+ # ' samples. A higher ESS indicates more reliable estimates. For most
6
+ # ' applications, an effective sample size greater than 1,000 is sufficient for
7
+ # ' stable estimates (Bürkner, 2017). This function returns the effective sample
8
+ # ' size (ESS) for various Bayesian model objects. For `brmsfit` objects, the
9
+ # ' returned ESS corresponds to the bulk-ESS (and the tail-ESS is also returned).
4
10
# '
5
11
# ' @param model A `stanreg`, `stanfit`, `brmsfit`, `blavaan`, or `MCMCglmm` object.
6
12
# ' @param ... Currently not used.
7
13
# ' @inheritParams hdi
8
14
# '
15
+ # ' @inheritSection hdi Model components
16
+ # '
9
17
# ' @return A data frame with two columns: Parameter name and effective sample size (ESS).
10
18
# '
11
- # ' @details **Effective Sample (ESS)** should be as large as possible, altough
19
+ # ' @details
20
+ # ' - **Effective Sample (ESS)** should be as large as possible, altough
12
21
# ' for most applications, an effective sample size greater than 1,000 is
13
22
# ' sufficient for stable estimates (Bürkner, 2017). The ESS corresponds to the
14
23
# ' number of independent samples with the same estimation power as the N
15
24
# ' autocorrelated samples. It is is a measure of \dQuote{how much independent
16
25
# ' information there is in autocorrelated chains} (*Kruschke 2015, p182-3*).
17
26
# '
27
+ # ' - **Bulk-ESS** is useful as a diagnostic for the sampling efficiency in
28
+ # ' the bulk of the posterior. It is defined as the effective sample size for
29
+ # ' rank normalized values using split chains. It can be interpreted as the
30
+ # ' reliability of indices of central tendency (mean, median, etc.).
31
+ # '
32
+ # ' - **Tail-ESS** is useful as a diagnostic for the sampling efficiency in
33
+ # ' the tails of the posterior. It is defined as the minimum of the effective
34
+ # ' sample sizes for 5% and 95% quantiles. It can be interpreted as the
35
+ # ' reliability of indices that depend on the tails of the distribution (e.g.,
36
+ # ' credible intervals, tail probabilities, etc.).
37
+ # '
18
38
# ' @references
19
39
# ' - Kruschke, J. (2014). Doing Bayesian data analysis: A tutorial with R, JAGS,
20
40
# ' and Stan. Academic Press.
21
41
# ' - Bürkner, P. C. (2017). brms: An R package for Bayesian multilevel models
22
42
# ' using Stan. Journal of Statistical Software, 80(1), 1-28
43
+ # ' - Vehtari, A., Gelman, A., Simpson, D., Carpenter, B., & Bürkner, P.-C.
44
+ # ' (2021). Rank-normalization, folding, and localization: An improved R-hat
45
+ # ' for assessing convergence of MCMC. Bayesian Analysis, 16(2), 667-718.
23
46
# '
24
- # ' @examplesIf require( "rstanarm")
47
+ # ' @examplesIf all(insight::check_if_installed(c( "rstanarm", "brms", "posterior"), quietly = TRUE) )
25
48
# ' \donttest{
26
- # ' library(rstanarm)
27
- # ' model <- suppressWarnings(
28
- # ' stan_glm(mpg ~ wt + gear, data = mtcars, chains = 2, iter = 200, refresh = 0)
29
- # ' )
49
+ # ' model <- suppressWarnings(rstanarm::stan_glm(
50
+ # ' mpg ~ wt + gear,
51
+ # ' data = mtcars,
52
+ # ' chains = 2,
53
+ # ' iter = 200,
54
+ # ' refresh = 0
55
+ # ' ))
56
+ # ' effective_sample(model)
57
+ # '
58
+ # ' model <- suppressWarnings(brms::brm(
59
+ # ' mpg ~ wt,
60
+ # ' data = mtcars,
61
+ # ' chains = 2,
62
+ # ' iter = 200,
63
+ # ' refresh = 0
64
+ # ' ))
30
65
# ' effective_sample(model)
31
66
# ' }
32
67
# ' @export
@@ -50,14 +85,10 @@ effective_sample.default <- function(model, ...) {
50
85
# ' @rdname effective_sample
51
86
# ' @export
52
87
effective_sample.brmsfit <- function (model ,
53
- effects = c( " fixed" , " random " , " all " ) ,
54
- component = c( " conditional" , " zi " , " zero_inflated " , " all " ) ,
88
+ effects = " fixed" ,
89
+ component = " conditional" ,
55
90
parameters = NULL ,
56
91
... ) {
57
- # check arguments
58
- effects <- match.arg(effects )
59
- component <- match.arg(component )
60
-
61
92
pars <- insight :: find_parameters(
62
93
model ,
63
94
effects = effects ,
@@ -66,14 +97,16 @@ effective_sample.brmsfit <- function(model,
66
97
flatten = TRUE
67
98
)
68
99
69
- insight :: check_if_installed(" rstan" )
70
-
71
- s <- rstan :: summary(model $ fit )$ summary
72
- s <- subset(s , subset = rownames(s ) %in% pars )
100
+ insight :: check_if_installed(" posterior" )
101
+ idx <- as.data.frame(posterior :: summarise_draws(model ))
102
+ rows_to_keep <- idx $ variable %in% pars
103
+ # ess_*() functions are defined in:
104
+ # https://github.com/stan-dev/posterior/blob/master/R/convergence.R
73
105
74
106
data.frame (
75
- Parameter = rownames(s ),
76
- ESS = round(s [, " n_eff" ]),
107
+ Parameter = idx $ variable [rows_to_keep ],
108
+ ESS = round(idx [rows_to_keep , " ess_bulk" ]),
109
+ ESS_tail = round(idx [rows_to_keep , " ess_tail" ]),
77
110
stringsAsFactors = FALSE ,
78
111
row.names = NULL
79
112
)
@@ -83,57 +116,43 @@ effective_sample.brmsfit <- function(model,
83
116
# ' @rdname effective_sample
84
117
# ' @export
85
118
effective_sample.stanreg <- function (model ,
86
- effects = c( " fixed" , " random " , " all " ) ,
87
- component = c( " location" , " all " , " conditional " , " smooth_terms " , " sigma " , " distributional " , " auxiliary " ), # nolint
119
+ effects = " fixed" ,
120
+ component = " location" ,
88
121
parameters = NULL ,
89
122
... ) {
90
- # check arguments
91
- effects <- match.arg(effects )
92
- component <- match.arg(component )
93
-
94
- pars <- insight :: find_parameters(
123
+ effective_sample.brmsfit(
95
124
model ,
96
125
effects = effects ,
97
126
component = component ,
98
127
parameters = parameters ,
99
- flatten = TRUE
100
- )
101
-
102
- s <- as.data.frame(summary(model ))
103
- s <- s [rownames(s ) %in% pars , ]
104
-
105
- data.frame (
106
- Parameter = rownames(s ),
107
- ESS = s [[" n_eff" ]],
108
- stringsAsFactors = FALSE ,
109
- row.names = NULL
128
+ ...
110
129
)
111
130
}
112
131
113
132
114
133
# ' @export
115
134
effective_sample.stanmvreg <- function (model ,
116
- effects = c( " fixed" , " random " , " all " ) ,
117
- component = c( " location" , " all " , " conditional " , " smooth_terms " , " sigma " , " distributional " , " auxiliary " ), # nolint
135
+ effects = " fixed" ,
136
+ component = " location" ,
118
137
parameters = NULL ,
119
138
... ) {
120
- # check arguments
121
- effects <- match.arg(effects )
122
- component <- match.arg(component )
123
-
124
139
pars <- insight :: get_parameters(
125
140
model ,
126
141
effects = effects ,
127
142
component = component ,
128
143
parameters = parameters
129
144
)
130
145
131
- s <- as.data.frame(summary(model ))
132
- s <- s [rownames(s ) %in% colnames(pars ), ]
146
+ insight :: check_if_installed(" posterior" )
147
+ idx <- as.data.frame(posterior :: summarise_draws(model ))
148
+ rows_to_keep <- idx $ variable %in% colnames(pars )
149
+ # ess_*() functions are defined in:
150
+ # https://github.com/stan-dev/posterior/blob/master/R/convergence.R
133
151
134
152
data.frame (
135
- Parameter = rownames(s ),
136
- ESS = s [[" n_eff" ]],
153
+ Parameter = idx $ variable [rows_to_keep ],
154
+ ESS = round(idx [rows_to_keep , " ess_bulk" ]),
155
+ ESS_tail = round(idx [rows_to_keep , " ess_tail" ]),
137
156
stringsAsFactors = FALSE ,
138
157
row.names = NULL
139
158
)
@@ -142,18 +161,14 @@ effective_sample.stanmvreg <- function(model,
142
161
143
162
# ' @export
144
163
effective_sample.stanfit <- function (model ,
145
- effects = c( " fixed" , " random " , " all " ) ,
164
+ effects = " fixed" ,
146
165
parameters = NULL ,
147
166
... ) {
148
- # check arguments
149
- effects <- match.arg(effects )
150
-
151
- pars <-
152
- insight :: get_parameters(
153
- model ,
154
- effects = effects ,
155
- parameters = parameters
156
- )
167
+ pars <- insight :: get_parameters(
168
+ model ,
169
+ effects = effects ,
170
+ parameters = parameters
171
+ )
157
172
158
173
insight :: check_if_installed(" rstan" )
159
174
@@ -186,19 +201,15 @@ effective_sample.blavaan <- function(model, parameters = NULL, ...) {
186
201
187
202
# ' @export
188
203
effective_sample.MCMCglmm <- function (model ,
189
- effects = c( " fixed" , " random " , " all " ) ,
204
+ effects = " fixed" ,
190
205
parameters = NULL ,
191
206
... ) {
192
- # check arguments
193
- effects <- match.arg(effects )
194
-
195
- pars <-
196
- insight :: get_parameters(
197
- model ,
198
- effects = effects ,
199
- parameters = parameters ,
200
- summary = TRUE
201
- )
207
+ pars <- insight :: get_parameters(
208
+ model ,
209
+ effects = effects ,
210
+ parameters = parameters ,
211
+ summary = TRUE
212
+ )
202
213
203
214
s.fixed <- as.data.frame(summary(model )$ solutions )
204
215
s.random <- as.data.frame(summary(model )$ Gcovariances )
0 commit comments