Bootstrap White test¶
Source: R/additional_tests.R · Help: ?performWhiteTestBootstrap
Approximates the finite-sample distribution of White's LM statistic by resampling the fitted residuals, refitting the model, and recalculating the test statistic across many bootstrap replications.
Usage¶
performWhiteTestBootstrap(
model,
data = NULL,
B = 999,
parallel = FALSE,
n_cores = NULL,
reestimate_weights = NULL
)
Arguments¶
model- A fitted stats::lm object representing the mean specification to be diagnosed.
data- A base::data.frame (or object coercible to one) containing the
variables referenced by
model. It must include the observations used to fitmodeland will be checked for missing values. WhenNULL, the default, the model frame ofmodelis used. It holds the terms of the model rather than its variables (log(x)rather thanx), so a model that transforms a variable needsdata, as does a model with anoffset()term, and so may a fit whoseweightsoroffsetargument is a column of the data, which the model frame holds as(weights)or(offset). B- Integer scalar giving the number of bootstrap replications.
Defaults to 999. The p-value is
(1 + #) / (B_eff + 1), whereB_effis the number of replicates whose statistic is finite (Bwhen every replicate succeeds), so a test at levelalphais exact only whenalpha * (B_eff + 1)is an integer: with 999 it is at the 5% and 1% levels, and with 1000, the default before 0.15.0, at neither. parallel- Logical scalar; if
TRUEthe replicates are computed in parallel, by forked workers (parallel::mclapply()) where the platform can fork and on a socket cluster (parallel::makeCluster()) elsewhere. See Parallel replicates. n_cores- Optional integer number of worker processes when
parallel = TRUE. Defaults toparallel::detectCores() - 1. The result does not depend on it. reestimate_weights- Whether each replicate estimates the weights of a
fitWLS()fit again from the variance functionfitWLS()recorded on it.NULL, the default, does so for afitWLS()fit and holds the weights fixed for any other model.FALSEholds them fixed, as every call did before 0.15.0.TRUEis an error for a model thatfitWLS()did not return, or on which it fell back to equal weights. Each replicate regenerates the response and holds the design fixed, so a variance regressor that uses a variable of the response which the right-hand side of the model does not use, such asyorxforI(y / x) ~ z, or that is the response term itself, as~ .gives, cannot be estimated again:NULLthen holds the weights fixed, with a warning, andTRUEis an error. Giving the response as a column of the data, as inr ~ z, says which variables stay. See Weighted fits.
Value¶
A htest object reporting both the asymptotic White statistic
and its bootstrap p-value. The returned object also stores the simulated test
statistics in boot_statistics for further inspection.
Details¶
For a fitted model \(\hat{y} = X\hat{\beta}\), the algorithm proceeds as follows:
- Compute White's LM statistic \(n R^2\) from the auxiliary regression on squares and cross-products of the regressors.
- Generate \(B\) bootstrap samples by resampling the centred residuals with replacement, forming \(y^{*(b)} = \hat{y} + \hat{e}^{*(b)}\).
- Refit the model to each bootstrap sample and recompute White's statistic \(T^{*(b)}\) using the same auxiliary specification.
- Estimate the bootstrap p-value as \(\hat{p} = (1 + \sum_{b} I\{T^{*(b)} \ge T_{\text{obs}}\}) / (B_{\text{eff}} + 1)\), where \(b\) runs over the \(B_{\text{eff}}\) replicates whose statistic is finite, so the p-value is never zero.
The bootstrap distribution offers improved size control for moderate sample
sizes or high-dimensional designs where the chi-squared approximation may be
inaccurate. When parallel = TRUE the resampling step exploits available CPU
cores to reduce computation time.
Parallel replicates¶
With parallel = TRUE replicate i draws its random numbers from stream
i of a L'Ecuyer-CMRG generator (parallel::nextRNGStream()), seeded by
one number drawn from the session's generator. A call made after
set.seed() therefore returns the same result each time, whatever the
number of workers and whether they are forked or run on a socket cluster.
It does not return the result of the same call with parallel = FALSE,
which draws every replicate from the session's generator, as it did before
0.15.0: the two are bootstraps of the same data with different draws, and
each is valid. Before 0.15.0 a seeded call with parallel = TRUE gave a
different result each time, and on Windows more than one worker was an
error.
Weighted fits¶
A fit with weights \(w_i\) is ordinary least squares on
\(\sqrt{w_i}\, y_i\) and \(\sqrt{w_i}\, x_i\),
whose errors have constant variance under the null hypothesis, and the
bootstrap is carried out in that regression. What is resampled is its
residuals, the Pearson residuals \(\sqrt{w_i}\, e_i\).
When the model has an intercept they are centred, as the residuals of an
unweighted fit with an intercept are, because the weighted regression has
no constant column. Each draw is divided by \(\sqrt{w_i}\) to
return it to the scale of the observation it is added to, and each
replicate is refitted with the weights, so performWhiteTest() computes
its statistic from the Pearson residuals as it does for the fit supplied.
With equal weights the result is that of the unweighted fit.
Weighted or not, each replicate is refitted with an offset the model was
given as an argument, lm(..., offset = o); an offset written in the
formula, offset(o), is evaluated again from the data of the replicate. A
transformed response, such as log(y) in log(y) ~ x, is regenerated on
the scale the model uses, and the refit reads it in place of log(y).
Weights given to the fit are known, and they are held fixed in every
replicate. On a fit returned by fitWLS() they were estimated from the same
data, and since 0.15.0 they are estimated again in each replicate by
default (reestimate_weights): the replicate is fitted as the model
fitWLS() was given, the variance function fitWLS() recorded is fitted
again to its residuals, on the same regressors and with the same form, and
the replicate is refitted with the weights it gives, so that
performWhiteTest() sees a fitWLS() fit of the replicate. A replicate
whose variance function cannot be fitted, where fitWLS() would fall back
to equal weights, counts as a failed replicate, and the p-value is computed
from the replicates that remain; a warning gives the number that failed.
In inst/validation/weighted-fits-size.R, the data have standard deviation
\(\exp(0.3 x)\), the variance function is correctly
specified, the errors are normal, there are 150 observations and
B = 499. At the 5% level the test then rejected 0.064 of the time when it
held the weights of fitWLS() fixed, as every call did before 0.15.0 and
reestimate_weights = FALSE still does. It rejected 0.0415 when it
estimated them again, just below the release gate's interval, 0.042 to
0.058, and 0.054 with the true weights. The section on weighted fits
in performWildBootstrapTest() has the larger error of Koenker's
statistic.
References¶
Efron, B., & Tibshirani, R. J. (1993). An Introduction to the Bootstrap. Chapman & Hall/CRC.
Davidson, R., & MacKinnon, J. G. (2006). The power of bootstrap and asymptotic tests. Journal of Econometrics, 133(2), 421–441. doi:10.1016/j.jeconom.2005.02.002
See also¶
performWhiteTest() for the classical statistic and
performWhiteTestRobust() for enriched diagnostics.
Examples¶
# The bootstrap needs at least 50 observations, so mtcars (32) is too small.
set.seed(42)
n <- 120
sim <- data.frame(x = runif(n, 1, 5))
sim$y <- 1 + 2 * sim$x + rnorm(n, sd = 0.3 + 0.6 * sim$x)
mod <- lm(y ~ x, data = sim)
performWhiteTestBootstrap(mod, sim, B = 199)
# More replications give a smoother p-value estimate
performWhiteTestBootstrap(mod, sim, B = 499)
# parallel = TRUE runs the replicates on n_cores workers, forked where the
# platform can fork and on a socket cluster elsewhere. Two is the most
# R CMD check --as-cran allows, and the result does not depend on it.
set.seed(42)
performWhiteTestBootstrap(mod, sim, B = 199, parallel = TRUE, n_cores = 2)