34 votos

¿Cómo puedo interpretar una matriz de confusión?

Estoy usando matriz de confusión para comprobar el rendimiento de mi clasificador.

Estoy usando Scikit-Learn, estoy un poco confundido. ¿Cómo puedo interpretar el resultado de

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

¿Cómo puedo decidir si estos valores previstos son buenos o no?

1 votos

Inicialmente olvídate de sklearn, eso es una pista falsa. El origen de tu malentendido parece más fundamental. Echa un vistazo aquí: es.wikipedia.org/wiki/Matriz de confusión . Concéntrese en la narración del ejemplo 3*3 en la página de la wikipedia. Eso probablemente resolverá lo que sea su confusión.

0 votos

54voto

achennu Puntos 101

La matriz de confusión es una forma de tabular el número de clasificaciones erróneas, es decir, el número de clases predichas que terminaron en una casilla de clasificación errónea basada en las clases verdaderas.

Aunque sklearn.metrics.confusion_matrix proporciona una matriz numérica, me parece más útil generar un "informe" utilizando lo siguiente:

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)

lo que resulta en:

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

Esto nos permite ver que:

  1. Los elementos diagonales muestran el número de clasificaciones correctas para cada clase: 3, 1 y 3 para las clases 0, 1 y 2.
  2. Los elementos fuera de diagonal proporcionan las clasificaciones erróneas: por ejemplo, 2 de la clase 2 fueron clasificados erróneamente como 0, ninguno de la clase 0 fue clasificado erróneamente como 2, etc.
  3. El número total de clasificaciones para cada clase en ambos y_true y y_pred de los subtotales "Todos"

Este método también funciona para las etiquetas de texto, y para un gran número de muestras en el conjunto de datos puede ampliarse para proporcionar informes de porcentaje.

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

La salida entonces es:

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

donde las cifras representan ahora el porcentaje (en lugar del número de casos) de los resultados que fueron clasificados.

Aunque hay que tener en cuenta que el sklearn.metrics.confusion_matrix La salida se puede visualizar directamente con:

import matplotlib.pyplot as plt
conf = sklearn.metrics.confusion_matrix(y_true, y_pred)
plt.imshow(conf, cmap='binary', interpolation='None')
plt.show()

4 votos

¡Bienvenido a nuestro sitio! Aprecio el cuidado y la calidad que has puesto en tu primera respuesta aquí.

1 votos

El primer ejemplo ya no funciona, al menos a partir de pandas-0.13.1. Acabo de actualizar a pandas-0.16.0, y sigue dando el mismo error: AssertionError: arrays and names must have the same length

1 votos

@chbrown: parece que algo ha cambiado en pandas que necesita que los sit sean un array o una serie. He actualizado el código de ejemplo para utilizar y_pred = pd.Series(...) . Esto debería funcionar ahora.

5voto

Charles Ma Puntos 12330

En el eje Y la matriz de confusión tiene los valores reales, y en el eje X los valores dados por el predictor. Por tanto, los recuentos de la diagonal son el número de predicciones correctas. Y los elementos de la diagonal son las predicciones incorrectas.

En su caso:

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

0 votos

Es un poco confuso (Usted dijo "# uno 1 se predijo como 2" - mientras que en la diagonal es 0), tengo una matriz de 50K elemento es un poco difícil de proyectar todos los valores. ¿Hay alguna métrica que me dé estos resultados directamente? (Me refiero a si estoy obteniendo una buena matriz de confusión o no).

1 votos

Podrías mirar los elementos en la diagonal, esos son tus predicciones correctas, los elementos fuera de la diagonal son predicciones incorrectas. Eso es un comienzo.

0 votos

He obtenido dos resultados diferentes. En el objetivo, tenemos dos etiquetas '0' o '1', ¿Puede ayudar a dar una pista de cómo interpretar los resultados. - matriz_de_confusión: [[ 0 85723] [ 0 77]] - confusion_matrix: [[85648 75] [ 75 2]]

2voto

Dom Hastings Puntos 131

Me gustaría especificar gráficamente la necesidad de entender esto. Es una matriz sencilla que hay que entender bien antes de llegar a conclusiones. Así que aquí está una versión simplificada y explicable de las respuestas anteriores.

        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

Y, como pidió mi amigo @fu DL, aquí está el código:

from sklearn.metrics import confusion_matrix

Y_true = [0,0,0,1,1,1,2,2,0,1,2]
Y_pred = [0,0,1,1,1,2,2,2,0,0,0]

confusion = confusion_matrix(Y_true, Y_pred)

# PUT YOUR DESIRED LABELS HERE... 
row_label = "True"
col_label = "Predicted"

# For printing column label right in the middle
col_space = len(row_label)
index_middle = int(int(len(set(Y_true)))/2)

# Prints first row
print(" "*(col_space + 4), "  ".join([str(i) for i in set(Y_true)]), " <-  {}".format(col_label))

# Prints rest of the table
for index in range(len(set(Y_true))):
    if index == index_middle:
        print(row_label, " ", index, confusion[index])
    else:
        print(" "*(col_space+2), index, confusion[index])

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X