sklearn recall org example confusion_matrix confusion classification_report accuracy python machine-learning scikit-learn classification supervised-learning

python - recall - sklearn metrics



Scikit-learn: Cómo obtener True Positive, True Negative, False Positive y False Negative (10)

Soy nuevo en aprendizaje automático y en scikit-learn.

Mi problema:

(Por favor, corrija cualquier tipo de idea errónea)

Tengo un conjunto de datos que es un BIG JSON, lo recupero y lo trainList en una variable trainList .

Lo pre-proceso para poder trabajar con él.

Una vez hecho esto, empiezo la clasificación:

  1. Utilizo el método de validación cruzada kfold para obtener la precisión media y entreno a un clasificador.
  2. Realizo las predicciones y obtengo la matriz de precisión y confusión de ese pliegue.
  3. Después de esto, me gustaría obtener los valores de Verdadero Positivo (TP), Verdadero Negativo (TN), Falso Positivo (FP) y Falso Negativo (FN). Usaría estos parámetros para obtener la Sensibilidad y la especificidad, y los utilizaría con el total de los TP a un HTML para mostrar un gráfico con los TP de cada etiqueta.

Código:

Las variables que tengo por el momento:

trainList #It is a list with all the data of my dataset in JSON form labelList #It is a list with all the labels of my data

La mayor parte del método:

#I transform the data from JSON form to a numerical one X=vec.fit_transform(trainList) #I scale the matrix (don''t know why but without it, it makes an error) X=preprocessing.scale(X.toarray()) #I generate a KFold in order to make cross validation kf = KFold(len(X), n_folds=10, indices=True, shuffle=True, random_state=1) #I start the cross validation for train_indices, test_indices in kf: X_train=[X[ii] for ii in train_indices] X_test=[X[ii] for ii in test_indices] y_train=[listaLabels[ii] for ii in train_indices] y_test=[listaLabels[ii] for ii in test_indices] #I train the classifier trained=qda.fit(X_train,y_train) #I make the predictions predicted=qda.predict(X_test) #I obtain the accuracy of this fold ac=accuracy_score(predicted,y_test) #I obtain the confusion matrix cm=confusion_matrix(y_test, predicted) #I should calculate the TP,TN, FP and FN #I don''t know how to continue


Aquí hay una solución para el código de buggy de invoketheshell (que actualmente aparece como la respuesta aceptada):

def performance_measure(y_actual, y_hat): TP = 0 FP = 0 TN = 0 FN = 0 for i in range(len(y_hat)): if y_actual[i] == y_hat[i]==1: TP += 1 if y_hat[i] == 1 and y_actual[i] == 0: FP += 1 if y_hat[i] == y_actual[i] == 0: TN +=1 if y_hat[i] == 0 and y_actual[i] == 1: FN +=1 return(TP, FP, TN, FN)


Creo que ambas respuestas no son del todo correctas. Por ejemplo, supongamos que tenemos las siguientes matrices;
y_actual = [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0]

y_predic = [1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0]

Si calculamos los valores de FP, FN, TP y TN manualmente, deben ser los siguientes:

FP: 3 FN: 1 TP: 3 TN: 4

Sin embargo, si utilizamos la primera respuesta, los resultados se dan de la siguiente manera:

FP: 1 FN: 3 TP: 3 TN: 4

No son correctos, porque en la primera respuesta, Falso Positivo debe estar donde real es 0, pero el pronosticado es 1, no lo contrario. También es igual para Falso Negativo.

Y, si usamos la segunda respuesta, los resultados se computan de la siguiente manera:

FP: 3 FN: 1 TP: 4 TN: 3

Los números True Positive y True Negative no son correctos, deben ser opuestos.

¿Estoy correcto con mis cálculos? Por favor avíseme si me falta algo.


En la biblioteca de "métricas" de scikit-learn hay un método de confusión_matriz que le da el resultado deseado.

Puede utilizar cualquier clasificador que desee. Aquí utilicé a los vecinos como ejemplo.

from sklearn import metrics, neighbors clf = neighbors.KNeighborsClassifier() X_test = ... y_test = ... expected = y_test predicted = clf.predict(X_test) conf_matrix = metrics.confusion_matrix(expected, predicted) >>> print conf_matrix >>> [[1403 87] [ 56 3159]]

Los documentos: http://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html#sklearn.metrics.confusion_matrix


Escribí una versión que funciona usando solo numpy. Espero que te ayude.

