n <- 1000
betas <- c(1.2, 3, -2)
X <- cbind(var1 = rnorm(n, 0, 1), var2 = rnorm(n, 0, 2), var3 = rnorm(n, 0, 1.5))
set.seed(1)
epsilon <- rnorm(n, 0, 1)
y <- X %*% betas + epsilon
data <- data.frame(cbind(y, X))
colnames(data) <- c("y", "var1", "var2", "var3")
> head(data)
y var1 var2 var3
1 9.983021 0.07730312 1.7000869 -2.7082253
2 -3.690355 -0.29686864 -1.8506260 -1.0170610
3 4.526042 -1.18324224 1.7871624 -0.7100371
4 -7.119478 0.01129269 -1.8820195 1.5411256
5 6.545304 0.99160104 1.0779042 -0.8960814
6 -3.479102 1.59396745 -0.3639488 1.7397741
I generate data from $Y = X\beta + \epsilon$. Assume that $X$ is fixed, and the only thing that is random is $\epsilon$. I divide the data set in half: half for training and half for testing.
# Split the data set into training and test set
train <- data[1:(n/2), ]
test <- data[(n/2 + 1): n, ]
test_X <- test[, names(test) != "y", drop = FALSE]
I fit an OLS model and calculate the empirical prediction error and get a value of 1.120582
.
# Fit OLS model and calculate empirical prediction error
model <- lm(y ~ var1 + var2 + var3 - 1, data = train)
> mean((test$y - predict(model, newdata = test_X))^2)
[1] 1.120582
I then calculate the MSPE according to its formula:
\begin{align*} E||Y_{test} - X_{test} \hat{\beta}_{OLS}||_2^2 &= Var(X_{test}\hat{\beta}_{OLS}) + N_{test} * \sigma^2_{\epsilon}\\ &= tr\left(X_{test} Cov(\hat{\beta}_{OLS}) X_{test}^T\right) + N_{test} * \sigma^2_{\epsilon} \end{align*}
In this case, $N = 1000,$ so $N_{test} = N/2 = 500$, and $\sigma^2_{\epsilon} = 1$. Using the above formula, I get an MSPE of 503.0804
, which is very different from the 1.120582
I found above. I understand that MSPE is an expected value, i.e., ideally I would generate many data sets and average across their prediction error. However, the difference between 503.0804
and 1.120582
is so big that it leads me to think that I might have written down the formula or coded it wrong. Any thoughts?
# Calculate the MPSE
> sum(diag(as.matrix(test_X) %*% as.matrix(vcov(model)) %*% as.matrix(t(test_X)))) + nrow(test_X) * sigma2
[1] 503.0804