J'ai écrit un code de calcul de matrice de confusion en Python:
def conf_mat(prob_arr, input_arr):
# confusion matrix
conf_arr = [[0, 0], [0, 0]]
for i in range(len(prob_arr)):
if int(input_arr[i]) == 1:
if float(prob_arr[i]) < 0.5:
conf_arr[0][1] = conf_arr[0][1] + 1
else:
conf_arr[0][0] = conf_arr[0][0] + 1
Elif int(input_arr[i]) == 2:
if float(prob_arr[i]) >= 0.5:
conf_arr[1][0] = conf_arr[1][0] +1
else:
conf_arr[1][1] = conf_arr[1][1] +1
accuracy = float(conf_arr[0][0] + conf_arr[1][1])/(len(input_arr))
prob_arr est un tableau que mon code de classification a renvoyé et un exemple de tableau ressemble à ceci:
[1.0, 1.0, 1.0, 0.41592955657342651, 1.0, 0.0053405015805891975, 4.5321494433440449e-299, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.70943426182688163, 1.0, 1.0, 1.0, 1.0]
input_arr est le libellé de classe d'origine d'un ensemble de données et se présente comme suit:
[2, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1]
Ce que mon code essaie de faire est: je reçois prob_arr et input_arr et pour chaque classe (1 et 2) je vérifie s’ils sont mal classés ou non.
Mais mon code ne fonctionne que pour deux classes. Si je lance ce code pour plusieurs données classées, cela ne fonctionne pas. Comment puis-je faire cela pour plusieurs classes?
Par exemple, pour un ensemble de données avec trois classes, il devrait renvoyer: [[21,7,3],[3,38,6],[5,4,19]]
Scikit-Learn fournit une fonction confusion_matrix
from sklearn.metrics import confusion_matrix
y_actu = [2, 0, 2, 2, 0, 1, 1, 2, 2, 0, 1, 2]
y_pred = [0, 0, 2, 1, 0, 2, 1, 0, 2, 0, 2, 2]
confusion_matrix(y_actu, y_pred)
qui sort un tableau de Numpy
array([[3, 0, 0],
[0, 1, 2],
[2, 1, 3]])
Mais vous pouvez aussi créer une matrice de confusion en utilisant des pandas:
import pandas as pd
y_actu = pd.Series([2, 0, 2, 2, 0, 1, 1, 2, 2, 0, 1, 2], name='Actual')
y_pred = pd.Series([0, 0, 2, 1, 0, 2, 1, 0, 2, 0, 2, 2], name='Predicted')
df_confusion = pd.crosstab(y_actu, y_pred)
Vous obtiendrez un Pandas DataFrame (bien étiqueté):
Predicted 0 1 2
Actual
0 3 0 0
1 0 1 2
2 2 1 3
Si vous ajoutez margins=True
comme
df_confusion = pd.crosstab(y_actu, y_pred, rownames=['Actual'], colnames=['Predicted'], margins=True)
vous obtiendrez également la somme pour chaque ligne et colonne:
Predicted 0 1 2 All
Actual
0 3 0 0 3
1 0 1 2 3
2 2 1 3 6
All 5 2 5 12
Vous pouvez également obtenir une matrice de confusion normalisée en utilisant:
df_conf_norm = df_confusion / df_confusion.sum(axis=1)
Predicted 0 1 2
Actual
0 1.000000 0.000000 0.000000
1 0.000000 0.333333 0.333333
2 0.666667 0.333333 0.500000
Vous pouvez tracer cette confusion_matrix en utilisant
def plot_confusion_matrix(df_confusion, title='Confusion matrix', cmap=plt.cm.gray_r):
plt.matshow(df_confusion, cmap=cmap) # imshow
#plt.title(title)
plt.colorbar()
tick_marks = np.arange(len(df_confusion.columns))
plt.xticks(tick_marks, df_confusion.columns, rotation=45)
plt.yticks(tick_marks, df_confusion.index)
#plt.tight_layout()
plt.ylabel(df_confusion.index.name)
plt.xlabel(df_confusion.columns.name)
plot_confusion_matrix(df_confusion)
Ou tracez la matrice de confusion normalisée en utilisant:
plot_confusion_matrix(df_conf_norm)
Ce projet pourrait également vous intéresser https://github.com/pandas-ml/pandas-ml et son paquet Pip https://pypi.python.org/pypi/pandas_ml
Avec ce paquet, la matrice de confusion peut être imprimée joliment, tracer . Vous pouvez binariser une matrice de confusion, obtenir des statistiques de classe telles que TP, TN, FP, FN, ACC, TPR, FPR, FNR, TNR , LR-, DOR, VPP, FDR, FOR, VAN et quelques statistiques globales
In [1]: from pandas_ml import ConfusionMatrix
In [2]: y_actu = [2, 0, 2, 2, 0, 1, 1, 2, 2, 0, 1, 2]
In [3]: y_pred = [0, 0, 2, 1, 0, 2, 1, 0, 2, 0, 2, 2]
In [4]: cm = ConfusionMatrix(y_actu, y_pred)
In [5]: cm.print_stats()
Confusion Matrix:
Predicted 0 1 2 __all__
Actual
0 3 0 0 3
1 0 1 2 3
2 2 1 3 6
__all__ 5 2 5 12
Overall Statistics:
Accuracy: 0.583333333333
95% CI: (0.27666968568210581, 0.84834777019156982)
No Information Rate: ToDo
P-Value [Acc > NIR]: 0.189264302376
Kappa: 0.354838709677
Mcnemar's Test P-Value: ToDo
Class Statistics:
Classes 0 1 2
Population 12 12 12
P: Condition positive 3 3 6
N: Condition negative 9 9 6
Test outcome positive 5 2 5
Test outcome negative 7 10 7
TP: True Positive 3 1 3
TN: True Negative 7 8 4
FP: False Positive 2 1 2
FN: False Negative 0 2 3
TPR: (Sensitivity, hit rate, recall) 1 0.3333333 0.5
TNR=SPC: (Specificity) 0.7777778 0.8888889 0.6666667
PPV: Pos Pred Value (Precision) 0.6 0.5 0.6
NPV: Neg Pred Value 1 0.8 0.5714286
FPR: False-out 0.2222222 0.1111111 0.3333333
FDR: False Discovery Rate 0.4 0.5 0.4
FNR: Miss Rate 0 0.6666667 0.5
ACC: Accuracy 0.8333333 0.75 0.5833333
F1 score 0.75 0.4 0.5454545
MCC: Matthews correlation coefficient 0.6831301 0.2581989 0.1690309
Informedness 0.7777778 0.2222222 0.1666667
Markedness 0.6 0.3 0.1714286
Prevalence 0.25 0.25 0.5
LR+: Positive likelihood ratio 4.5 3 1.5
LR-: Negative likelihood ratio 0 0.75 0.75
DOR: Diagnostic odds ratio inf 4 2
FOR: False omission rate 0 0.2 0.4285714
J'ai remarqué qu'une nouvelle bibliothèque Python sur Confusion Matrix nommée PyCM est sortie: vous pouvez peut-être jeter un coup d'œil.
Scikit-learn (que je recommande d'utiliser de toute façon) l'a inclus dans le module metrics
:
>>> from sklearn.metrics import confusion_matrix
>>> y_true = [0, 1, 2, 0, 1, 2, 0, 1, 2]
>>> y_pred = [0, 0, 0, 0, 1, 1, 0, 2, 2]
>>> confusion_matrix(y_true, y_pred)
array([[3, 0, 0],
[1, 1, 1],
[1, 1, 1]])
Si vous ne voulez pas que scikit-apprenne à faire le travail pour vous ...
import numpy
actual = numpy.array(actual)
predicted = numpy.array(predicted)
# calculate the confusion matrix; labels is numpy array of classification labels
cm = numpy.zeros((len(labels), len(labels)))
for a, p in Zip(actual, predicted):
cm[a][p] += 1
# also get the accuracy easily with numpy
accuracy = (actual == predicted).sum() / float(len(actual))
Ou jetez un oeil à une implémentation plus complète ici dans NLTK .
Presque une décennie a passé, mais les solutions (sans aide précieuse) à ce poste sont compliquées et inutilement longues. Calculer une matrice de confusion peut être fait proprement en Python en quelques lignes. Par exemple:
def compute_confusion_matrix(true, pred):
'''Computes a confusion matrix using numpy for two np.arrays
true and pred.
Results are identical (and similar in computation time) to:
"from sklearn.metrics import confusion_matrix"
However, this function avoids the dependency on sklearn.'''
K = len(np.unique(true)) # Number of classes
result = np.zeros((K, K))
for i in range(len(true)):
result[true[i]][pred[i]] += 1
return result
Cette fonction crée des matrices de confusion pour un nombre quelconque de classes.
def create_conf_matrix(expected, predicted, n_classes):
m = [[0] * n_classes for i in range(n_classes)]
for pred, exp in Zip(predicted, expected):
m[pred][exp] += 1
return m
def calc_accuracy(conf_matrix):
t = sum(sum(l) for l in conf_matrix)
return sum(conf_matrix[i][i] for i in range(len(conf_matrix))) / t
Contrairement à votre fonction ci-dessus, vous devez extraire les classes prédites avant d'appeler la fonction, en fonction de vos résultats de classification, c'est-à-dire sth. comme
[1 if p < .5 else 2 for p in classifications]
Voici une classe de matrice de confusion qui prend en charge la jolie impression, etc.:
http://nltk.googlecode.com/svn/trunk/doc/api/nltk.metrics.confusionmatrix-pysrc.html
Mettre à jour
Depuis la rédaction de cet article, j'ai mis à jour l'implémentation de ma bibliothèque pour y inclure quelques autres fonctionnalités de Nice. Comme pour le code ci-dessous, aucune dépendance tierce n'est requise. La classe peut également produire un tableau de tabulation de Nice, similaire à de nombreux progiciels statistiques couramment utilisés. Voir ceci Gist .
Une implémentation multiclass simple
Une matrice de confusion multi-classes peut être calculée très simplement avec Vanilla Python en environ O(N) temps. Il suffit d’associer les classes uniques trouvées dans le vecteur actual
dans une liste à 2 dimensions. À partir de là, nous parcourons simplement les vecteurs actual
et predicted
compressés et remplissons les comptes.
# A Simple Confusion Matrix Implementation
def confusionmatrix(actual, predicted, normalize = False):
"""
Generate a confusion matrix for multiple classification
@params:
actual - a list of integers or strings for known classes
predicted - a list of integers or strings for predicted classes
normalize - optional boolean for matrix normalization
@return:
matrix - a 2-dimensional list of pairwise counts
"""
unique = sorted(set(actual))
matrix = [[0 for _ in unique] for _ in unique]
imap = {key: i for i, key in enumerate(unique)}
# Generate Confusion Matrix
for p, a in Zip(predicted, actual):
matrix[imap[p]][imap[a]] += 1
# Matrix Normalization
if normalize:
sigma = sum([sum(matrix[imap[i]]) for i in unique])
matrix = [row for row in map(lambda i: list(map(lambda j: j / sigma, i)), matrix)]
return matrix
Utilisation
# Input Below Should Return: [[2, 1, 0], [0, 2, 1], [1, 2, 1]]
cm = confusionmatrix(
[1, 1, 2, 0, 1, 1, 2, 0, 0, 1], # actual
[0, 1, 1, 0, 2, 1, 2, 2, 0, 2] # predicted
)
# And The Output
print(cm)
[[2, 1, 0], [0, 2, 1], [1, 2, 1]]
Remarque: les classes actual
se trouvent le long des colonnes et les classes predicted
se trouvent le long des lignes.
# Actual
# 0 1 2
# # #
[[2, 1, 0], # 0
[0, 2, 1], # 1 Predicted
[1, 2, 1]] # 2
Les noms de classe peuvent être des chaînes ou des entiers
# Input Below Should Return: [[2, 1, 0], [0, 2, 1], [1, 2, 1]]
cm = confusionmatrix(
["B", "B", "C", "A", "B", "B", "C", "A", "A", "B"], # actual
["A", "B", "B", "A", "C", "B", "C", "C", "A", "C"] # predicted
)
# And The Output
print(cm)
[[2, 1, 0], [0, 2, 1], [1, 2, 1]]
Vous pouvez également renvoyer la matrice avec des proportions (normalisation)
# Input Below Should Return: [[0.2, 0.1, 0.0], [0.0, 0.2, 0.1], [0.1, 0.2, 0.1]]
cm = confusionmatrix(
["B", "B", "C", "A", "B", "B", "C", "A", "A", "B"], # actual
["A", "B", "B", "A", "C", "B", "C", "C", "A", "C"], # predicted
normalize = True
)
# And The Output
print(cm)
[[0.2, 0.1, 0.0], [0.0, 0.2, 0.1], [0.1, 0.2, 0.1]]
Extraction de statistiques d'une matrice de confusion de classification multiple
Une fois que vous avez la matrice, vous pouvez calculer plusieurs statistiques pour évaluer votre classificateur. Cela dit, extraire les valeurs d'une configuration de matrice de confusion pour une classification multiple peut s'avérer être un casse-tête. Voici une fonction qui renvoie à la fois la matrice de confusion et les statistiques par classe:
# Not Required, But Nice For Legibility
from collections import OrderedDict
# A Simple Confusion Matrix Implementation
def confusionmatrix(actual, predicted, normalize = False):
"""
Generate a confusion matrix for multiple classification
@params:
actual - a list of integers or strings for known classes
predicted - a list of integers or strings for predicted classes
@return:
matrix - a 2-dimensional list of pairwise counts
statistics - a dictionary of statistics for each class
"""
unique = sorted(set(actual))
matrix = [[0 for _ in unique] for _ in unique]
imap = {key: i for i, key in enumerate(unique)}
# Generate Confusion Matrix
for p, a in Zip(predicted, actual):
matrix[imap[p]][imap[a]] += 1
# Get Confusion Matrix Sum
sigma = sum([sum(matrix[imap[i]]) for i in unique])
# Scaffold Statistics Data Structure
statistics = OrderedDict(((i, {"counts" : OrderedDict(), "stats" : OrderedDict()}) for i in unique))
# Iterate Through Classes & Compute Statistics
for i in unique:
loc = matrix[imap[i]][imap[i]]
row = sum(matrix[imap[i]][:])
col = sum([row[imap[i]] for row in matrix])
# Get TP/TN/FP/FN
tp = loc
fp = row - loc
fn = col - loc
tn = sigma - row - col + loc
# Populate Counts Dictionary
statistics[i]["counts"]["tp"] = tp
statistics[i]["counts"]["fp"] = fp
statistics[i]["counts"]["tn"] = tn
statistics[i]["counts"]["fn"] = fn
statistics[i]["counts"]["pos"] = tp + fn
statistics[i]["counts"]["neg"] = tn + fp
statistics[i]["counts"]["n"] = tp + tn + fp + fn
# Populate Statistics Dictionary
statistics[i]["stats"]["sensitivity"] = tp / (tp + fn) if tp > 0 else 0.0
statistics[i]["stats"]["specificity"] = tn / (tn + fp) if tn > 0 else 0.0
statistics[i]["stats"]["precision"] = tp / (tp + fp) if tp > 0 else 0.0
statistics[i]["stats"]["recall"] = tp / (tp + fn) if tp > 0 else 0.0
statistics[i]["stats"]["tpr"] = tp / (tp + fn) if tp > 0 else 0.0
statistics[i]["stats"]["tnr"] = tn / (tn + fp) if tn > 0 else 0.0
statistics[i]["stats"]["fpr"] = fp / (fp + tn) if fp > 0 else 0.0
statistics[i]["stats"]["fnr"] = fn / (fn + tp) if fn > 0 else 0.0
statistics[i]["stats"]["accuracy"] = (tp + tn) / (tp + tn + fp + fn) if (tp + tn) > 0 else 0.0
statistics[i]["stats"]["f1score"] = (2 * tp) / ((2 * tp) + (fp + fn)) if tp > 0 else 0.0
statistics[i]["stats"]["fdr"] = fp / (fp + tp) if fp > 0 else 0.0
statistics[i]["stats"]["for"] = fn / (fn + tn) if fn > 0 else 0.0
statistics[i]["stats"]["ppv"] = tp / (tp + fp) if tp > 0 else 0.0
statistics[i]["stats"]["npv"] = tn / (tn + fn) if tn > 0 else 0.0
# Matrix Normalization
if normalize:
matrix = [row for row in map(lambda i: list(map(lambda j: j / sigma, i)), matrix)]
return matrix, statistics
Statistiques calculées
Ci-dessus, la matrice de confusion est utilisée pour tabuler des statistiques pour chaque classe, qui sont renvoyées dans une variable OrderedDict
avec la structure suivante:
OrderedDict(
[
('A', {
'stats' : OrderedDict([
('sensitivity', 0.6666666666666666),
('specificity', 0.8571428571428571),
('precision', 0.6666666666666666),
('recall', 0.6666666666666666),
('tpr', 0.6666666666666666),
('tnr', 0.8571428571428571),
('fpr', 0.14285714285714285),
('fnr', 0.3333333333333333),
('accuracy', 0.8),
('f1score', 0.6666666666666666),
('fdr', 0.3333333333333333),
('for', 0.14285714285714285),
('ppv', 0.6666666666666666),
('npv', 0.8571428571428571)
]),
'counts': OrderedDict([
('tp', 2),
('fp', 1),
('tn', 6),
('fn', 1),
('pos', 3),
('neg', 7),
('n', 10)
])
}),
('B', {
'stats': OrderedDict([
('sensitivity', 0.4),
('specificity', 0.8),
('precision', 0.6666666666666666),
('recall', 0.4),
('tpr', 0.4),
('tnr', 0.8),
('fpr', 0.2),
('fnr', 0.6),
('accuracy', 0.6),
('f1score', 0.5),
('fdr', 0.3333333333333333),
('for', 0.42857142857142855),
('ppv', 0.6666666666666666),
('npv', 0.5714285714285714)
]),
'counts': OrderedDict([
('tp', 2),
('fp', 1),
('tn', 4),
('fn', 3),
('pos', 5),
('neg', 5),
('n', 10)
])
}),
('C', {
'stats': OrderedDict([
('sensitivity', 0.5),
('specificity', 0.625),
('precision', 0.25),
('recall', 0.5),
('tpr', 0.5),
('tnr', 0.625), (
'fpr', 0.375), (
'fnr', 0.5),
('accuracy', 0.6),
('f1score', 0.3333333333333333),
('fdr', 0.75),
('for', 0.16666666666666666),
('ppv', 0.25),
('npv', 0.8333333333333334)
]),
'counts': OrderedDict([
('tp', 1),
('fp', 3),
('tn', 5),
('fn', 1),
('pos', 2),
('neg', 8),
('n', 10)
])
})
]
)
Voici une implémentation simple qui gère un nombre inégal de classes dans les étiquettes prédites et réelles (voir les exemples 3 et 4). J'espère que ça aide!
Pour les personnes qui viennent d’apprendre cela, voici un rapide aperçu. Les étiquettes des colonnes indiquent la classe prédite et les étiquettes des lignes indiquent la classe correcte. Dans l'exemple 1, nous avons [3 1] sur la rangée supérieure. Encore une fois, les lignes indiquent la vérité. Cela signifie donc que l'étiquette correcte est "0" et qu'il existe 4 exemples avec une étiquette de vérité au sol de "0". Les colonnes indiquent les prédictions. Nous avons donc 3/4 des échantillons correctement étiquetés "0", mais 1/4 a été incorrectement étiqueté comme "1".
def confusion_matrix(actual, predicted):
classes = np.unique(np.concatenate((actual,predicted)))
confusion_mtx = np.empty((len(classes),len(classes)),dtype=np.int)
for i,a in enumerate(classes):
for j,p in enumerate(classes):
confusion_mtx[i,j] = np.where((actual==a)*(predicted==p))[0].shape[0]
return confusion_mtx
Exemple 1:
actual = np.array([1,1,1,1,0,0,0,0])
predicted = np.array([1,1,1,1,0,0,0,1])
confusion_matrix(actual,predicted)
0 1
0 3 1
1 0 4
Exemple 2:
actual = np.array(["a","a","a","a","b","b","b","b"])
predicted = np.array(["a","a","a","a","b","b","b","a"])
confusion_matrix(actual,predicted)
0 1
0 4 0
1 1 3
Exemple 3:
actual = np.array(["a","a","a","a","b","b","b","b"])
predicted = np.array(["a","a","a","a","b","b","b","z"]) # <-- notice the 3rd class, "z"
confusion_matrix(actual,predicted)
0 1 2
0 4 0 0
1 0 3 1
2 0 0 0
Exemple 4:
actual = np.array(["a","a","a","x","x","b","b","b"]) # <-- notice the 4th class, "x"
predicted = np.array(["a","a","a","a","b","b","b","z"])
confusion_matrix(actual,predicted)
0 1 2 3
0 3 0 0 0
1 0 2 0 1
2 1 1 0 0
3 0 0 0 0
J'ai écrit un cours simple pour construire une matrice de confusion sans avoir à dépendre d'une bibliothèque d'apprentissage automatique.
La classe peut être utilisée telle que:
labels = ["cat", "dog", "velociraptor", "kraken", "pony"]
confusionMatrix = ConfusionMatrix(labels)
confusionMatrix.update("cat", "cat")
confusionMatrix.update("cat", "dog")
...
confusionMatrix.update("kraken", "velociraptor")
confusionMatrix.update("velociraptor", "velociraptor")
confusionMatrix.plot()
La classe ConfusionMatrix:
import pylab
import collections
import numpy as np
class ConfusionMatrix:
def __init__(self, labels):
self.labels = labels
self.confusion_dictionary = self.build_confusion_dictionary(labels)
def update(self, predicted_label, expected_label):
self.confusion_dictionary[expected_label][predicted_label] += 1
def build_confusion_dictionary(self, label_set):
expected_labels = collections.OrderedDict()
for expected_label in label_set:
expected_labels[expected_label] = collections.OrderedDict()
for predicted_label in label_set:
expected_labels[expected_label][predicted_label] = 0.0
return expected_labels
def convert_to_matrix(self, dictionary):
length = len(dictionary)
confusion_dictionary = np.zeros((length, length))
i = 0
for row in dictionary:
j = 0
for column in dictionary:
confusion_dictionary[i][j] = dictionary[row][column]
j += 1
i += 1
return confusion_dictionary
def get_confusion_matrix(self):
matrix = self.convert_to_matrix(self.confusion_dictionary)
return self.normalize(matrix)
def normalize(self, matrix):
amin = np.amin(matrix)
amax = np.amax(matrix)
return [[(((y - amin) * (1 - 0)) / (amax - amin)) for y in x] for x in matrix]
def plot(self):
matrix = self.get_confusion_matrix()
pylab.figure()
pylab.imshow(matrix, interpolation='nearest', cmap=pylab.cm.jet)
pylab.title("Confusion Matrix")
for i, vi in enumerate(matrix):
for j, vj in enumerate(vi):
pylab.text(j, i+.1, "%.1f" % vj, fontsize=12)
pylab.colorbar()
classes = np.arange(len(self.labels))
pylab.xticks(classes, self.labels)
pylab.yticks(classes, self.labels)
pylab.ylabel('Expected label')
pylab.xlabel('Predicted label')
pylab.show()
Une solution numérique uniquement pour un nombre quelconque de classes ne nécessitant pas de bouclage:
import numpy as np
classes = 3
true = np.random.randint(0, classes, 50)
pred = np.random.randint(0, classes, 50)
np.bincount(true * classes + pred).reshape((classes, classes))
Vous devez mapper des classes sur une ligne dans votre matrice de confusion.
Ici la cartographie est triviale:
def row_of_class(classe):
return {1: 0, 2: 1}[classe]
Dans votre boucle, calculez expected_row
, correct_row
et incrémentez conf_arr[expected_row][correct_row]
. Vous aurez même moins de code que celui avec lequel vous avez commencé.
Seulement avec numpy, nous pouvons faire ce qui suit en considérant l'efficacité:
def confusion_matrix(pred, label, nc=None):
assert pred.size == label.size
if nc is None:
nc = len(unique(label))
logging.debug("Number of classes assumed to be {}".format(nc))
confusion = np.zeros([nc, nc])
# avoid the confusion with `0`
tran_pred = pred + 1
for i in xrange(nc): # current class
mask = (label == i)
masked_pred = mask * tran_pred
cls, counts = unique(masked_pred, return_counts=True)
# discard the first item
cls = [cl - 1 for cl in cls][1:]
counts = counts[1:]
for cl, count in Zip(cls, counts):
confusion[i, cl] = count
return confusion
Pour d'autres fonctionnalités telles que plot, mean-IoU, voir mes référentiels .
Vous pouvez rendre votre code plus concis et (parfois) plus rapide en utilisant numpy
. Par exemple, dans le cas de deux classes, votre fonction peut être réécrite comme suit (voir mply.acc()
):
def accuracy(actual, predicted):
"""accuracy = (tp + tn) / ts
, where:
ts - Total Samples
tp - True Positives
tn - True Negatives
"""
return (actual == predicted).sum() / float(len(actual))
, où:
actual = (numpy.array(input_arr) == 2)
predicted = (numpy.array(prob_arr) < 0.5)
De manière générale, vous devrez modifier votre tableau de probabilité. Au lieu d’avoir un nombre pour chaque instance et de classer selon qu’il soit ou non supérieur à 0,5, vous aurez besoin d’une liste de scores (un pour chaque classe), puis prenez le plus grand des scores comme classe choisi (aka argmax).
Vous pouvez utiliser un dictionnaire pour contenir les probabilités pour chaque classification:
prob_arr = [{classification_id: probability}, ...]
Choisir une classification ressemblerait à quelque chose comme:
for instance_scores in prob_arr :
predicted_classes = [cls for (cls, score) in instance_scores.iteritems() if score = max(instance_scores.values())]
Cela gère le cas où deux classes ont les mêmes scores. Vous pouvez obtenir un score en choisissant le premier dans cette liste, mais la façon dont vous gérez cela dépend de ce que vous classifiez.
Une fois que vous avez votre liste de classes prédites et une liste de classes attendues, vous pouvez utiliser un code tel que Torsten Marek 'pour créer le tableau de confusion et en calculer la précision.