我将添加一个种子,以便可以复制以下结果:
library(glmnet)
library(MASS)
data("Boston")
x = model.matrix(crim~.-1,data=Boston)#-1 for removing the intercept column
y = Boston$crim
set.seed(100)
cv.lasso = cv.glmnet(x,y,type.measure = "mse",alpha=1)
最小交叉验证的 MSE 是min(cv.lasso$cvm) = 43.51256
. 对应的 lambda 是cv.lasso$lambda.min = 0.01843874
。lambda.1se
是cv.lasso$lambda.1se = 3.375651
。_ 这对应于交叉验证的 MSE
cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.1se)] = 57.5393
我们可以直接从 GLMNET 的输出中访问经过交叉验证的标准错误,如下所示:
cv.lasso$cvsd[which(cv.lasso$lambda == cv.lasso$lambda.min)] = 15.40236
所以交叉验证的 MSE 一个标准错误是
43.51256 + 15.40236 = 58.91492
这仅略高于上述交叉验证的 MSE lambda.1se
(即57.5393
)。lambda
如果我们在之前查看交叉验证的 MSE lambda.1se
,它是:
cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.1se)-1] = 59.89079
因此,现在我们可以协调 GLMNET 的输出,让我解释一下为什么使用您的计算没有得到相同的结果:
cv.lasso$cvm
包含 的每个值的交叉验证平均 MSE lambda
。
- 当我们说 1 个标准错误时,我们不是在谈论跨 lambda 的标准错误,而是跨给定 lambda 折叠的标准错误。
- 继续上述观点,在 处
lambda.min
,我们有 10 次折叠。我们拟合了 10 个模型并有 10 个样本外 MSE。这 10 个 MSE 的平均值由 给出cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.min)]
。这 10 个 MSE 的标准偏差由 给出cv.lasso$cvsd[which(cv.lasso$lambda == cv.lasso$lambda.min)]
。GLMNET 输出中没有给出的是 10 个 MSE lambda.min
。如果我们有这个,那么我们应该能够通过使用上面的公式来复制标准误差。
让我知道这是否有帮助。
编辑:让我们做一个例子,我们预先定义三个折叠
set.seed(100)
folds = sample(1:3, nrow(x), replace = T)
cv.lasso = cv.glmnet(x,y,type.measure = "mse",alpha=1, keep =T, foldid = folds)
注意
> min(cv.lasso$cvm)
[1] 42.76584
> cv.lasso$cvsd[which.min(cv.lasso$cvm)]
[1] 17.89725
(这些与前面的示例不同,因为我们已经定义了自己的折叠)
另请注意,我keep = T
在cv.glmnet
调用中有一个附加参数。这将返回每个 lambda 的折叠预测。您可以通过执行以下操作提取它们以获得最佳 lambda:
cv.lasso$fit.preval[,which.min(cv.lasso$cvm)]
在我们继续之前,让我们创建一个包含响应、折叠预测和相应折叠的数据框:
library(data.table)
OOSPred = data.table(y = y,
predictions = cv.lasso$fit.preval[,which.min(cv.lasso$cvm)],
folds = folds)
这是前 10 行的预览:
> head(OOSPred, 10)
y predictions folds
1: 0.00632 -0.7477977 1
2: 0.02731 -1.3823830 1
3: 0.02729 -3.4826143 2
4: 0.03237 -4.4419795 1
5: 0.06905 -3.4373021 2
6: 0.02985 -2.5256505 2
7: 0.08829 0.7343478 3
8: 0.14455 1.1262462 2
9: 0.21124 4.0507847 2
10: 0.17004 0.5859587 1
例如,对于 的情况folds = 1
,模型建立在折叠 #2 和 #3 上,然后对折叠 #1 中的观察结果进行预测。我们现在按倍计算 MSE:
OOSPredSum = OOSPred[, list(MSE = mean((y - predictions)^2)), by = folds]
folds MSE
1: 1 27.51469
2: 2 75.72847
3: 3 19.93480
最后,我们返回折叠中 MSE 的平均 MSE 和标准误差
> OOSPredSum[, list("Mean MSE" = mean(MSE), "Standard Error" = sd(MSE)/sqrt(3))]
Mean MSE Standard Error
1: 41.05932 17.47213
GLMNET 可能正在执行加权平均值和标准误差(由每个折叠中的观察数加权),这就是为什么上面的数字接近但不完全匹配的原因。