Bagaimana saya bisa menafsirkan matriks kebingungan Sklearn

24

Saya menggunakan matriks kebingungan untuk memeriksa kinerja classifier saya.

Saya menggunakan Scikit-Learn, saya agak bingung. Bagaimana saya bisa menafsirkan hasil dari

from sklearn.metrics import confusion_matrix
>>> y_true = [2, 0, 2, 2, 0, 1]
>>> y_pred = [0, 0, 2, 2, 0, 2]
>>> confusion_matrix(y_true, y_pred)
array([[2, 0, 0],
       [0, 0, 1],
       [1, 0, 2]])

Bagaimana saya bisa mengambil keputusan apakah nilai prediksi ini baik atau tidak.

pengguna3378649
sumber
1
Awalnya lupakan sklearn, itu herring merah. Sumber kesalahpahaman Anda tampaknya lebih mendasar. Lihat di sini: en.wikipedia.org/wiki/Confusion_matrix . Fokus pada naratif contoh 3 * 3 di halaman wikipedia. Itu kemungkinan besar akan mengatasi apa pun kebingungan Anda.
Zhubarb

Jawaban:

47

Matriks kebingungan adalah cara mentabulasi jumlah kesalahan klasifikasi, yaitu, jumlah kelas prediksi yang berakhir di nampan klasifikasi yang salah berdasarkan kelas yang benar.

Sementara sklearn.metrics.confusion_matrix menyediakan matriks numerik, saya merasa lebih berguna untuk menghasilkan 'laporan' menggunakan yang berikut:

import pandas as pd
y_true = pd.Series([2, 0, 2, 2, 0, 1, 1, 2, 2, 0, 1, 2])
y_pred = pd.Series([0, 0, 2, 1, 0, 2, 1, 0, 2, 0, 2, 2])

pd.crosstab(y_true, y_pred, rownames=['True'], colnames=['Predicted'], margins=True)

yang mengakibatkan:

Predicted  0  1  2  All
True                   
0          3  0  0    3
1          0  1  2    3
2          2  1  3    6
All        5  2  5   12

Ini memungkinkan kita untuk melihat bahwa:

  1. Elemen diagonal menunjukkan jumlah klasifikasi yang benar untuk masing-masing kelas: 3, 1 dan 3 untuk kelas 0, 1 dan 2.
  2. Elemen off-diagonal memberikan kesalahan klasifikasi: misalnya, 2 dari kelas 2 salah diklasifikasikan sebagai 0, tidak ada kelas 0 yang salah diklasifikasikan sebagai 2, dll.
  3. Jumlah total klasifikasi untuk setiap kelas di kedua y_truedan y_pred, dari subtotal "Semua"

Metode ini juga berfungsi untuk label teks, dan untuk sejumlah besar sampel dalam dataset dapat diperluas untuk memberikan laporan persentase.

import numpy as np
import pandas as pd

# create some data
lookup = {0: 'biscuit', 1:'candy', 2:'chocolate', 3:'praline', 4:'cake', 5:'shortbread'}
y_true = pd.Series([lookup[_] for _ in np.random.random_integers(0, 5, size=100)])
y_pred = pd.Series([lookup[_] for _ in np.random.random_integers(0, 5, size=100)])

pd.crosstab(y_true, y_pred, rownames=['True'], colnames=['Predicted']).apply(lambda r: 100.0 * r/r.sum())

Outputnya adalah:

Predicted     biscuit  cake      candy  chocolate    praline  shortbread
True                                                                    
biscuit     23.529412    10  23.076923  13.333333  15.384615    9.090909
cake        17.647059    20   0.000000  26.666667  15.384615   18.181818
candy       11.764706    20  23.076923  13.333333  23.076923   31.818182
chocolate   11.764706     5  15.384615   6.666667  15.384615   13.636364
praline     17.647059    10  30.769231  20.000000   0.000000   13.636364
shortbread  17.647059    35   7.692308  20.000000  30.769231   13.636364

