当通过 glmnet 包估计套索模型时,我想知道是否更好:(a)直接从 cv.fit 对象中提取系数/预测/偏差cv.glmnet,或者(b)使用最小 lambda fromcv.glmnet重新运行glmnet并从glmnet进程中拉出这些对象。(请耐心等待——我觉得这已经被记录在案了,但我在网上看到了这两个例子/教程,并且没有可靠的逻辑来选择一种方式。)
也就是说,对于系数,我可以运行(a):
cvfit = cv.glmnet(x=xtrain, y=ytrain, alpha=1, type.measure = "mse", nfolds = 20)
coef.cv <- coef(cvfit, s = "lambda.min")
Run Code Online (Sandbox Code Playgroud)
或者我之后可以运行(b):
fit = glmnet(x=xtrain, y=ytrain, alpha=1, lambda=cvfit$lambda.min)
coef <- coef(fit, s = "lambda.min")
Run Code Online (Sandbox Code Playgroud)
虽然这两个过程选择相同的模型变量,但它们不会产生相同的系数。同样,我可以通过以下两个过程之一进行预测:
prdct <- predict(fit,newx=xtest)
prdct.cv <- predict(cvfit, newx=xtest, s = "lambda.min")
Run Code Online (Sandbox Code Playgroud)
他们预测相似但不相同的向量。
最后,我认为我可以通过以下两种方法之一解释 % 偏差:
percdev <- fit$dev.ratio
percdev.cv <- cvfit$glmnet.fit$dev.ratio[cvfit$cvm==mse.min.cereal]
Run Code Online (Sandbox Code Playgroud)
但实际上,这样拉是不可能的percdev.cv,因为如果 cv.glmnet 使用的 lambda 序列少于 100 个元素,则cvfit$glmnet.fit$dev.ratio和的长度cvfit$cvm==mse.min.cereal不匹配。所以我不太确定如何从cvfit$glmnet.fit.
所以我想我想知道哪个过程是最好的,为什么以及人们通常如何提取适当的 dev.ratio 统计数据。谢谢!
正如评论中所指出的,它与提供的 lambda 序列有关,因为如果您查看 的源代码,它会在前几行中cv.glmnet调用which在定义的 lambda 值上运行。glmnet:::cv.glmnet.rawglmnet()
所以我们可以使用下面的例子:
library(mlbench)
data(BostonHousing)
data = BostonHousing
data$chas=as.numeric(data$chas)
cvfit = cv.glmnet(x=as.matrix(data[,-14]),y=data[,14])
coef.cv <- coef(cvfit, s = "lambda.min")
fit = glmnet(x=as.matrix(data[,-14]), y=data[,14], alpha=1, lambda=cvfit$lambda.min)
coef <- coef(fit, s = "lambda.min")
head(cbind(coef.cv,coef))
6 x 2 sparse Matrix of class "dgCMatrix"
1 1
(Intercept) 31.74123706 31.86654225
crim -0.09834634 -0.09869320
zn 0.04144161 0.04158829
indus . .
chas 2.68518774 2.68163334
nox -16.30664523 -16.35459059
Run Code Online (Sandbox Code Playgroud)
它们略有不同,如果您提供 cv.glmnet 中使用的 lambda 序列:
fit = glmnet(x=as.matrix(data[,-14]), y=data[,14], alpha=1, lambda=cvfit$lambda)
coef <- coef(fit, s = cvfit$lambda.min)
head(cbind(coef.cv,coef))
6 x 2 sparse Matrix of class "dgCMatrix"
1 1
(Intercept) 31.74123706 31.74123706
crim -0.09834634 -0.09834634
zn 0.04144161 0.04144161
indus . .
chas 2.68518774 2.68518774
nox -16.30664523 -16.30664523
Run Code Online (Sandbox Code Playgroud)
他们现在是一样的。dev.ratio 也会匹配:
fit$dev.ratio[fit$lambda==cvfit$lambda.min]
[1] 0.7401482
cvfit$glmnet.fit$dev.ratio[which.min(cvfit$cvm)]
[1] 0.7401482
Run Code Online (Sandbox Code Playgroud)