The issues is that the standard errors comes from
$$\hat\sigma^2 (X^\top X)^{-1}$$
where $\hat\sigma^2$ is the unbiased estimator and not the MLE. See summary.lm
summary.lm
#R function (object, correlation = FALSE, symbolic.cor = FALSE,
#R ...)
#R {
#R z <- object
#R p <- z$rank
#R rdf <- z$df.residual
#R ...
#R Qr <- qr.lm(object)
#R ...
#R r <- z$residuals
#R f <- z$fitted.values
#R w <- z$weights
#R if (is.null(w)) {
#R mss <- if (attr(z$terms, "intercept"))
#R sum((f - mean(f))^2)
#R else sum(f^2)
#R rss <- sum(r^2)
#R }
#R ...
#R resvar <- rss/rdf
#R ...
#R R <- chol2inv(Qr$qr[p1, p1, drop = FALSE])
#R se <- sqrt(diag(R) * resvar)
#R ...
This is the inverse observed Fisher information for $(\beta_0, \beta_1)$ conditional on $\hat\sigma^2$. Now the inverse observed Fisher information you compute is for the triplet $(\beta_0, \beta_1, \sigma)$. I.e., you use the MLE of $\sigma$ and not the unbiased estimator. Thus, I gather the standard errors should differ by factor $\sqrt{n/(n-3 + 1)}$ or something similar. This is the case
set.seed(1)
n = 4 # very small sample size !
b0 <- 5
b1 <- 2
sigma <- 5
x <- runif(n, 1, 100)
y = b0 + b1*x + rnorm(n, 0, sigma)
negLL <- function(beta, y, x) {
b0 <- beta[1]
b1 <- beta[2]
sigma <- beta[3]
yhat <- b0 + b1*x
return(-sum(dnorm(y, yhat, sigma, log = TRUE)))
}
res <- optim(c(0, 0, 1), negLL, y = y, x = x, hessian=TRUE)
estimates <- res$par # Parameters estimates
(se <- sqrt(diag(solve(res$hessian))))
#R [1] 5.690 0.097 1.653
k <- 3
se * sqrt(n / (n-k+1))
#R [1] 8.047 0.137 2.338
To elaborate more as usεr11852 requests, the log-likelihood is
$$l(\vec{\beta},\sigma) = -\frac{n}{2}\log(2\pi) - n\log{\sigma} - \frac{1}{2\sigma^2}(\vec{y}-X\vec\beta)^\top(\vec{y}-X\vec\beta)$$
where $X$ is the design matrix and $n$ is the number of observation. Consequently, the observed information matrix is
$$-\nabla_{\vec{\beta}}\nabla_{\vec{\beta}}^\top l(\vec{\beta},\sigma) = \frac{1}{\sigma^2}X^\top X$$
Now we can either plug in the MLE or the unbaised estimator of $\sigma$ as the following show
m <- lm(y ~ x)
X <- cbind(1, x)
sqrt(sum(resid(m)^2)/n * diag(solve(crossprod(X))))
#R x
#R 5.71058285 0.09732149
k <- 3
sqrt(sum(resid(m)^2)/(n-k+1) * diag(solve(crossprod(X))))
#R x
#R 8.0759837 0.1376334
We can do the same with a QR decomposition as lm
does
obj <- qr(X)
sqrt(sum(resid(m)^2)/(n-k+1) * diag(chol2inv(obj$qr)))
#R [1] 8.0759837 0.1376334
So to answer
I understand from my readings on the web that optimization is not a simple task but I was wondering if it would be possible to reproduce in a simple way the standard error estimates from
glm
while usingoptim
.
then you need to scale up the standard errors in the Gaussian example you use.