Cet article est le premier de notre série consacrée aux métriques de classification, dans le cadre de notre formation : Evaluer la performance des modèles de Machine Learning et de Deep Learning.
Dans cet article nous introduisons trois concepts clés pour la compréhension des métriques de classification : les modèles standard, parfait et non-informatif.
Un modèle de classification est un modèle prédictif qui fournit des probabilités. Tout au long de cette série nous prendrons l’exemple d’un modèle de prédiction des résiliations, en utilisant le jeu de données Telco Customer Churn [1]. Ces données permettent de prédire les résiliations des clients d’une agence de télécommunication fictive en fonction de leurs offres, de leurs tarifs et des autres informations associées aux contrats.
Nous nous intéresserons essentiellement dans cette série à la classification à deux classes ou classification binaire (binary classification). C’est le cas le plus fréquent lorsqu’on prédit des événements : fraude, achat, maladie… qui soit surviennent soit ne surviennent pas. Mais il existe aussi des modèles de classification multi-classes (multi-class classification) que nous évoquerons. Ces modèles interviennent en situation de choix multiples (qu’allez-vous acheter en magasin?) ou d’événements à issues multiples (quels sont vos risques si vous êtes renversé par une voiture?).
Dans nos données de résiliation, on parlera d’individus positifs pour les clients qui ont résilié (churn en anglais) et d’individus négatifs pour les clients qui n’ont pas résilié (no churn). Concrètement, on connaît pour chaque client une variable Y qui vaut soit 1 (résiliation) soit 0 (pas de résiliation). Et l’on dispose d’un modèle qui calcule pour chaque client la probabilité P(Y=1).
Résumons notre cadre d’étude sur les données Telco :
Figure 1. Prédictions de probabilités par un modèle de classification.
Ce modèle peut être de trois types : algorithme de Machine Learning, modèle expert, Homme. Il utilise les données de chaque client pour prédire sa probabilité de résiliation P(Y=1), qui peut ensuite être comparée à la réalité.
Modèle standard – Performance intermédiaire
Pour illustrer ce qu’est un modèle standard, nous entraînons un algorithme de Machine Learning (XGBoost) sur les données Telco. Nous obtenons un modèle permettant de prédire une probabilité de résiliation pour chaque client. Visualisons la distribution de ces probabilités :
Figure 2. Probabilités prédites par un modèle de Machine Learning.
1 point = 1 client, coloré en orange s’il a effectivement résilié (churn), en bleu s’il n’a pas résilié (no churn). L’abscisse (en %) correspond à la probabilité prédite par le modèle. L’ordonnée n’a pas de signification et sert uniquement à espacer les points pour mieux les visualiser.
Cette distribution présente les deux caractéristiques d’un modèle standard :
- Les distributions des individus négatifs (en bleu) et des individus positifs (en orange) se superposent en partie : le modèle ne parvient pas à séparer complètement les négatifs des positifs. Il fera donc des erreurs.
- Plus la probabilité est grande, plus la proportion de positifs augmente par rapport aux négatifs. Le modèle a donc en partie “trié” les positifs des négatifs : il a intégré des informations utiles qui le rendent performant (même s’il n’est pas parfait).
Modèle standard
\begin{equation*} \Leftrightarrow \end{equation*}
Les positifs ont en moyenne une probabilité strictement supérieure aux négatifs.
Le code d’entraînement du modèle standard sur les données Telco est disponible en annexe de l’article.
Modèle parfait – Performance maximale
A présent, imaginons un modèle parfait (perfect model). Nous utilisons le terme “imaginer” à dessein, car le modèle parfait est généralement impossible à atteindre.
Visualisons des exemples de distribution de probabilité de modèles parfaits :
Figure 3. Exemples de modèles parfaits.
C’est la capacité à séparer les positifs des négatifs qui définit le modèle parfait.
La caractéristique de ce modèle est qu’il sépare parfaitement les probabilités des positifs de celles des négatifs.
Modèle parfait
\begin{equation*} \Leftrightarrow \end{equation*}
Les positifs ont toujours une probabilité strictement supérieure aux négatifs.
Pourquoi le modèle parfait est-il en général inaccessible ? Précisons :
- Considérons deux individus “jumeaux” ayant exactement les mêmes caractéristiques (âge, ancienneté, contrat…). Le modèle leur prédit nécessairement la même probabilité; or ils peuvent malgré tout avoir des comportements différents : l’un peut résilier et l’autre pas. On a donc deux individus positifs et négatifs qui ont la même probabilité.
- D’une manière générale, l’information dont dispose un modèle est toujours partielle et il ne peut prédire parfaitement les comportements. Il est donc normal que les probabilités prédites ne séparent pas parfaitement les individus positifs et négatifs.
Même s’il est inaccessible, le modèle parfait est une notion essentielle car il conduit à la performance maximale pour chaque métrique de classification, ce que nous verrons dans la suite de cette série.
Modèle non-informatif – Performance minimale
La notion la plus complexe à appréhender est celle de modèle non-informatif. Ce modèle est appelé de plusieurs façons, en français comme en anglais : modèle non-informatif (no skill model / no skill classifier), modèle aléatoire (random model / random classifier), ou encore modèle de performance minimale (baseline model / baseline classifier).
Visualisons des distributions de probabilité de modèles non-informatifs :
Figure 4. Exemples de modèles non-informatifs.
Le modèle est obtenu en attribuant aléatoirement des probabilités (à gauche selon une loi uniforme, à droite selon une loi normale bornée).
Ces modèles ont en commun d’avoir la même répartition spatiale des individus positifs et négatifs sur le graphe : leur distribution de probabilité est la même.
Modèle non-informatif
\begin{equation*} \Leftrightarrow \end{equation*}
Les positifs ont la même distribution de probabilités que les négatifs.
Pour fabriquer artificiellement un modèle non-informatif, c’est simple : il suffit de choisir un générateur de probabilité et de l’utiliser aléatoirement pour tous les individus, qu’ils soient positifs ou négatifs.
# Pour une prédiction avec une loi uniforme :
probas_pred = np.random.rand(len(y_test))
En pratique, ce modèle n’a pas d’intérêt : puisqu’il ne sépare pas les individus positifs des négatifs, il n’apporte aucune information utile. Mais comme le modèle parfait, il est une notion essentielle car il conduit à la performance minimale pour chaque métrique de classification, ce que nous verrons dans la suite de cette série.
Point important : en pratique, il est possible de descendre en dessous de la performance minimale d’un modèle (par exemple on peut obtenir un modèle avec un AUC ROC inférieur à 50% ou avec un AUC Precision Recall inférieur au taux de positifs). Cela peut alors signifier deux choses :
- Soit vous avez un modèle très peu robuste qui exploite si mal l’information qu’il fait des prédictions pires que le hasard.
- Soit vous avez une erreur de code. Cela peut arriver avec sklearn : la méthode predict_proba renvoie une array avec une colonne par classe, mais celles-ci ne sont pas forcément dans l’ordre que vous attendez. Vous avez donc probablement inversé vos probabilités. La solution est d’utiliser l’attribut du modèle model.classes_ pour vous assurer de bien récupérer la probabilité P(Y=1) :
model_output = model.predict_proba( validation_data )
probas_pred = model_output[:, np.where(model.classes_ == 1 )[0]]
Conclusion
Résumons la différence entre les trois types de modèles prédictifs décrits :
Figure 5. Synthèse des différences entre modèle non-informatif, modèle standard et modèle parfait.
La quasi-totalité des modèles de Machine Learning sont des modèles standards, qui ont une performance intermédiaire : ils apportent une réelle plus-value mais font quand même des erreurs.
Nous verrons par la suite une grande diversité de métriques pour mesurer la performance des modèles prédictifs : precision, recall, sensitivity, specificity, accuracy, F1-score… Bien assimiler ce qu’est un modèle parfait et ce qu’est un modèle non-informatif est crucial pour comprendre ces métriques, car ces deux modèles définissent respectivement la valeur maximale et la valeur minimale de chaque métrique. Ils définissent donc des valeurs de référence auxquelles on peut comparer la performance d’un modèle prédictif.
Le deuxième article de cette série est dédié à la matrice de confusion. Nous y verrons comment convertir des probabilités en prédictions, et identifier les erreurs d’un modèle.
- 2 jours
- 950€
- 2 jours
- 1 200€
Annexe : Entraînement d’un modèle de machine learning sous python
Le code suivant permet d’entraîner le modèle de machine learning utilisé comme exemple de modèle standard. Pour cet exemple, nous utilisons un modèle XGBoost.
Afin de rester concis dans le code présenté, nous avons omis les scripts de rééchantillonnage des données et d’optimisation des hyperparamètres. Nous conservons ici les hyperparamètres par défaut de XGBoost, aussi vous obtiendrez des résultats un peu moins performants que ceux présentés dans cette série d’articles.
# data est un DataFrame pandas contenant les données Telco
# Définition des colonnes numériques et catégorielles
numerical_col = (
data.select_dtypes(exclude=object).columns.drop(["Churn"]).to_list()
)
categorical_col = data.select_dtypes(include=object).columns.to_list()
# Préparation des données
from sklearn.model_selection import train_test_split
# Séparation de la variable à prédire
X, y = data.drop(columns=["Churn"]), data["Churn"]
# Séparation train test
X_train, X_test, y_train, y_test = train_test_split(X, y)
# Imputing et Scaling des données
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import RobustScaler, OrdinalEncoder
from sklearn.pipeline import make_pipeline
from sklearn.compose import make_column_transformer
# Pipeline des variables numériques
num_imputer = SimpleImputer(strategy="constant", fill_value=-100)
num_scaler = RobustScaler()
num_pipeline = make_pipeline(num_imputer, num_scaler)
# Pipeline des variables catégorielles
cat_imputer = SimpleImputer(strategy="constant", fill_value="missing")
cat_encoder = OrdinalEncoder(
handle_unknown="use_encoded_value", unknown_value=-1
)
cat_pipeline = make_pipeline(cat_imputer, cat_encoder)
# Combinaison des pipelines numériques et catégorielles
# numerical_col est la liste des variables numériques
# categorical_col est la liste des variables catégorielles
preprocessing_pipeline = make_column_transformer(
(num_pipeline, numerical_col), (cat_pipeline, categorical_col)
)
# Ajout d'un modèle prédictif (XGBoost) à la pipeline
from xgboost import XGBClassifier
model = XGBClassifier()
prediction_pipeline = make_pipeline(preprocessing_pipeline, model)
# Entrainement du modèle sur les données Train
prediction_pipeline.fit(X_train, y_train)
# Prédiction des probabilités de chaque classe (0 ou 1)
# sur les données Test
model_output = prediction_pipeline.predict_proba(X_test)
# Récupération des probabilités de la classe positive (1)
probas_pred = model_output[ : , np.where(model.classes_ == 1 )[0]]
# Une autre option est de récupérer directement les labels prédits par
# le modèle avec la fonction predict(). Attention dans ce cas le choix d'un
# seuil de classification est implicite. La valeur utilisée par scikit-learn
# est de 50%.
label_pred = prediction_pipeline.predict(X_test)
Références :
- « Telco Customer Churn ». https://kaggle.com/blastchar/telco-customer-churn