如何从分类树概率中绘制 ROC 曲线

Posted

技术标签:

【中文标题】如何从分类树概率中绘制 ROC 曲线【英文标题】:How to plot a ROC curve from Classification Tree probabilities 【发布时间】:2015-11-24 09:43:43 【问题描述】:

我正在尝试绘制具有分类树概率的 ROC 曲线。但是,当我绘制曲线时,它不存在。我正在尝试绘制 ROC 曲线,然后从曲线下的区域中找到 AUC 值。有谁知道如何解决这一问题?如果可以的话,谢谢。二元列 Risk 代表风险错误分类,我认为这是我的标签。我应该在代码中的不同点应用 ROC 曲线方程吗?

这是数据框:

   library(ROCR)

   data(Risk.table)

   pred = prediction(Risk.table$Predicted.prob, Risk.table2$Risk)
   perf = performance(pred, measure="tpr", x.measure="fpr")
   perf
   plot(perf)

   Predicted.prob Actual.prob   predicted actual Risk
  1       0.5384615   0.4615385        G8     V4    0
  2       0.1212121   0.8787879        V4     V4    1
  3       0.5384615   0.4615385        G8     G8    1
  4       0.9000000   0.1000000        G8     G8    1
  5       0.1212121   0.8787879        V4     V4    1
  6       0.1212121   0.8787879        V4     V4    1
  7       0.9000000   0.1000000        G8     G8    1
  8       0.5384615   0.4615385        G8     V4    0
  9       0.5384615   0.4615385        G8     V4    0
  10      0.1212121   0.8787879        V4     G8    0
  11      0.1212121   0.8787879        V4     V4    1
  12      0.9000000   0.1000000        G8     V4    0
  13      0.9000000   0.1000000        G8     V4    0
  14      0.1212121   0.8787879        G8     V4    1
  15      0.9000000   0.1000000        G8     G8    1
  16      0.5384615   0.4615385        G8     V4    0
  17      0.9000000   0.1000000        G8     V4    0
  18      0.1212121   0.8787879        V4     V4    1
  19      0.5384615   0.4615385        G8     V4    0
  20      0.1212121   0.8787879        V4     V4    1
  21      0.9000000   0.1000000        G8     G8    1
  22      0.5384615   0.4615385        G8     V4    0
  23      0.9000000   0.1000000        G8     V4    0
  24      0.1212121   0.8787879        V4     V4    1

这里是这段代码输出的ROC曲线,但是曲线不见了:

我又试了,这个ROC曲线是错的

我使用下面的代码构造了上面的数据框:

包含所有数据的初始数据帧称为 shuffle.cross.validation2

  #Split data 70:30 after shuffling the data frame

  index<-1:nrow(LDA.scores1)
  trainindex.LDA3=sample(index, trunc(length(index)*0.70),replace=FALSE)      

  LDA.70.trainset3<-shuffle.cross.validation2[trainindex.LDA3,]

  LDA.30.testset3<-shuffle.cross.validation2[-trainindex.LDA3,]

使用包 rpart() 运行分类树

 tree.split3<-rpart(Family~., data=LDA.70.trainset3, method="class")
 tree.split3
 summary(tree.split3)
 print(tree.split3)
 plot(tree.split3)
 text(tree.split3,use.n=T,digits=0)
 printcp(tree.split3)
 tree.split3

预测预测数据和实际数据

 res3=predict(tree.split3,newdata=LDA.30.testset3)
 res4=as.data.frame(res3)

使用 NA(实际和预测分类率)创建两列

 res4$predicted<-NA
 res4$actual<-NA


 for (i in 1:length(res4$G8))

 if(res4$R2[i]>res4$V4[i]) 
 res4$predicted[i]<-"G8"
 

 else 
 res4$predicted[i]<-"V4"
 

  print(i)
 

 res4

 res4$actual<-LDA.30.testset3$Family
 res4
 Risk.table$Risk<-NA
 Risk.table

创建二元预测列

  for (i in 1:length(Risk.table$Risk))

  if(Risk.table$predicted[i]==res4$actual[i]) 
  Risk.table$Risk[i]<-1
  

  else 
  Risk.table$Risk[i]<-0
  

  print(i)
  

