Caret glmnet vs cv.glmnet


14

Здається, існує велика плутанина в порівнянні використання glmnetв рамках caretпошуку оптимальної лямбда та використання cv.glmnetтого ж завдання.

Поставлено багато питань, наприклад:

Класифікаційна модель train.glmnet vs. cv.glmnet?

Який правильний спосіб використання glmnet з каретою?

Перехресне підтвердження `glmnet` за допомогою` caret`

але відповіді не надано, що може бути пов'язано з відтворюваністю питання. Після першого запитання я навожу досить подібний приклад, але у мене є той самий запитання: Чому оцінені лямбдаї такі різні?

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,05 за допомогою cv.glmnet()

  • 0,001 за допомогою train()

Я знаю, що використовувати standardize=FALSEв cv.glmnet()доцільно, але я дуже хочу порівняти обидва методи, використовуючи однакові передумови. Як основне пояснення, я вважаю, що підхід до вибірки для кожної складки може бути проблемою, але я використовую однакові насіння, і результати є зовсім іншими.

Тож я дійсно застряг у тому, чому два підходи настільки різні, хоча вони повинні бути зовсім схожими? - Я сподіваюся, що громада має деяке уявлення, у чому тут питання

Відповіді:


17

Я бачу тут два випуски. По-перше, ваш навчальний набір занадто малий щодо вашого тестового набору. Як правило, ми б хотіли, щоб навчальний набір був, принаймні, порівнянний за розміром з тестовим набором. Інша примітка полягає в тому, що для перехресної перевірки ви взагалі не використовуєте тестовий набір, оскільки алгоритм в основному створює набори тестування для вас за допомогою "навчального набору". Тож вам буде краще використовувати більше даних у якості початкового навчального набору.

По-друге, 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, я не враховував а) розмір зразка та б) складки.
Jogi

Дякую за пост! Отже, якщо я правильно це зробив, зазвичай один розбиває набір даних на великий навчальний набір і менший тестовий набір (= пробіг) та виконує резюме k-кратного на навчальному наборі. Нарешті, одна перевірка на тестовому наборі, використовуючи результати резюме, правильно?
Jogi

@Jogi Це був би спосіб зробити це. Ви також можете просто використовувати весь набір даних для CV, якщо вам не потрібна подальша перевірка, оскільки CV вже вибирає найкращі параметри на основі середньої продуктивності моделі для кожної ітерації тестових наборів.
StAtS
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.