I'm futzing with getting the SE of model residual standard deviations from a linear regression, and keep getting narrower errors than I should - and I'd like to figure out why.
The basic approach I'm taking is to fit a linear model. Draw simulated coefficients from a multivariate normal distribution. Calculate the RSS and from that, use sqrt(RSS/(n-2)) to calculate the model residual SD. Rinse and repeat 1K times, and then get the SD of the model residual SD.
But... I keep finding that I'm off by an order of magnitude at least. Here's an example in R.
First, the model.
library(palmerpenguins)
plot(bill_length_mm ~ flipper_length_mm, data = penguins)
pen <- lm(bill_length_mm ~ flipper_length_mm, data = penguins)
Then, the simulated coefficients.
library(mvtnorm)
coefTab <- data.frame(rmvnorm(n, coef(pen), sigma = vcov(pen)))
Now, on to getting the residual SD. A function!
get_resid_sd <- function(a, b, y, x){
pred <- a+b*x
res <- y - pred
n <- sum(!is.na(res))
sqrt( sum(res^2, na.rm=T)/(n-2) )
}
And let's apply it to our coefficients
coefTab$sigma <- sapply(1:n,
function(i){
get_resid_sd(coefTab[i,1], coefTab[i,2], penguins$bill_length_mm,
penguins$flipper_length_mm)
})
Now, the SE
> sd(coefTab$sigma)
[1] 0.01208458
OK, but.... to validate, let's use rstanarm
as it naturally produces simulations with no extra work, and can produce equivalent results to lm()
using stan_glm()
with the appropriate optimizer and null priors.
library(rstanarm)
penStan <- stan_glm(bill_length_mm ~ flipper_length_mm, data = penguins,
algorithm = "optimizing", prior = NULL,
prior_intercept = NULL, prior_aux = NULL)
Now, the SE of the model residual SD....
> sd(as.matrix(penStan)[,3])
[1] 0.1639105
Huh. You see why I'm a) glad I checked myself and b) why I'm worried I did something tragically wrong.
Would love to know folks' thoughts, as if fixed, I think this is a killer example for students. Feel like I'm falling down on something obvious due to 2020 brain.