首页 文章

glmnet&caret:ROC,敏感度,训练模型的特异性

提问于
浏览
3

我想使用GLMNET来拟合二项Logistic回归模型 . 我可以直接使用插入符号或glmnet-package . 让我们以数据(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)

正如您所看到的,如果我使用插入符号包,我可以轻松打印模型的ROC,灵敏度和特异性 . 然而,如果我没有CARET直接使用glmnet,我无法找到类似的方法来打印ROC,Sens,Spec - 是否有类似的方法来获取这些指标?

谢谢你的帮助!

1 回答

  • 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 .

相关问题