以上V4和G8两个族的预测概率和实际概率的创建

    #Confusion Matrix

    cm=table(res4$actual, res4$predicted)

    names(dimnames(cm))=c("actual", "predicted")

朴素贝叶斯

  index<-1:nrow(significant.lda.Wilks2)
  trainindex.LDA.help1=sample(index, trunc(length(index)*0.70), replace=FALSE)                                     
  sig.train=significant.lda.Wilks2[trainindex.LDA.help1,]
  sig.test=significant.lda.Wilks2[-trainindex.LDA.help1,]


    library(klaR)
    nbmodel<-NaiveBayes(Family~., data=sig.train)
    prediction<-predict(nbmodel, sig.test)
    NB<-as.data.frame(prediction)
    colnames(NB)<-c("Actual", "Predicted.prob", "acual.prob")

    NB$actual2 = NA
    NB$actual2[NB$Actual=="G8"] = 1
    NB$actual2[NB$Actual=="V4"] = 0
    NB2<-as.data.frame(NB)

    plot(fit.perf, col="red"); #Naive Bayes
    plot(perf, col="blue", add=T); #Classification Tree
    abline(0,1,col="green")

使用 caret 包的原始朴素贝叶斯代码

     library(caret)
     library(e1071)

  train_control<-trainControl(method="repeatedcv", number=10, repeats=3)
  model<-train(Matriline~., data=LDA.scores, trControl=train_control,    method="nb")
  predictions <- predict(model, LDA.scores[,2:13])
  confusionMatrix(predictions,LDA.scores$Family)

结果

               Confusion Matrix and Statistics

                        Reference
                Prediction V4 G8
                        V4 25  2
                        G8  5 48

                  Accuracy : 0.9125         
                    95% CI : (0.828, 0.9641)
       No Information Rate : 0.625          
       P-Value [Acc > NIR] : 4.918e-09      

                    Kappa : 0.8095         
   Mcnemar's Test P-Value : 0.4497         

              Sensitivity : 0.8333         
              Specificity : 0.9600         
           Pos Pred Value : 0.9259         
           Neg Pred Value : 0.9057         
               Prevalence : 0.3750         
           Detection Rate : 0.3125         
     Detection Prevalence : 0.3375         
        Balanced Accuracy : 0.8967         

         'Positive' Class : V4         

【问题讨论】:

prediction 函数中,您的预测和标签来自两个不同的数据帧,这可能不是您想要的。您的绘图 一条 ROC 曲线,但对于预测能力完全为零的模型。当我使用您发布的数据中的Predicted.probRisk 运行您的代码时,我得到一条 ROC 曲线,但它低于 45 度线,因为预测和标签是反相关的。 另外,您的代码包含data(Risk.table),但据我所知,没有包含名为Risk.table 的数据框的包。 我应该在代码中的不同点应用更高的 ROC 曲线方程吗?感谢您的评论 嗨,epic,对不起,Risk.table 只是上述data.frame 的名称。我通过运行我提供的额外代码实现了这个数据框中的概率。我对分类做了一个预测,因为我正在制作一个混淆矩阵,因此是 Predicted Prob 和 Acutual Prob 列。这些概率来自我的初始数据框中的类别相关列,其中包含所有值 (shuffle.cross.validated2),其中包含两个类 V4 和 G8。 如果您在问题中包含数据样本,我们可以运行(并修复或改进)您的代码,这将更容易为您提供帮助。现在,您可以做的一件事是摆脱 for 循环并利用 R 的矢量化。例如:Risk.table$Risk = ifelse(Risk.table$predicted==res4$actual, 1,0). 【参考方案1】:

我有很多事情要指出:

1) 我认为您的代码必须在 rpart 命令中为 Family ~ .

2) 在您的初始表中,我可以在您的预测列中看到一个值 W3。这是否意味着您没有二元因变量? ROC 曲线适用于二进制数据,请检查一下。

3) 您在初始表中的预测概率和实际概率总和为 1。这合理吗?我认为它们代表了其他东西,因此您可能会考虑更改名称,以防它们将来让您感到困惑。

