5

I have a dataset with 6 classes and I would like to plot a ROC curve for a multiclass classification. The first answer in this thread given by Achim Zeileis is a very good one.

ROC curve in R using rpart package?

But this works only for a binomial classification. And the error i get is Error in prediction, Number of classes is not equal to 2. Any one who has done this for a multi-class classification?

Here is a simple example of what I am trying to do. data <- read.csv("colors.csv")

let's say data$cType has 6 values (or levels) as (red, green, blue, yellow, black and white)

Is there anyway to plot a ROC curve for these 6 classes? Any working example for a class of more than 2 would be appreciated.

Community
  • 1
  • 1
Mahsolid
  • 433
  • 4
  • 12
  • 28
  • @achim-zeileis, any tips dear? – Mahsolid Apr 14 '16 at 18:25
  • What do you expect to show in ROC curves for multiclass classifications? ROC curves are intended to show binary results; more precisely two rates: true positive vs. false positive. You can establish each such curve for your six cases, but I don't see how a single ROC curve for a multiclass classification could even be defined. – RHertel Apr 14 '16 at 18:29
  • I want to do all the performance measurements as we do for binary. I have read that it is possible to do it using an R package called `pROC` but i can't find a working example. – Mahsolid Apr 14 '16 at 18:37
  • In my opinion the only way this could work would be to convert the problem into several binary ones, by defining six different "one vs. the rest" cases and evaluating the corresponding ROC curves. – RHertel Apr 14 '16 at 18:40
  • I have edited my question with a simple example now. Could you give me a simple working example dear? – Mahsolid Apr 14 '16 at 18:49
  • see http://stats.stackexchange.com/questions/2151/how-to-plot-roc-curves-in-multiclass-classification – fishtank Apr 14 '16 at 19:07
  • Also see related: http://stackoverflow.com/questions/20518376/how-to-deal-with-multiple-class-roc-analysis-in-r-proc-package – fishtank Apr 14 '16 at 19:09
  • ROC curves are defined on binary classification systems. By definition you will need to extend it on multiclass classification, so you won't have a ROC curve any longer. – Calimo Apr 14 '16 at 20:49

2 Answers2

2

I know this is an old question, but the fact that the only answer is written using Python bothers me a lot, given that the question specifically asks for an R solution.

As you can see from the code below, I am using pROC::multiclass.roc() function. The only requirement to make it work is that the names of the columns of the predictions matrix match the true classes (real_values).

The first example generates random predictions. The second one generates a better prediction. The third one generates the perfect prediction (i.e., always assigning the highest probability to the true class.)

library(pROC)
set.seed(42)
head(real_values)
real_values <- matrix( c("class1", "class2", "class3"), nc=1 )

# [,1]    
# [1,] "class1"
# [2,] "class2"
# [3,] "class3"

# Random predictions
random_preds <- matrix(rbeta(3*3,2,2), nc=3)
random_preds <- sweep(random_preds, 1, rowSums(a1), FUN="/")
colnames(random_preds) <- c("class1", "class2", "class3")


head(random_preds)

#       class1    class2    class3
# [1,] 0.3437916 0.6129104 0.4733117
# [2,] 0.6016169 0.4700832 0.9364681
# [3,] 0.6741742 0.8677781 0.4823129

multiclass.roc(real_values, random_preds)
#Multi-class area under the curve: 0.1667



better_preds <- matrix(c(0.75,0.15,0.5,
                         0.15,0.5,0.75,
                         0.15,0.75,0.5), nc=3)
colnames(better_preds) <- c("class1", "class2", "class3")

head(better_preds)

#       class1 class2 class3
# [1,]   0.75   0.15   0.15
# [2,]   0.15   0.50   0.75
# [3,]   0.50   0.75   0.50

multiclass.roc(real_values, better_preds)
#Multi-class area under the curve: 0.6667


perfect_preds <- matrix(c(0.75,0.15,0.5,
                          0.15,0.75,0.5,
                          0.15,0.5,0.75), nc=3)
colnames(perfect_preds) <- c("class1", "class2", "class3")
head(perfect_preds)

multiclass.roc(real_values, perfect_preds)
#Multi-class area under the curve: 1
0

Answering an old question while having the same requirement - I've found the scikit documentation explains a few approaches well.

http://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html

The approaches mentioned include:

  • "binarizing" i.e. converting the problem to binary classification, using either macro-averaging or micro-averaging
  • Draw multiple ROC curves, one per label
  • One vs. All

Copying example from the above link, which illustrates one vs. all and micro averaging using their libs:

print(__doc__)

import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle

from sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from scipy import interp

# Import some data to play with
iris = datasets.load_iris()
X = iris.data
y = iris.target

# Binarize the output
y = label_binarize(y, classes=[0, 1, 2])
n_classes = y.shape[1]

# Add noisy features to make the problem harder
random_state = np.random.RandomState(0)
n_samples, n_features = X.shape
X = np.c_[X, random_state.randn(n_samples, 200 * n_features)]

# shuffle and split training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.5,
                                                    random_state=0)

# Learn to predict each class against the other
classifier = OneVsRestClassifier(svm.SVC(kernel='linear', probability=True,
                                 random_state=random_state))
y_score = classifier.fit(X_train, y_train).decision_function(X_test)

# Compute ROC curve and ROC area for each class
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(n_classes):
    fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])
    roc_auc[i] = auc(fpr[i], tpr[i])

# Compute micro-average ROC curve and ROC area
fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_score.ravel())
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])

I'm actually looking for a Javascript solution (using https://github.com/mljs/performance) so I haven't implemented it with the above library, but it's been the most illuminating example I found so far.

scipilot
  • 6,681
  • 1
  • 46
  • 65