r-使用插入符号、glmnet和(嵌套的)交叉验证构建嵌套的逻辑回归模型



我的问题

我想建立一个逻辑回归模型,在预测二元变量时具有高AUC。

我想使用以下方法(如果可行(:

  1. 使用弹性网络模型(glmnet(来减少预测因子并找到最佳超参数(α和λ(

  2. 将该模型的输出(简单的线性组合(与逻辑回归模型(=finalmodel(中的额外预测器(超级医生superdoc的意见(相结合,类似于中第26页所述

Afshar p、Mohammadi A、Plataniotis KN、Oikonomu A、Benali H手工制作的基于深度学习的癌症放射组学:挑战和机会。IEEE信号处理杂志2019;36:132-60。此处提供

示例数据

作为示例数据,我有一个具有许多数字预测因子和二进制(pos/neg(结果(diabetes(的数据集。

# library
library(tidyverse)
library(caret)
library(glmnet)
library(mlbench)
# get example data
data(PimaIndiansDiabetes, package="mlbench")
data <- PimaIndiansDiabetes
# add the super doctors opinion to the data
set.seed(2323)
data %>% 
rowwise() %>% 
mutate(superdoc=case_when(diabetes=="pos" ~ as.numeric(sample(0:2,1)), TRUE~ 0)) -> data
# separate the data in a training set and test set
train.data <- data[1:550,]
test.data <- data[551:768,]

由reprex包于2021-03-14创建(v1.0.0(

我已经尝试过的

# train the model (without the superdoc's opinion)
set.seed(2323)
model <- train(
diabetes ~., data = train.data %>% select(-superdoc), method = "glmnet",
trControl = trainControl("cv",
number = 10,
classProbs = TRUE,
savePredictions = TRUE,
summaryFunction = twoClassSummary),
tuneLength = 10,
metric="ROC" #ROC metric is in twoClassSummary
)

# extract the coefficients for the best alpha and lambda  
coef(model$finalModel, model$finalModel$lambdaOpt) -> coeffs
tidy(coeffs) %>% tibble() -> coeffs
coef.interc = coeffs %>% filter(row=="(Intercept)") %>% pull(value)
coef.pregnant = coeffs %>% filter(row=="pregnant") %>% pull(value)
coef.glucose = coeffs %>% filter(row=="glucose") %>% pull(value)
coef.pressure = coeffs %>% filter(row=="pressure") %>% pull(value)
coef.mass = coeffs %>% filter(row=="mass") %>% pull(value)
coef.pedigree = coeffs %>% filter(row=="pedigree") %>% pull(value)
coef.age = coeffs %>% filter(row=="age") %>% pull(value)

# combine the model with the superdoc's opinion in a logistic regression model
finalmodel = glm(diabetes ~ superdoc + I(coef.interc + coef.pregnant*pregnant + coef.glucose*glucose + coef.pressure*pressure + coef.mass*mass + coef.pedigree*pedigree + coef.age*age),family=binomial, data=train.data)

# make predictions on the test data
predict(finalmodel,test.data, type="response") -> predictions

# check the AUC of the model in the test data
roc(test.data$diabetes,predictions, ci=TRUE) 
#> Setting levels: control = neg, case = pos
#> Setting direction: controls < cases
#> 
#> Call:
#> roc.default(response = test.data$diabetes, predictor = predictions,     ci = TRUE)
#> 
#> Data: predictions in 145 controls (test.data$diabetes neg) < 73 cases (test.data$diabetes pos).
#> Area under the curve: 0.9345
#> 95% CI: 0.8969-0.9721 (DeLong)

由reprex包于2021-03-14创建(v1.0.0(

我不太确定的地方

我认为为了找到最准确的模型并避免过度拟合,我必须使用嵌套的交叉验证(正如我在这里学到的(。但是,我不知道该怎么做。现在,每次我使用另一个set.seed时,都会选择不同的预测器,并得到不同的AUCs。这可以通过正确使用嵌套交叉验证来解决吗?

更新1

我刚刚了解到嵌套CV并不能帮助你获得最准确的模型。问题是,在上面的第二个代码样本中,我得到了具有不同set.seet的可变系数。实际上,我遇到了与这里描述的相同的问题:在插入中提取glmnet模型的最佳调谐参数的系数

一个公布的解决方案是使用重复CV混合这种变化。不幸的是,我没能参加这次跑步。

更新2

使用"repeatedcv"解决了我的问题。使用重复的cv而不是嵌套的cv就成功了!

model <- train(
diabetes ~., data = train.data %>% select(-superdoc), method = "glmnet",
trControl = trainControl("repeatedcv",
number = 10,
repeats=10,
classProbs = TRUE,
savePredictions = TRUE,
summaryFunction = twoClassSummary),
tuneLength = 10,
metric="ROC" #ROC metric is in twoClassSummary
)

感谢@missuse,我可以解决我的问题:

交叉验证无助于获得最准确的模型。这个(我的(误解在博客文章中得到了很好的讨论:;交叉验证-训练/预测";误解

小数据集中glmnet的预测器系数随种子变化的问题可以通过重复交叉验证(即caret::trainControl中的"repeatedcv",如本文评论中所述(来解决

堆叠学习器(在我的例子中是堆叠的glmnetglm(通常使用较低级别学习器的折叠外预测来构建。这可以使用mlr3包来完成,如本文所述:调整堆叠学习器。由于这不是最初的问题,我在这里提出了一个新问题。

最新更新