import numpy as np def perf_metrics_2X2(yobs, yhat): """ Returns the specificity, sensitivity, positive predictive value, and negative predictive value of a 2X2 table. where: 0 = negative case 1 = positive case Parameters ---------- yobs : array of positive and negative ``observed`` cases yhat : array of positive and negative ``predicted`` cases Returns ------- sensitivity = TP / (TP+FN) specificity = TN / (TN+FP) pos_pred_val = TP/ (TP+FP) neg_pred_val = TN/ (TN+FN) Author: Julio Cardenas-Rodriguez """ TP = np.sum( yobs[yobs==1] == yhat[yobs==1] ) TN = np.sum( yobs[yobs==0] == yhat[yobs==0] ) FP = np.sum( yobs[yobs==1] == yhat[yobs==0] ) FN = np.sum( yobs[yobs==0] == yhat[yobs==1] ) sensitivity = TP / (TP+FN) specificity = TN / (TN+FP) pos_pred_val = TP/ (TP+FP) neg_pred_val = TN/ (TN+FN) return sensitivity, specificity, pos_pred_val, neg_pred_val


Para el caso de clases múltiples, todo lo que necesita puede encontrarse en la matriz de confusión. Por ejemplo, si su matriz de confusión se ve así:

Entonces, lo que estás buscando, por clase, se puede encontrar así:

Usando pandas / numpy, puedes hacer esto para todas las clases a la vez así:

FP = confusion_matrix.sum(axis=0) - np.diag(confusion_matrix) FN = confusion_matrix.sum(axis=1) - np.diag(confusion_matrix) TP = np.diag(confusion_matrix) TN = confusion_matrix.values.sum() - (FP + FN + TP) # Sensitivity, hit rate, recall, or true positive rate TPR = TP/(TP+FN) # Specificity or true negative rate TNR = TN/(TN+FP) # Precision or positive predictive value PPV = TP/(TP+FP) # Negative predictive value NPV = TN/(TN+FN) # Fall out or false positive rate FPR = FP/(FP+TN) # False negative rate FNR = FN/(TP+FN) # False discovery rate FDR = FP/(TP+FP) # Overall accuracy ACC = (TP+TN)/(TP+FP+FN+TN)


Puede obtener todos los parámetros de la matriz de confusión. La estructura de la matriz de confusión (que es la matriz 2X2) es la siguiente

TP|FP FN|TN

Asi que

TP = cm[0][0] FP = cm[0][1] FN = cm[1][0] TN = cm[1][1]

Más detalles en https://en.wikipedia.org/wiki/Confusion_matrix


Según la documentación de scikit-learn,

http://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html#sklearn.metrics.confusion_matrix

Por definición, una matriz de confusión C es tal que C [i, j] es igual al número de observaciones que se sabe que están en el grupo i pero que se predice que están en el grupo j.

Por lo tanto, en la clasificación binaria, el recuento de verdaderos negativos es C [0,0], los falsos negativos es C [1,0], los verdaderos positivos son C [1,1] y los falsos positivos son C [0,1].

CM = confusion_matrix(y_true, y_pred) TN = CM[0][0] FN = CM[1][0] TP = CM[1][1] FP = CM[0][1]


Si tiene dos listas que tienen los valores predichos y reales; Como parece que lo hace, puede pasarlos a una función que calculará TP, FP, TN, FN con algo como esto:

def perf_measure(y_actual, y_hat): TP = 0 FP = 0 TN = 0 FN = 0 for i in range(len(y_hat)): if y_actual[i]==y_hat[i]==1: TP += 1 if y_hat[i]==1 and y_actual[i]!=y_hat[i]: FP += 1 if y_actual[i]==y_hat[i]==0: TN += 1 if y_hat[i]==0 and y_actual[i]!=y_hat[i]: FN += 1 return(TP, FP, TN, FN)

Desde aquí, creo que podrá calcular las tasas de interés para usted y otras medidas de rendimiento, como la especificidad y la sensibilidad.


Si tiene más de una clase en su clasificador, puede usar pandas-ml en esa parte. La Matriz de Confusión de pandas-ml da información más detallada. Mira esto


puede probar sklearn.metrics.classification_report como se muestra a continuación:

import sklearn y_true = [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0] y_pred = [1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0] print sklearn.metrics.classification_report(y_true, y_pred)

salida:

precision recall f1-score support 0 0.80 0.57 0.67 7 1 0.50 0.75 0.60 4 avg / total 0.69 0.64 0.64 11