キャレットglmnetとcv.glmnet


14

glmnetwithin caretを使用して最適なラムダを検索cv.glmnetし、同じタスクを実行するために使用することの比較には、多くの混乱があるようです。

次のような多くの質問が提起されました。

分類モデルtrain.glmnet対cv.glmnet?

キャレットでglmnetを使用する適切な方法は何ですか?

「キャレット」を使用して「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()はお勧めできませんが、同じ前提条件を使用して両方の方法を比較する必要があります。主な説明として、各フォールドのサンプリングアプローチが問題になる可能性があると思いますが、同じシードを使用しているため、結果はまったく異なります。

だから、私は2つのアプローチが非常に似ているはずなのに、なぜ2つのアプローチがそんなに違うのか本当に悩んでいますか?-私は、コミュニティがここで問題を理解していることを願っています

回答:


16

ここに2つの問題があります。まず、トレーニングセットがテストセットに比べて小さすぎます。通常、少なくともテストセットとサイズが同等のトレーニングセットが必要です。もう1つの注意点は、クロス検証では、テストセットをまったく使用しないことです。これは、アルゴリズムが基本的に「トレーニングセット」を使用してテストセットを作成するためです。したがって、最初のトレーニングセットとしてより多くのデータを使用する方が良いでしょう。

第二に、3倍はCVが信頼するには小さすぎる。通常、5〜10倍が推奨されます(nfolds = 5for cv.glmnetnumber=5for caret)。これらの変更により、2つの方法で同じラムダ値が得られ、ほぼ同じ推定値が得られました。

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.