di mana angka sekarang mewakili persentase (bukan jumlah kasus) dari hasil yang diklasifikasikan.

Meskipun perlu dicatat, bahwa sklearn.metrics.confusion_matrixoutput dapat langsung divisualisasikan menggunakan:

import matplotlib.pyplot as plt
conf = sklearn.metrics.confusion_matrix(y_true, y_pred)
plt.imshow(conf, cmap='binary', interpolation='None')
plt.show()
achennu
sumber
4
Selamat datang di situs kami! Saya menghargai perhatian dan kualitas yang Anda berikan pada jawaban pertama Anda di sini.
whuber
1
Contoh pertama tidak lagi berfungsi, setidaknya pada panda-0.13.1. Saya baru saja mengupgrade ke panda-0.16.0, dan masih mendapatkan kesalahan yang sama:AssertionError: arrays and names must have the same length
chbrown
1
@chbrown: sepertinya ada sesuatu yang berubah dalam panda yang perlu menjadi array atau seri. Saya telah memperbarui kode contoh untuk digunakan y_pred = pd.Series(...). Ini seharusnya bekerja sekarang.
achennu
5

Pada y-axis confusion matrix memiliki nilai aktual, dan pada x-axis nilai diberikan oleh prediktor. Oleh karena itu, penghitungan diagonal adalah jumlah prediksi yang benar. Dan elemen-elemen diagonal adalah prediksi yang salah.

Dalam kasus Anda:

>>> confusion_matrix(y_true, y_pred)
    array([[2, 0, 0],  # two zeros were predicted as zeros
           [0, 0, 1],  # one 1 was predicted as 2
           [1, 0, 2]]) # two 2s were predicted as 2, and one 2 was 0
Akavall
sumber
Agak membingungkan (Anda mengatakan "# 1 1 diprediksi sebagai 2" - sedangkan diagonal adalah 0), saya memiliki matriks elemen 50K agak sulit untuk memproyeksikan semua nilai. Apakah ada metrik yang memberi saya hasil ini secara langsung? (Maksud saya jika saya mendapatkan matriks kebingungan yang baik atau tidak).
user3378649
1
Anda bisa melihat elemen pada diagonal, itu adalah prediksi yang benar, elemen off-diagonal adalah prediksi yang salah. Itu awal.
Akavall
Saya mendapat dua hasil berbeda. Dalam target, kami memiliki dua label '0' atau '1', Dapatkah Anda membantu memberikan petunjuk bagaimana menafsirkan hasil tersebut. - confusion_matrix: [[0 85723] [0 77]] - confusion_matrix: [[85648 75] [75 2]]
user3378649
1

Saya ingin menentukan secara grafis kebutuhan untuk memahami ini. Ini adalah matriks sederhana yang perlu dipahami dengan baik sebelum mencapai kesimpulan. Jadi, inilah versi jawaban di atas yang dapat dijelaskan dan disederhanakan.

        0  1  2   <- Predicted
     0 [2, 0, 0]  
TRUE 1 [0, 0, 1]  
     2 [1, 0, 2] 

# At 0,0: True value was 0, Predicted value was 0, - 2 times predicted
# At 1,1: True value was 1, Predicted value was 1, - 0 times predicted
# At 2,2: True value was 2, Predicted value was 2, - 2 times predicted
# At 1,2: True value was 1, Predicted value was 2, - 1 time predicted
# At 2,0: True value was 2, Predicted value was 0, - 1 time predicted...
...Like that
Pranzell
sumber
4
Bisakah Anda mengedit ini untuk mengatakan bagaimana menurut Anda melampaui jawaban yang sudah diberikan?
mdewey
1
Hei! Saya baru saja merujuk ke jawaban Akavall. Dia telah menyebutkan pemikiran yang terlibat. Saya baru saja menjelaskan jawabannya, yang cenderung benar, dengan cara yang lebih baik mungkin.
Pranzell
@Pranzell Bisakah Anda membagikan kode Anda untuk menggambar tabel berbasis teks yang begitu indah?
fu DL