How to make sklearn.metrics.confusion_matrix() to always return TP, TN, FP, FN?

Scoodood picture Scoodood · Sep 15, 2017 · Viewed 7k times · Source

I am using sklearn.metrics.confusion_matrix(y_actual, y_predict) to extract tn, fp, fn, tp and most of the time it works perfectly.

from sklearn.metrics import confusion_matrix

y_actual, y_predict = [1,1,1,1], [0,0,0,0]
tn, fp, fn, tp = confusion_matrix(y_actual, y_predict).ravel()
>>> [0 0 4 0]   # ok

y_actual, y_predict = [1,1,1,1],[0,1,0,1]
tn, fp, fn, tp = confusion_matrix(y_actual, y_predict).ravel()
>>> [0 0 2 2]   # ok

However, in some cases the confusion_matrix() doesn't always return those info and I would get ValueError as shown below.

from sklearn.metrics import confusion_matrix

y_actual, y_predict = [0,0,0,0],[0,0,0,0]
tn, fp, fn, tp = confusion_matrix(y_actual, y_predict).ravel()
>>> [4]    # ValueError: not enough values to unpack (expected 4, got 1)

y_actual, y_predict = [1,1,1,1],[1,1,1,1]
tn, fp, fn, tp = confusion_matrix(y_actual, y_predict).ravel()
>>> [4]    # ValueError: not enough values to unpack (expected 4, got 1)

My temporary solution is to write my own function to extract those info. Is there any way I can force the confusion_matrix() to always return the tn, fp, fn, tp output?

Thanks

Answer

kdd picture kdd · Sep 15, 2017

This issue has to do with the number of unique labels that are included in your input matrices. In your second block of examples, it is (correctly) building a confusion matrix with just one class, either 0 or 1, respectively.

To force it to output both classes even when one of them is not predicted, use the label attribute.

y_actual, y_predict = [0,0,0,0],[0,0,0,0]
tn, fp, fn, tp = confusion_matrix(y_actual, y_predict, labels=[0,1]).ravel()
>> array([[4, 0],
          [0, 0]])