En préparant une intervention pour mardi prochain, j’épluchais les résultats renvoyés pour un exercice, et j’ai eu un résultat assez étrange avec un modèle de classification. J’avais donné la même base cet automne à l’ensae, et j’avais donc près d’une trentaine d’autres modèles, pour comparer (disons plutôt que sur la même base de test, j’ai une trentaine de prévisions). Les observations noires sont celles obtenues cet automne (le trait correspond aux meilleurs AUC sur la base de test), et les observations rouges sont celles que j’ai obtenu pour l’intervention de mardi (là encore, le trait vertical correspond aux meilleurs modèles, au sens du AUC), sur une observation de la base de test,
Ce sont les probabilités prédites (mais j’ai enlevé l’échelle).
Pour presque toutes mes observations, les poids rouges sont bien au dessus des autres… Mais cela n’enlève en rien le fait que l’AUC obtenu (pour les deux modèles rouges) est très bon. C’est effectivement un résultat important (et connu) : le critère AUC (mais plus généralement la courbe ROC en entier) n’indique en rien si la valeur prédite est bonne, ou pas. Il nous dit juste si l’ordre obtenu est correct. Si les valeurs les plus importantes sont effectivement les valeurs pour lesquelles on a un 1, l’AUC sera très bon.
C’est ce qu’on peut observer sur le petit exemple ci-dessous. Considérons un modèle logistique simulé assez simple,
> n=1e3 > set.seed(1) > x1=rnorm(n) > x2=runif(n) > u=-3+x2+x1 > p=exp(u)/(1+exp(u)) > y=rbinom(n,prob=p,size=1) > library(ROCR) > df=data.frame(y,x1,x2) > mean(df$y) [1] 0.116 > reg=glm(y~.,data=df,family=binomial) > p=predict(reg,type="response") > mean(p) [1] 0.116 > pred1=prediction(p, df$y) > L=performance(pred1, "tpr", "fpr")
L’AUC est ici
> auc=performance(pred1, "auc")@y.values[[1]] > auc [1] 0.7681191
et la courbe ROC est la suivante,
> plot(unlist(L@x.values),unlist(L@y.values), + type="s",col="blue")
Supposons que l’on change la constante du modèle logistique,
> reg$coefficients[1]=0
Dans ce cas, notre prévision est assez mauvaise, car la probabilité moyenne prédite est ici
> u=reg$coefficients[1]+reg$coefficients[2]* + df$x1+reg$coefficients[3]*df$x2 > p=exp(u)/(1+exp(u)) > mean(p) [1] 0.6060676
(on est loin des 11,6% de 1 dans la base). Pourtant le AUC est bon
> pred1=prediction(p, df$y) > L=performance(pred1, "tpr", "fpr") > auc=performance(pred1, "auc")@y.values[[1]] > auc [1] 0.7681191
(c’est en fait la même valeur qu’auparavant, ce qui a du sens puisque la courbe ROC est identique)
> lines(unlist(L@x.values),unlist(L@y.values), + type="s",col="red")
Autrement dit, ces outils, classiquement utilisés pour juger la qualité d’un classifieur, ne permettent en aucun cas de dire que la probabilité prédite a du sens. Ces critères permettent juste de dire qu’on identifie assez bien les personnes qui ont le plus de chance d’avoir la réponse 1. Ce qui n’est pas si mal… mais c’est un autre problème que celui d’avoir une probabilité qui soit pertinente.