lambda.1se 不在错误的一个标准错误中
lambda.1se not being in one standard error of the error
在函数 cv.glmnet()
的文档中给出:
lambda.1se :
largest value of lambda such that error is within 1 standard error of the minimum.
这意味着 lambda.1se
给出了 lambda
,它给出了一个误差 (cvm
),距离最小误差只有一个标准误差。
所以,在尝试检查这个事实时:
库MASS
中有一个数据集Boston
。我使用套索执行了交叉验证:
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)
而 cv.lasso$lambda.min
的值是:
> cv.lasso$lambda.min
[1] 0.05630926
并且,cv.lasso$lambda.1se
的值为:
> cv.lasso$lambda.1se
[1] 3.375651
现在,看看这个:
> std(cv.lasso$cvm)
[1] 0.7177808
其中 std
是一个函数,即 returns 插入其中的值的标准误差。1
而cvm
的最小值可以求得为:
> cv.lasso$cvm[cv.lasso$lambda==cv.lasso$lambda.min]
[1] 42.95009
因此,我们将标准误差添加到 cvm
的值中,我们得到:
> 42.95009+0.7177808
[1] 43.66787
这个cvm
值虽然没有对应的lambda
值,但是我们可以根据已有的数据来推测一下:
这意味着 lambda.1se
应该在 0.4784899 和 0.4359821 之间。但事实并非如此。所以,有一种直觉说我在这里犯了一个错误。你能帮我指点一下吗?
1:std
的定义:
std<-function(x)
sd(x)/sqrt(length(x))
我将添加一个种子,以便可以复制以下结果:
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
这仅略高于上面 lambda.1se
处的交叉验证 MSE(即 57.5393
)。如果我们在 lambda.1se
之前的 lambda
查看交叉验证的 MSE,它是:
cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.1se)-1] = 59.89079
现在我们可以协调 GLMNET 的输出,让我解释一下为什么您使用您的计算没有得到相同的结果:
cv.lasso$cvm
包含 lambda
的每个值的交叉验证平均 MSE。
- 当我们说 1 个标准错误时,我们不是在谈论 lambda 的标准错误,而是给定 lambda 的折叠标准错误。
- 继续上面的点,在
lambda.min
,我们有10折。我们拟合了 10 个模型并有 10 个样本外 MSE。 cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.min)]
给出了这 10 个 MSE 的平均值。这 10 个 MSE 的标准差由 cv.lasso$cvsd[which(cv.lasso$lambda == cv.lasso$lambda.min)]
给出。我们在 GLMNET 输出中没有给出的是 lambda.min
处的 10 个 MSE。如果我们有这个,那么我们应该能够使用上面的公式复制标准错误。
如果有帮助请告诉我。
编辑:让我们做一个例子,我们预先定义三折
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
(这些与前面的示例不同,因为我们已经定义了自己的折叠)
另请注意,我在 cv.glmnet
调用中有一个附加参数 keep = T
。这 return 是每个 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
最后,我们return MSE 的平均 MSE 和标准误差
> OOSPredSum[, list("Mean MSE" = mean(MSE), "Standard Error" = sd(MSE)/sqrt(3))]
Mean MSE Standard Error
1: 41.05932 17.47213
GLMNET 可能正在执行加权均值和标准误差(由每次折叠中的观察次数加权),这就是为什么收盘价以上的数字并不完全匹配。
我认为程序是:
- 对于每个 ƛ,它创建 x 个模型(x = nº of folds 其中数据集已被分割用于交叉验证算法)
- 对于每个 ƛ 和每个模型 x,它计算均值(误差)和 sd(误差),因此,均值( x 错误)和 sd(x 错误)
假设我们有 ƛmin 和 serrorƛmin(在步骤 2 中计算)。现在,ƛse 定义为 "largest value of lambda such that error is within 1 standard error of the minimum"。那么ƛse的条件是:
ƛse 在 [ƛmin - seƛmin, ƛmin + seƛmin]
Then ƛse = max(ƛ),ƛ 其中满足上述条件。
我可以给你举个例子:
lasso_cv <- cv.glmnet(x = x, y= endpoint, alpha = 1, lambda = lambdas_to_try,
standardize = TRUE, nfolds = 10,type.measure="auc",
family="binomial")
注意 ƛmin 是:
lasso_cv$lambda.min
[1] 0.007742637
而 serrorƛmin 是:
serrorlmin <- lasso_cv$cvsd[which(lasso_cv$lambda == lasso_cv$lambda.min)]
serrorlmin
[1] 0.01058009
那么,ƛse选择的范围是:
rang <- c(lasso_cv$lambda.min - serrorlmin,lasso_cv$lambda.min + serrorlmin)
[1] -0.002837457 0.018322731
并找到它:
max(lasso_cv$lambda[lasso_cv$lambda>=rang[1] & lasso_cv$lambda<=rang[2]])
[1] 0.01629751
并且此值匹配 ƛse!
lasso_cv$lambda.1se # 0.01629751
希望对您有所帮助!
在函数 cv.glmnet()
的文档中给出:
lambda.1se :
largest value of lambda such that error is within 1 standard error of the minimum.
这意味着 lambda.1se
给出了 lambda
,它给出了一个误差 (cvm
),距离最小误差只有一个标准误差。
所以,在尝试检查这个事实时:
库MASS
中有一个数据集Boston
。我使用套索执行了交叉验证:
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)
而 cv.lasso$lambda.min
的值是:
> cv.lasso$lambda.min
[1] 0.05630926
并且,cv.lasso$lambda.1se
的值为:
> cv.lasso$lambda.1se
[1] 3.375651
现在,看看这个:
> std(cv.lasso$cvm)
[1] 0.7177808
其中 std
是一个函数,即 returns 插入其中的值的标准误差。1
而cvm
的最小值可以求得为:
> cv.lasso$cvm[cv.lasso$lambda==cv.lasso$lambda.min]
[1] 42.95009
因此,我们将标准误差添加到 cvm
的值中,我们得到:
> 42.95009+0.7177808
[1] 43.66787
这个cvm
值虽然没有对应的lambda
值,但是我们可以根据已有的数据来推测一下:
这意味着 lambda.1se
应该在 0.4784899 和 0.4359821 之间。但事实并非如此。所以,有一种直觉说我在这里犯了一个错误。你能帮我指点一下吗?
1:std
的定义:
std<-function(x)
sd(x)/sqrt(length(x))
我将添加一个种子,以便可以复制以下结果:
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
。这对应于
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
这仅略高于上面 lambda.1se
处的交叉验证 MSE(即 57.5393
)。如果我们在 lambda.1se
之前的 lambda
查看交叉验证的 MSE,它是:
cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.1se)-1] = 59.89079
现在我们可以协调 GLMNET 的输出,让我解释一下为什么您使用您的计算没有得到相同的结果:
cv.lasso$cvm
包含lambda
的每个值的交叉验证平均 MSE。- 当我们说 1 个标准错误时,我们不是在谈论 lambda 的标准错误,而是给定 lambda 的折叠标准错误。
- 继续上面的点,在
lambda.min
,我们有10折。我们拟合了 10 个模型并有 10 个样本外 MSE。cv.lasso$cvm[which(cv.lasso$lambda == cv.lasso$lambda.min)]
给出了这 10 个 MSE 的平均值。这 10 个 MSE 的标准差由cv.lasso$cvsd[which(cv.lasso$lambda == cv.lasso$lambda.min)]
给出。我们在 GLMNET 输出中没有给出的是lambda.min
处的 10 个 MSE。如果我们有这个,那么我们应该能够使用上面的公式复制标准错误。
如果有帮助请告诉我。
编辑:让我们做一个例子,我们预先定义三折
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
(这些与前面的示例不同,因为我们已经定义了自己的折叠)
另请注意,我在 cv.glmnet
调用中有一个附加参数 keep = T
。这 return 是每个 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
最后,我们return MSE 的平均 MSE 和标准误差
> OOSPredSum[, list("Mean MSE" = mean(MSE), "Standard Error" = sd(MSE)/sqrt(3))]
Mean MSE Standard Error
1: 41.05932 17.47213
GLMNET 可能正在执行加权均值和标准误差(由每次折叠中的观察次数加权),这就是为什么收盘价以上的数字并不完全匹配。
我认为程序是:
- 对于每个 ƛ,它创建 x 个模型(x = nº of folds 其中数据集已被分割用于交叉验证算法)
- 对于每个 ƛ 和每个模型 x,它计算均值(误差)和 sd(误差),因此,均值( x 错误)和 sd(x 错误)
假设我们有 ƛmin 和 serrorƛmin(在步骤 2 中计算)。现在,ƛse 定义为 "largest value of lambda such that error is within 1 standard error of the minimum"。那么ƛse的条件是:
ƛse 在 [ƛmin - seƛmin, ƛmin + seƛmin]
Then ƛse = max(ƛ),ƛ 其中满足上述条件。
我可以给你举个例子:
lasso_cv <- cv.glmnet(x = x, y= endpoint, alpha = 1, lambda = lambdas_to_try,
standardize = TRUE, nfolds = 10,type.measure="auc",
family="binomial")
注意 ƛmin 是:
lasso_cv$lambda.min
[1] 0.007742637
而 serrorƛmin 是:
serrorlmin <- lasso_cv$cvsd[which(lasso_cv$lambda == lasso_cv$lambda.min)]
serrorlmin
[1] 0.01058009
那么,ƛse选择的范围是:
rang <- c(lasso_cv$lambda.min - serrorlmin,lasso_cv$lambda.min + serrorlmin)
[1] -0.002837457 0.018322731
并找到它:
max(lasso_cv$lambda[lasso_cv$lambda>=rang[1] & lasso_cv$lambda<=rang[2]])
[1] 0.01629751
并且此值匹配 ƛse!
lasso_cv$lambda.1se # 0.01629751
希望对您有所帮助!