Jak interpretować macierz nieporozumień Sklearn

24

Korzystam z macierzy zamieszania, aby sprawdzić wydajność mojego klasyfikatora.

Używam Scikit-Learn, jestem trochę zdezorientowany. Jak mogę zinterpretować wynik

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]])

Jak podjąć decyzję, czy te przewidywane wartości są dobre, czy nie.

użytkownik3378649
źródło
1
Początkowo zapomnij o sklearn, czyli czerwonym śledziu. Źródło twojego nieporozumienia wydaje się bardziej fundamentalne. Zajrzyj tutaj: en.wikipedia.org/wiki/Confusion_matrix . Skoncentruj się na narracji z przykładu 3 * 3 na stronie wikipedii. To najprawdopodobniej rozwiąże wszelkie wątpliwości.
Zhubarb,
Odpowiedni temat: stats.stackexchange.com/a/340079/121522
mkt - Przywróć Monikę

Odpowiedzi:

47

Macierz nieporozumień jest sposobem na zestawienie liczby błędnych klasyfikacji, tj. Liczby przewidywanych klas, które trafiły do ​​niewłaściwego koszyka klasyfikacyjnego w oparciu o prawdziwe klasy.

Chociaż sklearn.metrics.confusion_matrix zapewnia macierz numeryczną, bardziej użyteczne jest wygenerowanie „raportu” przy użyciu następujących elementów:

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)

Co skutkuje w:

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

To pozwala nam zobaczyć, że:

  1. Elementy ukośne pokazują liczbę poprawnych klasyfikacji dla każdej klasy: 3, 1 i 3 dla klas 0, 1 i 2.
  2. Elementy nie przekątne zapewniają błędne klasyfikacje: na przykład 2 z klasy 2 zostały błędnie zaklasyfikowane jako 0, żaden z klasy 0 nie został błędnie zaklasyfikowany jako 2 itd.
  3. Łączna liczba klasyfikacji dla każdej klasy w obu y_truei y_predz sum częściowych „Wszystkie”

Ta metoda działa również w przypadku etykiet tekstowych, a dla dużej liczby próbek w zestawie danych można rozszerzyć, aby dostarczać raporty procentowe.

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())

Dane wyjściowe to:

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

gdzie liczby reprezentują teraz procent (a nie liczbę przypadków) wyników, które zostały sklasyfikowane.

Należy pamiętać, że dane sklearn.metrics.confusion_matrixwyjściowe można bezpośrednio wizualizować za pomocą:

import matplotlib.pyplot as plt
conf = sklearn.metrics.confusion_matrix(y_true, y_pred)
plt.imshow(conf, cmap='binary', interpolation='None')
plt.show()
achennu
źródło
4
Witamy na naszej stronie! Doceniam staranność i jakość, jaką włożyłeś w swoją pierwszą odpowiedź tutaj.
whuber
1
Pierwszy przykład już nie działa, przynajmniej od pand-0.13.1. Właśnie uaktualniłem do pand-0.16.0 i nadal otrzymuję ten sam błąd:AssertionError: arrays and names must have the same length
chbrown
1
@chbrown: wydaje się, że coś zmieniło się w pandach, które muszą usiąść, aby być tablicą lub serią. Zaktualizowałem przykładowy kod do użycia y_pred = pd.Series(...). To powinno działać teraz.
achennu
5

Na macierzy zamieszania na osi y znajdują się wartości rzeczywiste, a na osi x wartości podane przez predyktor. Dlatego liczby na przekątnej są liczbą poprawnych prognoz. A elementy przekątnej są niepoprawnymi przewidywaniami.

W Twoim przypadku:

>>> 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
źródło
To trochę mylące (Powiedziałeś, że „# one 1 przewidywano jako 2” - podczas gdy w przekątnej jest 0), mam matrycę elementu 50K, trochę trudno jest wyświetlić wszystkie wartości. Czy są jakieś dane, które dają mi te wyniki bezpośrednio? (Mam na myśli, czy dostaję dobrą macierz dezorientacji, czy nie).
user3378649,
1
Możesz spojrzeć na elementy na przekątnej, to są twoje poprawne przewidywania, elementy nie przekątne są błędnymi przewidywaniami. To jest początek.
Akavall,
Mam dwa różne wyniki. W celu mamy dwie etykiety „0” lub „1”. Czy możesz pomóc podpowiedzieć, jak interpretować te wyniki. - confusion_matrix: [[0 85723] [0 77]] - confusion_matrix: [[85648 75] [75 2]]
user3378649
1

Chciałbym graficznie określić potrzebę zrozumienia tego. Jest to prosta matryca, którą należy dobrze zrozumieć przed wyciągnięciem wniosków. Oto uproszczona, możliwa do wyjaśnienia wersja powyższych odpowiedzi.

        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
źródło
4
Czy możesz to edytować, aby powiedzieć, jak według ciebie wykracza to poza udzielone już odpowiedzi?
mdewey,
1
Hej! Właśnie odniosłem się do odpowiedzi Akavall. Wspomniał o zaangażowanym myśleniu. Właśnie wyjaśniłem jego odpowiedź, która wydaje się być poprawna, prawdopodobnie w lepszy sposób.
Pranzell
@Pranzell Czy mógłbyś udostępnić swój kod, aby narysować tak piękną tabelę tekstową?
fu DL