lambda.1se不在错误的一个标准错误中

Moo*_*ter 3 r lasso-regression cross-validation

在函数的文档中cv.glmnet(),给出了:

lambda.1se:
lambda的最大值,以使误差在最小值的1个标准误差内。

这意味着lambda.1se给出lambda,从而给出一个误差(cvm),该误差与最小误差相差一个标准误差。

因此,在尝试检查这一事实时:库中
存在一个数据集。我使用套索执行了交叉验证:BostonMASS

x = model.matrix(crim~.-1,data=Boston)#-1 for removing the intercept column
y = Boston$crim
cv.lasso = cv.glmnet(x,y,type.measure = "mse",alpha=1)
Run Code Online (Sandbox Code Playgroud)

而出来的价值cv.lasso$lambda.min是:

> cv.lasso$lambda.min
[1] 0.05630926
Run Code Online (Sandbox Code Playgroud)

并且,值cv.lasso$lambda.1se是:

> cv.lasso$lambda.1se
[1] 3.375651
Run Code Online (Sandbox Code Playgroud)

现在,看看这个:

> std(cv.lasso$cvm)
[1] 0.7177808
Run Code Online (Sandbox Code Playgroud)

std函数是哪里,它返回插入其中的值的标准错误。1
的最小值cvm可以找到:

> cv.lasso$cvm[cv.lasso$lambda==cv.lasso$lambda.min]
[1] 42.95009
Run Code Online (Sandbox Code Playgroud)

因此,我们将标准误差添加到的值,cvm 得到:

> 42.95009+0.7177808
[1] 43.66787
Run Code Online (Sandbox Code Playgroud)

即使没有lambda与此值对应的cvm值,我们也可以根据现有数据得出一个想法:
在此处输入图片说明

这意味着lambda.1se应该在0.4784899和0.4359821之间。但这绝对不是。因此,有种直觉表明我在这里犯了一个错误。你能帮我指出这一点吗?


1:定义std

std<-function(x)
  sd(x)/sqrt(length(x))
Run Code Online (Sandbox Code Playgroud)

jav*_*jav 5

我将添加一个种子,以便可以复制以下结果:

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)
Run Code Online (Sandbox Code Playgroud)

交叉验证的最小MSE为min(cv.lasso$cvm) = 43.51256。对应的lambda为cv.lasso$lambda.min = 0.01843874。该lambda.1secv.lasso$lambda.1se = 3.375651。这对应于交叉验证的MSE

cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.1se)] = 57.5393
Run Code Online (Sandbox Code Playgroud)

我们可以直接从GLMNET的输出访问经过交叉验证的标准错误,如下所示:

cv.lasso$cvsd[which(cv.lasso$lambda == cv.lasso$lambda.min)] = 15.40236
Run Code Online (Sandbox Code Playgroud)

因此,交叉验证的MSE一个标准错误是

43.51256 + 15.40236 = 58.91492 
Run Code Online (Sandbox Code Playgroud)

这仅仅是稍微在比交叉验证MSE更高lambda.1se以上(即57.5393)。如果我们在lambda之前查看交叉验证的MSE lambda.1se,则为:

cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.1se)-1] = 59.89079
Run Code Online (Sandbox Code Playgroud)

现在,我们可以协调GLMNET的输出了,让我解释一下为什么使用您的计算不能得到相同的结果:

  1. cv.lasso$cvm包含的每个值的经过交叉验证的平均MSE lambda
  2. 当我们说1个标准误差时,我们不是在讨论lambda的标准误差,而是谈论给定lambda的褶皱的标准误差。
  3. 继续上述要点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)
Run Code Online (Sandbox Code Playgroud)

注意

> min(cv.lasso$cvm)
[1] 42.76584
> cv.lasso$cvsd[which.min(cv.lasso$cvm)]
[1] 17.89725
Run Code Online (Sandbox Code Playgroud)

(这些与上面的示例不同,因为我们定义了自己的折叠)

还要注意,我keep = Tcv.glmnet调用中还有一个附加参数。这将返回每个lambda的折叠预测。您可以通过执行以下操作提取它们以获得最佳的lambda:

cv.lasso$fit.preval[,which.min(cv.lasso$cvm)]
Run Code Online (Sandbox Code Playgroud)

在继续之前,让我们创建一个包含响应,折叠预测以及相应折叠的数据框:

library(data.table)
OOSPred = data.table(y = y, 
                     predictions = cv.lasso$fit.preval[,which.min(cv.lasso$cvm)], 
                     folds = folds)
Run Code Online (Sandbox Code Playgroud)

这是前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
Run Code Online (Sandbox Code Playgroud)

例如,对于的情况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
Run Code Online (Sandbox Code Playgroud)

最后,我们返回所有MSE的平均MSE和标准误

> OOSPredSum[, list("Mean MSE" = mean(MSE), "Standard Error" = sd(MSE)/sqrt(3))]
   Mean MSE Standard Error
1: 41.05932       17.47213
Run Code Online (Sandbox Code Playgroud)

GLMNET可能正在执行加权均值和标准误(通过每次折叠的观察数加权),这就是为什么收盘价上方的数字不完全匹配的原因。