4) 我认为您对 ROC 的工作原理以及它需要哪些输入感到困惑。您的Risk 列使用 1 表示正确预测,使用 0 表示错误预测。但是,ROC 曲线需要 1 代表一个类别,而 0 代表另一个类别。简单来说,命令是prediction(predictions, labels),其中predictions 是您的预测概率,labels 是您的因变量的真实类别/级别。 检查以下代码:

dt = read.table(text="
Id Predicted.prob Actual.prob   predicted actual Risk
1       0.5384615   0.4615385        G8     V4    0
2       0.1212121   0.8787879        V4     V4    1
3       0.5384615   0.4615385        G8     G8    1
4       0.9000000   0.1000000        G8     G8    1
5       0.1212121   0.8787879        V4     V4    1
6       0.1212121   0.8787879        V4     V4    1
7       0.9000000   0.1000000        G8     G8    1
8       0.5384615   0.4615385        G8     V4    0
9       0.5384615   0.4615385        G8     V4    0
10      0.1212121   0.8787879        V4     G8    0
11      0.1212121   0.8787879        V4     V4    1
12      0.9000000   0.1000000        G8     V4    0
13      0.9000000   0.1000000        G8     V4    0
14      0.1212121   0.8787879        W3     V4    1
15      0.9000000   0.1000000        G8     G8    1
16      0.5384615   0.4615385        G8     V4    0
17      0.9000000   0.1000000        G8     V4    0
18      0.1212121   0.8787879        V4     V4    1
19      0.5384615   0.4615385        G8     V4    0
20      0.1212121   0.8787879        V4     V4    1
21      0.9000000   0.1000000        G8     G8    1
22      0.5384615   0.4615385        G8     V4    0
23      0.9000000   0.1000000        G8     V4    0
24      0.1212121   0.8787879        V4     V4    1", header=T)

library(ROCR)

roc_pred <- prediction(dt$Predicted.prob, dt$Risk)
perf <- performance(roc_pred, "tpr", "fpr")
plot(perf, col="red")
abline(0,1,col="grey")

ROC曲线是:

当您创建一个新列 actual2 时,您有 1 而不是 G8 和 0 而不是 V4:

dt$actual2 = NA
dt$actual2[dt$actual=="G8"] = 1
dt$actual2[dt$actual=="V4"] = 0

roc_pred <- prediction(dt$Predicted.prob, dt$actual2)
perf <- performance(roc_pred, "tpr", "fpr")
plot(perf, col="red")
abline(0,1,col="grey")

5) 正如上面提到的@eipi10,您应该尝试摆脱代码中的 for 循环。

【讨论】:

谢谢安东尼奥斯克。这太棒了。我已经玩了很多年了,只是没有得到任何地方。你是一个传奇。再次感谢你:) 很高兴我能帮上忙。另一个有用的命令是 performance(roc_pred,"auc")@y.values ,它会为您提供曲线下的区域,以防您需要比较模型。 这正是我想要做的。我使用了两种监督机器学习技术,我想比较朴素贝叶斯 (NB) 和这个分类树之间的差异。您对如何在同一条 ROC 曲线上绘制 NB 和分类树的结果有什么想法,然后计算 AUC 以进行比较: 使用相同的脚本,您需要为一个模型创建roc_pred1perf1,为另一个模型创建roc_pred2perf2,然后执行plot(perf1, col="red"); plot(perf2, col="blue", add=T); abline(0,1,col="grey")。对于 auc 曲线,只需使用 performance(roc_pred1,"auc")@y.valuesperformance(roc_pred2,"auc")@y.values AntoniosK.看看我上面做了什么。太感谢了。你是一个救生员 :) 很高兴你对这个问题发表了评论,也许这会帮助其他人。保重

以上是关于如何从分类树概率中绘制 ROC 曲线的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 r 中的 ROCR 包绘制 ROC 曲线,*只有分类列联表*

如何解释决策树的 ROC AUC 曲线的阈值?

如何从具有 2 个输出神经元的 softmax 二元分类器绘制 ROC 曲线?

R语言构建logistic回归模型并评估模型:模型预测结果抽样可视化模型分类预测的概率分布情况使用WVPlots包绘制ROC曲线并计算AUC值

多分类问题的ROC曲线绘制

二元分类器过于自信,无法用 sklearn 绘制 ROC 曲线?