glmnet和caret:训练模型的ROC、灵敏度和特异性

3

我希望使用GLMNET来拟合二项式逻辑回归模型。我可以直接使用caret或者glmnet包。让我们以数据(BinomialExample)为例,执行以下代码,我已经实现了两个方法:

#rm(list = ls(all.names = TRUE))

library(glmnet)    
library(caret)
data(BinomialExample)

y[y==0] = "low"
y[y==1] = "high"
y <- as.factor(y)

#split data in training & validation set

set.seed(1)
splitSample <- createDataPartition(y, p = 0.8, list = FALSE)
training_expression <- x[splitSample,]
training_phenotype <- y[splitSample]
validation_expression <- x[-splitSample,]
validation_phenotype <- y[-splitSample]

#####################
##GLMNET with CARET##
#####################
eGrid <- expand.grid(.alpha=seq(0.1,0.9, by=0.1),.lambda=seq(0,1,by=0.01))
Control <- trainControl(verboseIter=TRUE, classProbs=TRUE, summaryFunction=twoClassSummary, method="cv") 

set.seed(1)
netFit <- train(x = training_expression, y = training_phenotype,method = "glmnet", metric = "ROC", tuneGrid=eGrid,trControl = Control)
netFitPerf <- getTrainPerf(netFit) 
trainROC <- netFitPerf[,1]
trainSens <- netFitPerf[,2]
trainSpec <- netFitPerf[,3] 
trainAlpha <- netFit$bestTune[,1]
trainLambda <- netFit$bestTune[,2]
print(sprintf("ROC: %s Sens: %s Spec: %s Alpha: %s Lambda: %s", round(trainROC,2), round(trainSens,2), round(trainSpec,2), round(trainAlpha,2),round(trainLambda,2))) 

predict_validation <- predict(netFit, newdata = validation_expression)
confusionMatrix(predict_validation,validation_phenotype)

######################
#GLMNET without CARET#
######################
set.seed(1)
elasticnet <- cv.glmnet(training_expression, training_phenotype, family = "binomial", type.measure = "class", nfolds=10, alpha=0.5, nlambda = 100) 
plot(elasticnet)
predict_validation <- predict(elasticnet, newx = validation_expression, s = c(elasticnet$lambda.min), type = "class")
confusionMatrix(predict_validation,validation_phenotype)

你可以看到,如果我使用CARAT包,我可以轻松地打印模型的ROC、灵敏度和特异度。然而,如果我直接使用GLMNET而不使用CARET,我无法找到一种类似的方法来打印ROC、灵敏度和特异性 - 是否有一种类似的方法来获得这些指标?

谢谢你的帮助!


虽然这是可能的,但如果“caret”可以实现你的目标,为什么要这样做呢?这只是出于好奇吗? - cdeterman
在这种特定情况下,我可以使用caret,但过去我总是直接使用glmnet(因为有些情况下caret无用(例如拟合Cox回归模型时))。因此,我仍然很想知道如何在不使用caret的情况下计算所提到的指标。 - user86533
2个回答

4
您可以从glmnet工作流程产生的各种对象中获取所需的值。例如,如果您执行以下操作:
cm = confusionMatrix(predict_validation,validation_phenotype)

然后cm$byClass包括特异性和敏感性:

cm$byClass
     Sensitivity          Specificity       Pos Pred Value       Neg Pred Value           Prevalence 
       0.8181818            1.0000000            1.0000000            0.8000000            0.5789474 
  Detection Rate Detection Prevalence    Balanced Accuracy 
       0.4736842            0.4736842            0.9090909 

同样,您可以从elasticnet$lambda.min获取Lambda,并从gsub(".*alpha = ([0-9]\\.[0-9]*).*","\\1",deparse(elasticnet$glmnet.fit$call)[2])获取alpha(尽管可能有比那个庞大的代码更好的方法)。实际上,由于alpha值是函数的输入,因此您甚至不需要提取它。但是,如果您在交叉验证中使用alpha以及lambda,则需要使用循环来尝试多个alpha值,然后您需要一些方法来提取最佳模型的alpha值。如果您决定在交叉验证中包括alpha,请务必阅读cv.glmnetDetails部分。
对于ROC曲线的AUC,cv.glmnet将为您提供,但您需要使用type.measure="auc"而不是type.measure="class",这会改变如何选择最佳模型。此外,在这个特定的数据样本中,您需要使用较少的CV折叠,但是在您的真实数据中可能不是问题。例如:
elasticnet <- cv.glmnet(training_expression, training_phenotype, family = "binomial", 
                        type.measure = "auc", nfolds=5, alpha=0.5, nlambda = 100) 

然后,为了得到AUC:
elasticnet$cvm[which(elasticnet$lambda==elasticnet$lambda.min)] 

或者

max(elasticnet$cvm)

如果您想在不使用AUC来选择最佳模型的情况下计算AUC,则可能需要自己计算或使用现有的函数进行计算,例如来自pROC包的auc


0

您可以直接使用 assess.glmnet 函数轻松查看 AUC 和其他度量,如 MSE。


assess.glmnet 不提供所需的灵敏度等信息,这正是问题所询问的。 - StupidWolf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接