Как построить кривую ROC из вероятностей дерева классификации

Я пытаюсь построить кривую ROC с вероятностями деревьев классификации. Однако, когда я строю кривую, ее нет. Я пытаюсь построить кривую ROC, а затем найти значение AUC из области под кривой. Кто-нибудь знает, как это исправить? Спасибо, если сможешь. Бинарный столбец «Риск» означает неправильную классификацию рисков, что, как я полагаю, является моим ярлыком. Следует ли применять уравнение кривой 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")

введите здесь описание изображения

Исходный наивный байесовский код с использованием пакета каретки

     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         

person Alice Hobbs    schedule 30.08.2015    source источник
comment
В функции prediction ваши прогнозы и метки взяты из двух разных фреймов данных, что, вероятно, не то, что вы планировали. Ваш график является кривой ROC, но для модели, которая имеет точно нулевую предсказательную силу. Когда я запускаю ваш код, используя Predicted.prob и Risk из опубликованных вами данных, я получаю кривую ROC, но она ниже линии 45 градусов, потому что прогнозы и метки антикоррелированы.   -  person eipi10    schedule 30.08.2015
comment
Кроме того, ваш код включает data(Risk.table), но, насколько я могу судить, нет пакета, который включает фрейм данных с именем Risk.table.   -  person eipi10    schedule 30.08.2015
comment
Следует ли применять уравнение кривой ROC выше в другой точке кода? Спасибо за ваш комментарий   -  person Alice Hobbs    schedule 30.08.2015
comment
Привет, эпик, извините, Risk.table - это просто название вышеуказанного data.frame. Я достиг вероятностей в этом фрейме данных, выполнив дополнительный код, который я предоставил. Я сделал прогноз по классификации, потому что я делал матрицу путаницы, отсюда столбцы «Прогнозируемая вероятность» и «Фактическая вероятность». Эти вероятности были получены из столбца, зависящего от категорий в моем исходном фрейме данных, содержащем все значения (shuffle.cross.validated2), содержащие два класса V4 и G8.   -  person Alice Hobbs    schedule 30.08.2015
comment
Вам будет намного легче помочь, если вы включите в свой вопрос образец данных, с помощью которого мы сможем запустить (и исправить или улучшить) ваш код. На данный момент вы можете избавиться от циклов for и вместо этого воспользоваться векторизацией R. Например: Risk.table$Risk = ifelse(Risk.table$predicted==res4$actual, 1,0).   -  person eipi10    schedule 30.08.2015
comment
Вторая кривая ROC, которую вы добавили в свой вопрос, - это правильная кривая ROC для опубликованных вами Risk.table данных. Обратите внимание, что корреляция Risk.table$Predicted.prob и Risk.table$Actual.prob равна -1. Когда ваши прогнозы не коррелируют с истинными значениями (что указывает на что-то не так с вашей моделью и / или вашим кодом), кривая ROC будет ниже диагонали.   -  person eipi10    schedule 30.08.2015


Ответы (1)


Я хочу отметить несколько вещей:

1) Я думаю, что ваш код должен быть Family ~ . внутри вашей команды rpart.

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 в своем коде.

person AntoniosK    schedule 01.09.2015
comment
Спасибо, Антониоск. Это великолепно. Я играл с этим целую вечность и ничего не добился. Вы легенда. Еще раз спасибо :) - person Alice Hobbs; 02.09.2015
comment
Рад, что помог. Еще одна полезная команда - performance(roc_pred,"auc")@y.values, которая даст вам площадь под кривой на случай, если вам нужно будет сравнить модели. - person AntoniosK; 02.09.2015
comment
Это именно то, что я пытаюсь сделать. Я использовал два метода контролируемого машинного обучения и хочу сравнить различия между наивным байесовским (NB) и этим классификационным деревом. У вас есть идеи, как построить график результатов для NB и дерева классификации на одной и той же кривой ROC, а затем рассчитать AUC для их сравнения: - person Alice Hobbs; 03.09.2015
comment
Используя тот же сценарий, вам нужно создать roc_pred1 и perf1 для одной модели и roc_pred2 и perf2 для другой, а затем сделать plot(perf1, col="red"); plot(perf2, col="blue", add=T); abline(0,1,col="grey"). Для кривой auc просто используйте performance(roc_pred1,"auc")@y.values и performance(roc_pred2,"auc")@y.values - person AntoniosK; 03.09.2015
comment
Антониоск. Посмотрите, что я сделал выше. Бесконечно благодарен. Вы спасаете жизнь :) Рад, что вы прокомментировали эту проблему, и, возможно, это поможет другим. Заботиться - person Alice Hobbs; 05.09.2015
comment
Выглядит хорошо и правильно как процесс, но я должен отметить, что синяя линия (дерево классификации) выглядит подозрительно хорошо. На самом деле это идеальная кривая ROC! Вы ожидали этого на основании ваших данных? Есть шанс, что что-то не так? - person AntoniosK; 05.09.2015
comment
Это то, о чем я думал. Первоначально я проводил тест NB с использованием пакета Caret, и оценка точности классификации составила 91% (код был вставлен выше). Я не знал, как преобразовать код и результаты матрицы путаницы в кривую ROC. Поэтому перешел на пакет клар. Код для деревьев классификации в пакете rpart и тест NB был запущен на данных с точно таким же форматом. Есть ли у вас предложения? - - person Alice Hobbs; 05.09.2015
comment
Я не думаю, что есть способ превратить матрицы путаницы в кривые ROC, потому что для построения кривой ROC вам нужен вектор предсказанных вероятностей (значения от 0 до 1, а не предсказанные классы 0/1) и фактические классы ( 0/1), как я уже упоминал выше. Вы должны иметь возможность использовать обе модели для прогнозирования вероятностей, таких как pred_prob_model1 и pred_prob_model2 (векторы прогнозируемых значений вероятности от 0 до 1, с использованием модели 1 и 2), и строить их против фактических классов (0/1), которые вы используете с помощью ROC. процесс. - person AntoniosK; 06.09.2015
comment
Я использовал ту же методологию для NB и дерева классификации, и определенно что-то не так с точностью классификации 1.0. Придется вернуться к чертежной доске. Могу ли я использовать ту же методологию для нанесения линейной дискриминантной оценки на кривую ROC? - person Alice Hobbs; 06.09.2015