Comment implémenter des métriques d'apprentissage automatique à partir de zéro en Python
Après avoir fait des prédictions, vous devez savoir si elles sont bonnes.
Il existe des mesures standards que nous pouvons utiliser pour résumer la qualité réelle d’un ensemble de prédictions.
Connaître la qualité d'un ensemble de prédictions vous permet de faire des estimations sur la qualité d'un modèle d'apprentissage automatique donné de votre problème,
Dans ce didacticiel, vous découvrirez comment implémenter quatre métriques d'évaluation de prédiction standard à partir de zéro en Python.
Après avoir lu ce tutoriel, vous saurez :
- Comment mettre en œuvre la précision de la classification.
- Comment mettre en œuvre et interpréter une matrice de confusion.
- Comment implémenter l'erreur absolue moyenne pour la régression.
- Comment implémenter l’erreur quadratique moyenne pour la régression.
Démarrez votre projet avec mon nouveau livre Machine Learning Algorithms From Scratch, comprenant des tutoriels pas à pas et les fichiers code source Python pour tous les exemples.
Commençons.
- Mise à jour d'août 2018 : testée et mise à jour pour fonctionner avec Python 3.6.
Description
Vous devez estimer la qualité d’un ensemble de prédictions lors de la formation d’un modèle d’apprentissage automatique.
Les mesures de performance telles que la précision de la classification et l'erreur quadratique moyenne peuvent vous donner une idée objective claire de la qualité d'un ensemble de prédictions et, par conséquent, de la qualité du modèle qui les a générées.
Ceci est important car cela vous permet de faire la différence et de choisir parmi :
- Différentes transformations des données utilisées pour entraîner le même modèle d'apprentissage automatique.
- Différents modèles d'apprentissage automatique formés sur les mêmes données.
- Différentes configurations pour un modèle d'apprentissage automatique entraîné sur les mêmes données.
En tant que telles, les mesures de performances sont un élément essentiel de la mise en œuvre d’algorithmes d’apprentissage automatique à partir de zéro.
Tutoriel
Ce tutoriel est divisé en 4 parties :
- 1. Exactitude des classifications.
- 2. Matrice de confusion.
- 3. Erreur absolue moyenne.
- 4. Erreur quadratique moyenne.
Ces étapes fourniront les bases dont vous avez besoin pour gérer l’évaluation des prédictions faites par les algorithmes d’apprentissage automatique.
1. Exactitude des classifications
Un moyen rapide d’évaluer un ensemble de prédictions sur un problème de classification consiste à utiliser la précision.
La précision de la classification est le rapport du nombre de prédictions correctes sur toutes les prédictions effectuées.
Elle est souvent présentée sous forme de pourcentage compris entre 0 % pour la pire précision possible et 100 % pour la meilleure précision possible.
accuracy = correct predictions / total predictions * 100
Nous pouvons implémenter cela dans une fonction qui prend les résultats attendus et les prédictions comme arguments.
Vous trouverez ci-dessous cette fonction nommée accuracy_metric() qui renvoie la précision de la classification en pourcentage. Notez que nous utilisons « == » pour comparer l'égalité réelle aux valeurs prédites. Cela nous permet de comparer des entiers ou des chaînes, deux principaux types de données que nous pouvons choisir d'utiliser lors du chargement des données de classification.
# Calculate accuracy percentage between two lists
def accuracy_metric(actual, predicted):
correct = 0
for i in range(len(actual)):
if actual[i] == predicted[i]:
correct += 1
return correct / float(len(actual)) * 100.0
Nous pouvons créer un petit ensemble de données pour tester cette fonction. Vous trouverez ci-dessous un ensemble de 10 valeurs entières réelles et prévues. Il y a deux erreurs dans l’ensemble des prédictions.
actual predicted
0 0
0 1
0 0
0 0
0 0
1 1
1 0
1 1
1 1
1 1
Vous trouverez ci-dessous un exemple complet avec cet ensemble de données pour tester la fonction accuracy_metric().
# Calculate accuracy percentage between two lists
def accuracy_metric(actual, predicted):
correct = 0
for i in range(len(actual)):
if actual[i] == predicted[i]:
correct += 1
return correct / float(len(actual)) * 100.0
# Test accuracy
actual = [0,0,0,0,0,1,1,1,1,1]
predicted = [0,1,0,0,0,1,0,1,1,1]
accuracy = accuracy_metric(actual, predicted)
print(accuracy)
L'exécution de cet exemple produit la précision attendue de 80 % ou 8/10.
80.0
La précision est une bonne mesure à utiliser lorsque vous disposez d'un petit nombre de valeurs de classe, telles que 2, également appelée problème de classification binaire.
La précision commence à perdre de son sens lorsque vous avez plus de valeurs de classe et que vous devrez peut-être examiner les résultats sous un angle différent, comme une matrice de confusion.
2. Matrice de confusion
Une matrice de confusion fournit une synthèse de toutes les prédictions faites par rapport aux valeurs réelles attendues.
Les résultats sont présentés dans une matrice avec des comptes dans chaque cellule. Les décomptes des valeurs réelles de classe sont résumés horizontalement, tandis que les décomptes de prédictions pour chaque valeur de classe sont présentés verticalement.
Un ensemble parfait de prédictions est représenté par une ligne diagonale allant du coin supérieur gauche au coin inférieur droit de la matrice.
L’intérêt d’une matrice de confusion pour les problèmes de classification est que vous pouvez clairement voir quelles prédictions étaient fausses et le type d’erreur commise.
Créons une fonction pour calculer une matrice de confusion.
Nous pouvons commencer par définir la fonction permettant de calculer la matrice de confusion à partir d'une liste de valeurs de classe réelles et d'une liste de prédictions.
La fonction est répertoriée ci-dessous et s'appelle confusion_matrix(). Il dresse d’abord une liste de toutes les valeurs de classe uniques et attribue à chaque valeur de classe un entier ou un index unique dans la matrice de confusion.
La matrice de confusion est toujours carrée, le nombre de valeurs de classe indiquant le nombre de lignes et de colonnes requises.
Ici, le premier index de la matrice est la ligne des valeurs réelles et le second est la colonne des valeurs prédites. Une fois la matrice de confusion carrée créée et initialisée à zéro dans chaque cellule, il s'agit de parcourir toutes les prédictions et d'incrémenter le compte dans chaque cellule.
La fonction renvoie deux objets. Le premier est l'ensemble des valeurs de classe uniques, afin qu'elles puissent être affichées lorsque la matrice de confusion est dessinée. La seconde est la matrice de confusion elle-même avec les décomptes dans chaque cellule.
# calculate a confusion matrix
def confusion_matrix(actual, predicted):
unique = set(actual)
matrix = [list() for x in range(len(unique))]
for i in range(len(unique)):
matrix[i] = [0 for x in range(len(unique))]
lookup = dict()
for i, value in enumerate(unique):
lookup[value] = i
for i in range(len(actual)):
x = lookup[actual[i]]
y = lookup[predicted[i]]
matrix[y][x] += 1
return unique, matrix
Rendons cela concret avec un exemple.
Vous trouverez ci-dessous un autre ensemble de données artificiel, cette fois avec 3 erreurs.
actual predicted
0 0
0 1
0 1
0 0
0 0
1 1
1 0
1 1
1 1
1 1
Nous pouvons calculer et imprimer la matrice de confusion pour cet ensemble de données comme suit :
# Example of Calculating a Confusion Matrix
# calculate a confusion matrix
def confusion_matrix(actual, predicted):
unique = set(actual)
matrix = [list() for x in range(len(unique))]
for i in range(len(unique)):
matrix[i] = [0 for x in range(len(unique))]
lookup = dict()
for i, value in enumerate(unique):
lookup[value] = i
for i in range(len(actual)):
x = lookup[actual[i]]
y = lookup[predicted[i]]
matrix[y][x] += 1
return unique, matrix
# Test confusion matrix with integers
actual = [0,0,0,0,0,1,1,1,1,1]
predicted = [0,1,1,0,0,1,0,1,1,1]
unique, matrix = confusion_matrix(actual, predicted)
print(unique)
print(matrix)
L’exécution de l’exemple produit le résultat ci-dessous. L'exemple imprime d'abord la liste des valeurs uniques puis la matrice de confusion.
{0, 1}
[[3, 1], [2, 4]]
Il est difficile d’interpréter les résultats de cette façon. Cela aiderait si nous pouvions afficher la matrice comme prévu avec des lignes et des colonnes.
Ci-dessous se trouve une fonction pour afficher correctement la matrice.
La fonction est nommée print_confusion_matrix(). Il nomme les colonnes P pour Prédictions et les lignes A pour Réel. Chaque colonne et ligne porte le nom de la valeur de classe à laquelle elle correspond.
La matrice est présentée en supposant que chaque étiquette de classe soit un caractère unique ou un entier à un chiffre et que les décomptes soient également des entiers à un chiffre. Vous pouvez l'étendre pour gérer de grandes étiquettes de classe ou des nombres de prédictions à titre d'exercice.
# pretty print a confusion matrix
def print_confusion_matrix(unique, matrix):
print('(A)' + ' '.join(str(x) for x in unique))
print('(P)---')
for i, x in enumerate(unique):
print("%s| %s" % (x, ' '.join(str(x) for x in matrix[i])))
Nous pouvons rassembler toutes les fonctions et afficher une matrice de confusion lisible par l’homme.
# Example of Calculating and Displaying a Pretty Confusion Matrix
# calculate a confusion matrix
def confusion_matrix(actual, predicted):
unique = set(actual)
matrix = [list() for x in range(len(unique))]
for i in range(len(unique)):
matrix[i] = [0 for x in range(len(unique))]
lookup = dict()
for i, value in enumerate(unique):
lookup[value] = i
for i in range(len(actual)):
x = lookup[actual[i]]
y = lookup[predicted[i]]
matrix[y][x] += 1
return unique, matrix
# pretty print a confusion matrix
def print_confusion_matrix(unique, matrix):
print('(A)' + ' '.join(str(x) for x in unique))
print('(P)---')
for i, x in enumerate(unique):
print("%s| %s" % (x, ' '.join(str(x) for x in matrix[i])))
# Test confusion matrix with integers
actual = [0,0,0,0,0,1,1,1,1,1]
predicted = [0,1,1,0,0,1,0,1,1,1]
unique, matrix = confusion_matrix(actual, predicted)
print_confusion_matrix(unique, matrix)
L’exécution de l’exemple produit le résultat ci-dessous. Nous pouvons voir les étiquettes de classe 0 et 1 en haut et en bas. En regardant la diagonale de la matrice du haut à gauche vers le bas à droite, nous pouvons voir que 3 prédictions de 0 étaient correctes et 4 prédictions de 1 étaient correctes.
En regardant dans les autres cellules, on peut voir 2 + 1 ou 3 erreurs de prédiction. Nous pouvons voir que 2 prédictions ont été faites comme un 1 qui étaient en fait une valeur de classe 0. Et nous pouvons voir 1 prédiction qui était un 0 qui était en fait un 1.
(A)0 1
(P)---
0| 3 1
1| 2 4
Une matrice de confusion est toujours une bonne idée à utiliser en plus de la précision de la classification pour faciliter l'interprétation des prédictions.
3. Erreur absolue moyenne
Les problèmes de régression sont ceux où une valeur réelle est prédite.
Une mesure facile à considérer est l’erreur dans les valeurs prédites par rapport aux valeurs attendues.
L’erreur moyenne absolue ou MAE en abrégé est une bonne première mesure d’erreur à utiliser.
Il est calculé comme la moyenne des valeurs d'erreur absolues, où « absolu » signifie « rendu positif » afin qu'elles puissent être additionnées.
MAE = sum( abs(predicted_i - actual_i) ) / total predictions
Vous trouverez ci-dessous une fonction nommée mae_metric() qui implémente cette métrique. Comme ci-dessus, il attend une liste de valeurs de résultats réels et une liste de prédictions. Nous utilisons la fonction Python intégrée abs() pour calculer les valeurs d'erreur absolues qui sont additionnées.
def mae_metric(actual, predicted):
sum_error = 0.0
for i in range(len(actual)):
sum_error += abs(predicted[i] - actual[i])
Nous pouvons créer un petit ensemble de données de régression pour tester cette fonction.
actual predicted
0.1 0.11
0.2 0.19
0.3 0.29
0.4 0.41
0.5 0.5
Une seule prédiction (0,5) est correcte, alors que toutes les autres prédictions sont fausses de 0,01. Par conséquent, nous nous attendons à ce que l’erreur absolue moyenne (ou l’erreur positive moyenne) de ces prédictions soit un peu inférieure à 0,01.
Vous trouverez ci-dessous un exemple qui teste la fonction mae_metric() avec l'ensemble de données artificiel.
# Calculate mean absolute error
def mae_metric(actual, predicted):
sum_error = 0.0
for i in range(len(actual)):
sum_error += abs(predicted[i] - actual[i])
return sum_error / float(len(actual))
# Test RMSE
actual = [0.1, 0.2, 0.3, 0.4, 0.5]
predicted = [0.11, 0.19, 0.29, 0.41, 0.5]
mae = mae_metric(actual, predicted)
print(mae)
L’exécution de cet exemple imprime la sortie ci-dessous. Nous pouvons voir que comme prévu, le MAE était d'environ 0,008, une petite valeur légèrement inférieure à 0,01.
0.007999999999999993
4. Erreur quadratique moyenne
Une autre méthode courante pour calculer l'erreur dans un ensemble de prédictions de régression consiste à utiliser l'erreur quadratique moyenne.
Abrégée en RMSE, la métrique est parfois appelée Mean Squared Error ou MSE, supprimant la partie racine du calcul et du nom.
Le RMSE est calculé comme la racine carrée de la moyenne des carrés des différences entre les résultats réels et les prévisions.
La mise au carré de chaque erreur force les valeurs à être positives et la racine carrée de l'erreur quadratique moyenne renvoie la métrique d'erreur aux unités d'origine à des fins de comparaison.
RMSE = sqrt( sum( (predicted_i - actual_i)^2 ) / total predictions)
Vous trouverez ci-dessous une implémentation de ceci dans une fonction nommée rmse_metric(). Il utilise la fonction sqrt() du module mathématique et utilise l'opérateur ** pour élever l'erreur à la puissance 2.
# Calculate root mean squared error
def rmse_metric(actual, predicted):
sum_error = 0.0
for i in range(len(actual)):
prediction_error = predicted[i] - actual[i]
sum_error += (prediction_error ** 2)
mean_error = sum_error / float(len(actual))
return sqrt(mean_error)
Nous pouvons tester cette métrique sur le même ensemble de données utilisé pour tester le calcul de l'erreur absolue moyenne ci-dessus.
Vous trouverez ci-dessous un exemple complet. Encore une fois, nous nous attendrions à ce qu’une valeur d’erreur soit généralement proche de 0,01.
from math import sqrt
# Calculate root mean squared error
def rmse_metric(actual, predicted):
sum_error = 0.0
for i in range(len(actual)):
prediction_error = predicted[i] - actual[i]
sum_error += (prediction_error ** 2)
mean_error = sum_error / float(len(actual))
return sqrt(mean_error)
# Test RMSE
actual = [0.1, 0.2, 0.3, 0.4, 0.5]
predicted = [0.11, 0.19, 0.29, 0.41, 0.5]
rmse = rmse_metric(actual, predicted)
print(rmse)
En exécutant l’exemple, nous voyons les résultats ci-dessous. Le résultat est légèrement supérieur à 0,0089.
Les valeurs RMSE sont toujours légèrement supérieures aux valeurs MSE, ce qui devient plus prononcé à mesure que les erreurs de prédiction augmentent. Il s’agit d’un avantage de l’utilisation du RMSE par rapport au MSE dans la mesure où cela pénalise les erreurs plus importantes avec des scores moins bons.
0.00894427190999915
Rallonges
Vous n'avez vu qu'un petit échantillon des mesures de performances les plus utilisées.
Il existe de nombreuses autres mesures de performances dont vous pourriez avoir besoin.
Vous trouverez ci-dessous une liste de 5 mesures de performances supplémentaires que vous souhaiterez peut-être implémenter pour étendre ce didacticiel.
- Précision pour la classification.
- Rappel pour classement.
- F1 pour le classement.
- Zone sous la courbe ROC ou AUC pour la classification.
- Qualité de l'ajustement ou R^2 (R au carré) pour la régression.
Avez-vous mis en œuvre l'une de ces extensions ?
Partagez vos expériences dans les commentaires ci-dessous.
Revoir
Dans ce didacticiel, vous avez découvert comment implémenter des métriques de performances de prédiction d'algorithmes à partir de zéro dans Python.
Concrètement, vous avez appris :
- Comment mettre en œuvre et interpréter l’exactitude de la classification.
- Comment implémenter et interpréter la matrice de confusion pour les problèmes de classification.
- Comment implémenter et interpréter l’erreur absolue moyenne pour la régression.
- Comment implémenter et interpréter l’erreur quadratique moyenne pour la régression.
Avez-vous des questions ?
Posez vos questions dans les commentaires et je ferai de mon mieux pour y répondre.