向线性模型添加更多变量并不意味着更好地估计真实参数
这不仅仅是估计变量,还有变量选择。当你只选择<10个变量时,你不可避免地会出错。
这就是为什么当您为子集选择较大尺寸时误差会减小。因为更多的系数,可能是来自真实模型的系数,正在被估计(而不是左等于零)。
由于变量之间的高度相关性,误差的减少比k=10
最强的改进发生在 k=10 之前。但是在的情况下,您还没有到达那里,并且您偶尔会从真实模型中选择错误的系数。k=10
此外,附加变量可能会产生一些正则化效果。
请注意,在某个点之后,大约 ,添加更多变量时错误会上升。k=16
图的再现
在最后的 R 代码中,我试图重现前向逐步情况的图表。(这也是这里的问题:Recreating figure from Elements of Statistical Learning)
我可以使图看起来相似
但是,我需要对生成进行一些调整,使用而不是(我仍然没有得到与开始于0.95 并下降到 0.65,而使用此处的代码计算的 MSE 则要低得多)。尽管如此,形状在质量上是相同的。β∼N(1,0.4)β∼N(0,0.4)
这张图中的误差并不是因为偏差:我想将均方误差分成偏差和方差(通过计算系数的平均误差和误差的方差)。但是,偏差非常低!这是由于参数之间的高度相关性。当您有一个只有 1 个参数的子集时,该子集中的选定参数将补偿缺失的参数(它可以这样做,因为它是高度相关的)。其他参数过低的量将或多或少地等于所选参数过高的量。因此,平均而言,一个参数或多或少会过高或过低。
- 上图的相关系数为 0.15 而不是 0.85。
- 此外,我使用了固定的和(否则偏差将平均为零,对此进行更多解释)。Xβ
参数估计的误差分布
下面你会看到参数估计中的误差是如何作为子集大小的函数分布的。这使得更容易理解为什么均方误差的变化表现得如此。β^1−β1
注意以下特点
- 小的子集大小有一个峰值。这是因为参数通常不包含在子集中,并且估计将为零,从而使误差等于。随着子集大小的增加和包含参数的概率增加,该峰值的大小减小。β^β^−β−β
- 当单峰尺寸减小时,或多或少有一个尺寸增大的高斯分布分量。这是参数包含在子集中时的错误。对于较小的子集大小,此组件中的误差不以零为中心。原因是该参数需要补偿另一个参数(与之高度相关)的遗漏。这使得偏差的计算实际上非常低。差异很大。
上面的例子是固定的和。如果您要更改每个模拟的,那么偏差每次都会不同。如果然后将偏差计算为,那么您将非常接近于零。βXβE(β^−β)
library(MASS)
### function to do stepforward regression
### adding variables with best increase in RSS
stepforward <- function(Y,X, intercept) {
kl <- length(X[1,]) ### number of columns
inset <- c()
outset <- 1:kl
best_RSS <- sum(Y^2)
### outer loop increasing subset size
for (k in 1:kl) {
beststep_RSS <- best_RSS ### RSS to beat
beststep_par <- 0
### inner looping trying all variables that can be added
for (par in outset) {
### create a subset to test
step_set <- c(inset,par)
step_data <- data.frame(Y=Y,X=X[,step_set])
### perform model with subset
if (intercept) {
step_mod <- lm(Y ~ . + 1, data = step_data)
}
else {
step_mod <- lm(Y ~ . + 0, data = step_data)
}
step_RSS <- sum(step_mod$residuals^2)
### compare if it is an improvement
if (step_RSS <= beststep_RSS) {
beststep_RSS <- step_RSS
beststep_par <- par
}
}
bestRSS <- beststep_RSS
inset <- c(inset,beststep_par)
outset[-which(outset == beststep_par)]
}
return(inset)
}
get_error <- function(X = NULL, beta = NULL, intercept = 0) {
### 31 random X variables, standard normal
if (is.null(X)) {
X <- mvrnorm(300,rep(0,31), M)
}
### 10 random beta coefficients 21 zero coefficients
if (is.null(beta)) {
beta <- c(rnorm(10,1,0.4^0.5),rep(0,21))
}
### Y with added noise
Y <- (X %*% beta) + rnorm(300,0,6.25^0.5)
### get step order
step_order <- stepforward(Y,X, intercept)
### error computation
l <- 10
error <- matrix(rep(0,31*31),31) ### this variable will store error for 31 submodel sizes
for (l in 1:31) {
### subdata
Z <- X[,step_order[1:l]]
sub_data <- data.frame(Y=Y,Z=Z)
### compute model
if (intercept) {
sub_mod <- lm(Y ~ . + 1, data = sub_data)
}
else {
sub_mod <- lm(Y ~ . + 0, data = sub_data)
}
### compute error in coefficients
coef <- rep(0,31)
if (intercept) {
coef[step_order[1:l]] <- sub_mod$coefficients[-1]
}
else {
coef[step_order[1:l]] <- sub_mod$coefficients[]
}
error[l,] <- (coef - beta)
}
return(error)
}
### correlation matrix for X
M <- matrix(rep(0.15,31^2),31)
for (i in 1:31) {
M[i,i] = 1
}
### perform 50 times the model
set.seed(1)
X <- mvrnorm(300,rep(0,31), M)
beta <- c(rnorm(10,1,0.4^0.5),rep(0,21))
nrep <- 500
me <- replicate(nrep,get_error(X,beta, intercept = 1)) ### this line uses fixed X and beta
###me <- replicate(nrep,get_error(X,beta, intercept = 1)) ### this line uses random X and fixed beta
###me <- replicate(nrep,get_error(X,beta, intercept = 1)) ### random X and beta each replicate
### storage for error statistics per coefficient and per k
mean_error <- matrix(rep(0,31^2),31)
mean_MSE <- matrix(rep(0,31^2),31)
mean_var <- matrix(rep(0,31^2),31)
### compute error statistics
### MSE, and bias + variance for each coefficient seperately
### k relates to the subset size
### i refers to the coefficient
### averaging is done over the multiple simulations
for (i in 1:31) {
mean_error[i,] <- sapply(1:31, FUN = function(k) mean(me[k,i,]))
mean_MSE[i,] <- sapply(1:31, FUN = function(k) mean(me[k,i,]^2))
mean_var[i,] <- mean_MSE[i,] - mean_error[i,]^2
}
### plotting curves
### colMeans averages over the multiple coefficients
layout(matrix(1))
plot(1:31,colMeans(mean_MSE[1:31,]), ylim = c(0,0.4), xlim = c(1,31), type = "l", lwd = 2,
xlab = "Subset size k", ylab = "mean square error of parameters",
xaxs = "i", yaxs = "i")
points(1:31,colMeans(mean_MSE[1:31,]), pch = 21 , col = 1, bg = 0, cex = 0.7)
lines(1:31,colMeans(mean_var[1:31,]), lty = 2)
lines(1:31,colMeans(mean_error[1:31,]^2), lty = 3)
legend(31,0.4, c("MSE", "variance component", "bias component"),
lty = c(1,2,3), lwd = c(2,1,1), pch = c(21,NA,NA), col = 1, pt.bg = 0, xjust = 1,
cex = 0.7)
### plotting histogram
layout(matrix(1:5,5))
par(mar = c(4,4,2,1))
xpar = 1
for (col in c(1,4,7,10,13)) {
hist(me[col,xpar,], breaks = seq(-7,7,0.05),
xlim = c(-1,1), ylim = c(0,500),
xlab = "", ylab = "", main=paste0("error in parameter ",xpar," for subset size ",col),
)
}