Module 8 — Métriques : rappel, NDCG, couverture, diversité
Le module 1 posait déjà la conclusion : la RMSE ne mesure pas la qualité d'un moteur de recommandation. Ce module explique pourquoi, puis construit rigoureusement les métriques de classement qui la remplacent. Chacune éclaire un aspect différent, et un moteur mature les suit toutes en parallèle.
Précision, rappel et F1 à k
L'apprenant regarde en moyenne les premières recommandations. Toutes les métriques sérieuses se calculent donc à k, souvent .
Pour un apprenant , soient les cours recommandés et les cours réellement pertinents — définis comme ceux qu'il a effectivement suivis dans la période de test (voir découpage temporel du module 10). On définit :
La précision à 10 répond à « parmi les 10 cours recommandés, combien étaient bons ? ». Le rappel à 10 répond à « parmi les cours pertinents pour cet apprenant, combien ont été récupérés dans les 10 premiers ? ». Les deux se calculent par apprenant puis se moyennent sur l'ensemble de test.
Un piège subtil : la précision décroît mécaniquement avec (on ajoute des candidats moins sûrs), tandis que le rappel croît. Comparer précision@5 à rappel@50 n'a pas de sens ; comparer précision@10 entre deux modèles en a.
La F1@k combine les deux :
En pratique, on regarde toujours les deux séparément : améliorer F1 en perdant du rappel sur les apprenants qui ont peu d'interactions est souvent un mauvais compromis.
NDCG à la main
La précision et le rappel ignorent l'ordre à l'intérieur du top-k. Une recommandation qui met un cours pertinent en première position a exactement la même précision@10 qu'une recommandation qui le met en dixième — alors que l'apprenant clique sur la première position bien plus souvent. Le NDCG (Normalized Discounted Cumulative Gain) corrige ce défaut.
Pour un classement, on définit le gain cumulé actualisé :
où est la pertinence de l'objet en position (souvent 0 ou 1 pour la rétroaction implicite, jusqu'à 5 pour l'explicite). Le dénominateur est le facteur d'atténuation qui pénalise les positions basses. On divise ensuite par le DCG du classement idéal (les objets pertinents placés dans l'ordre de leur pertinence) pour obtenir un nombre entre 0 et 1 :
Prenons un exemple à la main pour avec des pertinences binaires. L'apprenant a réellement suivi trois cours (pertinents), et la recommandation les place en positions 1, 3 et 5 :
- gains bruts : 1, 0, 1, 0, 1
- gains actualisés : , , , ,
- DCG@5 = 1,000 + 0 + 0,500 + 0 + 0,387 ≈ 1,887
- classement idéal : pertinents en 1, 2, 3 ; IDCG@5 = 1,000 + 0,631 + 0,500 = 2,131
- NDCG@5 = 1,887 / 2,131 ≈ 0,886
Cette valeur de 0,886 dit qu'à pertinence égale on aurait pu faire à peine mieux. Si les trois pertinents étaient en 5, 8, 10, le NDCG serait autour de 0,5 : très différent, alors que rappel@10 vaudrait toujours 1.
import numpy as np
def dcg(pertinences):
return np.sum((2 ** pertinences - 1) / np.log2(np.arange(len(pertinences)) + 2))
def ndcg_a_k(recommandes, pertinents, k=10):
rel = np.array([1 if c in pertinents else 0 for c in recommandes[:k]])
ideal = np.sort(rel)[::-1]
idcg = dcg(ideal)
return dcg(rel) / idcg if idcg > 0 else 0.0
MAP et Hit Rate
La MAP@k (Mean Average Precision) est une alternative au NDCG qui suppose des pertinences binaires. Pour un apprenant, on calcule la précision à chaque position où figure un pertinent, on moyenne, on obtient l'AP. On moyenne les AP sur tous les apprenants pour obtenir la MAP. Elle est équivalente au NDCG en cas binaire à un facteur près et souvent préférée pour sa simplicité.
Le Hit Rate@k est encore plus simple : la fraction d'apprenants pour lesquels au moins un cours pertinent apparaît dans le top-k. C'est la métrique la plus lisible en réunion produit, celle qui répond directement à « quelle fraction de nos apprenants trouvent quelque chose d'utile en page d'accueil ? ». Elle est plus grossière que le NDCG mais souvent la première à évoluer quand on change un modèle.
Couverture du catalogue
Toutes les métriques précédentes ne regardent qu'un apprenant à la fois. La couverture regarde le moteur dans son ensemble : quelle fraction du catalogue est-elle effectivement recommandée à au moins un apprenant sur une période ?
Un moteur qui recommande toujours les 20 mêmes cours atteint 100 % de précision sur ces 20 cours mais 4 % de couverture — et laisse 96 % du catalogue en pure perte. C'est le signal principal qu'un modèle est victime du biais de popularité du module 9, ou d'une bulle de filtre du module 4. La couverture est le premier indicateur qu'un moteur de qualité doit tenir au-dessus d'un seuil (50 % est un objectif raisonnable sur un catalogue mature).
Diversité et nouveauté
La diversité intra-liste mesure à quel point les cours recommandés à un même apprenant se ressemblent entre eux. On la calcule comme un moins la similarité cosinus moyenne entre paires :
Une liste diverse évite d'enfermer dans un thème et améliore l'expérience globale sans forcément améliorer le clic immédiat. C'est un contrepoids explicite au filtrage par contenu, souvent utilisé dans l'algorithme MMR (Maximal Marginal Relevance) qui prend le meilleur candidat qui ne ressemble pas trop à ceux déjà sélectionnés.
La nouveauté mesure la surprise : à quel point les cours recommandés sont-ils moins populaires que ce que suit l'apprenant en général ? Elle se quantifie souvent par l'entropie de la distribution de popularité des recommandations, ou par l'écart entre la popularité moyenne des recommandations et celle de tout le catalogue. Un moteur trop nouveau produit du bruit ; un moteur pas assez nouveau enferme dans la queue courte. Le bon équilibre se règle par A/B test.
Pourquoi la RMSE trompeuse
La RMSE mesure l'erreur moyenne sur les cellules observées. Or les cellules observées sont dominées par des couples où l'apprenant a choisi de noter le cours — un ensemble non aléatoire, biaisé vers les cours qu'il aimait. Le modèle qui minimise la RMSE devient bon à prédire les notes des couples déjà biaisés positifs, et le top-k qu'il recommande peut être arbitrairement mauvais.
L'illustration classique : un modèle qui prédit la note moyenne de chaque cours obtient une RMSE médiocre mais un rappel@10 souvent supérieur à un modèle plus sophistiqué mal réglé. Ce n'est pas une pathologie, c'est le signe que la RMSE ne mesure pas la bonne chose.
Un moteur mature suit une métrique de classement (NDCG@10 ou MAP@10) comme cible d'entraînement, une métrique de couverture comme garde-fou, une métrique de diversité comme signal produit. Se limiter à la première produit un moteur qui optimise ce qu'il montre déjà, sans jamais élargir. C'est le piège documenté dans les publications de YouTube et Spotify depuis 2019.
En résumé
- Précision et rappel à k répondent à des questions différentes : qualité de ce qui est montré, part du pertinent capté.
- Le NDCG@k intègre l'ordre à l'intérieur du top-k avec un facteur ; c'est la métrique dominante pour l'entraînement.
- La couverture du catalogue trahit les biais de popularité et de filtrage ; à surveiller au-dessus de 50 % sur un catalogue mature.
- La diversité intra-liste et la nouveauté équilibrent l'expérience globale ; elles se règlent par A/B test.
- La RMSE est trompeuse parce que les cellules observées sont biaisées ; elle ne juge pas la qualité d'un classement.
Module suivant : la rétroaction implicite et les biais de position qui la contaminent.