캐럿 glmnet vs cv.glmnet


14

glmnetwithin caret을 사용하여 최적의 람다를 검색 cv.glmnet하고 동일한 작업을 수행하는 것을 비교하는 데 많은 혼란이있는 것 같습니다 .

다음과 같은 많은 질문이 제기되었습니다.

분류 모델 train.glmnet 대 cv.glmnet?

캐럿과 함께 glmnet을 사용하는 올바른 방법은 무엇입니까?

`caret`를 사용한 교차 유효성 검사`glmnet`

그러나 질문의 ​​재현 가능성으로 인한 답변이 없습니다. 첫 번째 질문에 이어 비슷한 예를 들지만 같은 질문이 있습니다. 추정 된 람다는 왜 다른가?

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)

요약하면 최적의 람다는 다음과 같이 제공됩니다.

  • 를 사용하여 0.055 cv.glmnet()

  • 사용하여 0.001 train()

standardize=FALSEin 을 사용 하는 cv.glmnet()것이 바람직하지 않다는 것을 알고 있지만 동일한 전제 조건을 사용하여 두 방법을 비교하고 싶습니다. 주요 설명으로, 각 폴드에 대한 샘플링 접근법이 문제가 될 수 있다고 생각합니다. 그러나 동일한 시드를 사용하고 결과는 상당히 다릅니다.

그래서 나는 두 접근법이 왜 그렇게 다른지에 여전히 붙어 있지만 그것들은 상당히 유사해야합니까? -커뮤니티에 문제가 무엇인지 알기를 바랍니다.

답변:


17

여기에 두 가지 문제가 있습니다. 먼저 훈련 세트가 테스트 세트에 비해 너무 작습니다. 일반적으로 테스트 세트와 크기가 비슷한 훈련 세트를 원할 것입니다. 또 다른 참고 사항은 알고리즘이 기본적으로 "트레이닝 세트"를 사용하여 테스트 세트를 생성하기 때문에 교차 검증의 경우 테스트 세트를 전혀 사용하지 않는다는 것입니다. 따라서 초기 교육 세트로 더 많은 데이터를 사용하는 것이 좋습니다.

둘째, CV를 신뢰할 수 없을 정도로 3 배가 너무 작습니다. 일반적으로 5 ~ 10 폴드 (권장 nfolds = 5을 위해 cv.glmnet및 number=5위해 caret). 이러한 변경으로 두 방법과 거의 동일한 추정치에서 동일한 람다 값을 얻었습니다.

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

귀하의 답변에 감사드립니다-그것은 나에게 완벽하게 이해됩니다. 나는 CV의 초보자이기 때문에 a) 샘플의 크기와 b) 접기를 설명하지 않았습니다.
— Jogi

게시물 주셔서 감사합니다! 내가 올바르게 이해하면 일반적으로 데이터 세트를 큰 훈련 세트와 작은 시험 세트 (= 홀드 아웃)로 나누고 훈련 세트에서 k- 폴드 CV를 수행합니다. 마지막으로 CV의 결과를 사용하여 테스트 세트에서 유효성을 검사합니까?
— Jogi

@Jogi 그렇게하는 방법이 될 것입니다. CV는 이미 테스트 세트의 각 반복에서 모델의 평균 성능을 기반으로 최상의 매개 변수를 선택하므로 추가 검증이 필요하지 않은 경우 CV에 전체 데이터 세트를 사용할 수도 있습니다.
— StAtS
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.