插入符号 glmnet 与 cv.glmnet

机器算法验证 r 插入符号 网络
2022-02-16 03:37:31

glmnet在比较使用withincaret搜索最佳 lambda 和 usingcv.glmnet执行相同任务时,似乎存在很多混淆。

提出了许多问题,例如:

分类模型 train.glmnet 与 cv.glmnet?

将 glmnet 与插入符号一起使用的正确方法是什么?

使用 `caret` 交叉验证 `glmnet`

但没有给出答案,这可能是由于问题的可重复性。在第一个问题之后,我给出了一个非常相似的例子,但确实有同样的问题:为什么估计的 lambdas 如此不同?

library(caret)
library(glmnet)
set.seed(849)
training <- twoClassSim(50, linearVars = 2)
set.seed(849)
testing <- twoClassSim(500, linearVars = 2)
trainX <- training[, -ncol(training)]
testX <- testing[, -ncol(testing)]
trainY <- training$Class

# Using glmnet to directly perform CV
set.seed(849)
cvob1=cv.glmnet(x=as.matrix(trainX),y=trainY,family="binomial",alpha=1, type.measure="auc", nfolds = 3,lambda = seq(0.001,0.1,by = 0.001),standardize=FALSE)

cbind(cvob1$lambda,cvob1$cvm)

# best parameter
cvob1$lambda.mi

# best coefficient
coef(cvob1, s = "lambda.min")


# Using caret to perform CV
cctrl1 <- trainControl(method="cv", number=3, returnResamp="all",classProbs=TRUE,summaryFunction=twoClassSummary)
set.seed(849)
test_class_cv_model <- train(trainX, trainY, method = "glmnet", trControl = cctrl1,metric = "ROC",
                             tuneGrid = expand.grid(alpha = 1,lambda = seq(0.001,0.1,by = 0.001)))


test_class_cv_model 

# best parameter
test_class_cv_model$bestTune

# best coefficient
coef(test_class_cv_model$finalModel, test_class_cv_model$bestTune$lambda)

总而言之,最佳 lambda 表达式如下:

  • 0.055 通过使用cv.glmnet()

  • 0.001 通过使用train()

我知道使用standardize=FALSEincv.glmnet()是不可取的,但我真的想使用相同的先决条件比较这两种方法。作为主要解释,我认为每个折叠的抽样方法可能是一个问题——但我使用相同的种子,结果却大不相同。

所以我真的很困惑为什么这两种方法如此不同,而它们应该非常相似?- 我希望社区对这里的问题有所了解

1个回答

我在这里看到两个问题。首先,你的训练集相对于你的测试集来说太小了。通常,我们需要一个至少在大小上与测试集相当的训练集。另一个注意事项是,对于交叉验证,您根本没有使用测试集,因为该算法基本上使用“训练集”为您创建测试集。所以你最好使用更多的数据作为你的初始训练集。

其次,3 折太小,你的简历不可靠。通常,建议 5-10 折(nfolds = 5forcv.glmnetnumber=5for caret)。通过这些更改,我在两种方法中得到了相同的 lambda 值和几乎相同的估计值:

set.seed(849)
training <- twoClassSim(500, linearVars = 2)
set.seed(849)
testing <- twoClassSim(50, linearVars = 2)
trainX <- training[, -ncol(training)]
testX <- testing[, -ncol(testing)]
trainY <- training$Class

# Using glmnet to directly perform CV
set.seed(849)
cvob1=cv.glmnet(x=as.matrix(trainX), y=trainY,family="binomial",alpha=1, 
                type.measure="auc", nfolds = 5, lambda = seq(0.001,0.1,by = 0.001),
                standardize=FALSE)

cbind(cvob1$lambda,cvob1$cvm)

# best parameter
cvob1$lambda.min

# best coefficient
coef(cvob1, s = "lambda.min")


# Using caret to perform CV
cctrl1 <- trainControl(method="cv", number=5, returnResamp="all",
                       classProbs=TRUE, summaryFunction=twoClassSummary)
set.seed(849)
test_class_cv_model <- train(trainX, trainY, method = "glmnet", 
                             trControl = cctrl1,metric = "ROC",
                             tuneGrid = expand.grid(alpha = 1,
                                                    lambda = seq(0.001,0.1,by = 0.001)))

test_class_cv_model 

# best parameter
test_class_cv_model$bestTune

# best coefficient
coef(test_class_cv_model$finalModel, test_class_cv_model$bestTune$lambda)

结果:

> cvob1$lambda.min
[1] 0.001

> coef(cvob1, s = "lambda.min")
8 x 1 sparse Matrix of class "dgCMatrix"
1
(Intercept) -0.781015706
TwoFactor1  -1.793387005
TwoFactor2   1.850588656
Linear1      0.009341356
Linear2     -1.213777391
Nonlinear1   1.158009360
Nonlinear2   0.609911748
Nonlinear3   0.246029667

> test_class_cv_model$bestTune
alpha lambda
1     1  0.001

> coef(test_class_cv_model$finalModel, test_class_cv_model$bestTune$lambda)
8 x 1 sparse Matrix of class "dgCMatrix"
1
(Intercept) -0.845792624
TwoFactor1  -1.786976586
TwoFactor2   1.844767690
Linear1      0.008308165
Linear2     -1.212285068
Nonlinear1   1.159933335
Nonlinear2   0.676803555
Nonlinear3   0.309947442