Карет глмнет против cv.glmnet

14

Кажется, существует большая путаница при сравнении использования glmnetвнутри caretдля поиска оптимальной лямбды и использования cv.glmnetдля выполнения той же задачи.

Было задано много вопросов, например:

Модель классификации train.glmnet против 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.055 с помощью cv.glmnet()

  • 0,001 с помощью train()

Я знаю, что использование standardize=FALSEв cv.glmnet()не рекомендуется, но я действительно хочу сравнить оба метода, используя одни и те же предпосылки. В качестве основного объяснения, я думаю, что подход выборки для каждого сгиба может быть проблемой - но я использую одни и те же семена, и результаты совершенно разные.

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

Jogi
источник

Ответы:

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
STATs
источник
Большое спасибо за ваш ответ - это имеет смысл для меня. Поскольку я новичок в CV, я не учел а) размер образца и б) сгибы.
Йоги
Спасибо за пост! Так что, если я правильно понял, обычно один разбивает набор данных на большой тренировочный набор и меньший набор тестов (= задержка) и выполняет k-кратное резюме на тренировочном наборе. Наконец один проверяет на тестовом наборе, используя результаты резюме правильно?
Йоги
@Jogi Это был бы способ сделать это. Вы также можете просто использовать весь набор данных для CV, если вам не требуется дополнительная проверка, так как CV уже выбирает лучшие параметры на основе средней производительности модели на каждой итерации наборов тестирования.
СТАТИ