Un avis peut parler à la fois de livraison et de prix ; un panier peut contenir du beurre et du parmesan. La classification multi-label prédit plusieurs étiquettes pour un même cas, au lieu d'en choisir une seule. On l'utilise pour étiqueter des documents, router des demandes ou suggérer plusieurs produits.
Un bibliothécaire qui range un livre : il ne choisit pas un seul rayon, il colle toutes les étiquettes pertinentes, « histoire », « cuisine », « Italie ».
Méthode de base, la relevance binaire : un classifieur par étiquette, entraîné indépendamment. Ce produit sera-t-il dans le panier, oui ou non ?
Dans une chaîne de classifieurs, chaque modèle reçoit aussi les réponses des modèles précédents. Le parmesan est prédit en sachant si la sauce tomate l'a été.
Chaque étiquette reçoit une probabilité. On retient celles qui dépassent un seuil, choisi selon le coût d'une étiquette oubliée ou superflue.
Un ticket par ligne, un produit par colonne (acheté ou non). Cinq produits servent d'étiquettes à prédire ensemble : beurre, sauce tomate, parmesan, chips, vin rouge. Les autres produits du panier servent d'indices.
Pour chaque ticket, une probabilité par produit ; au-delà de 25 %, le produit est suggéré. Sur le jeu d'exemple, la chaîne améliore surtout le parmesan : son F1 passe de 0,30 à 0,39, car il s'achète avec la sauce tomate.
Une moyenne globale cache les étiquettes rares, souvent mal prédites. On suit le F1 de chaque étiquette : il combine la part des achats réels anticipés et la part des suggestions justes.
Noms donnés pour Python (scikit-learn). En R, la relevance binaire s'écrit en une boucle ; le package utiml propose les méthodes avancées.
Relevance binaire pour des étiquettes indépendantes, chaîne quand elles se tiennent. L'ordre de la chaîne compte : on place d'abord les étiquettes qui aident à prédire les autres.
Le seuil de 50 % ne convient pas aux étiquettes rares : le parmesan ne dépasse presque jamais cette probabilité. On fixe un seuil par étiquette, sur un jeu de validation.
Régression logistique, Random Forest, SVM : chaque étiquette hérite de ses forces et de ses exigences. On commence simple, puis on remplace si le gain le justifie.
# Produits à suggérer en caisse : classification multi-label en R
tickets <- read.csv("tickets_caisse.csv")
paniers <- as.data.frame.matrix(table(tickets$id_ticket, tickets$produit))
paniers[paniers > 1] <- 1 # 1 ligne par ticket, 1 colonne par produit
etiquettes <- c("beurre", "sauce_tomate", "parmesan", "chips", "vin_rouge")
X <- paniers[, setdiff(names(paniers), etiquettes)]
set.seed(42)
idx <- sample(nrow(paniers), round(0.7 * nrow(paniers)))
f1 <- function(reel, pred) round(2 * sum(reel & pred) / (sum(reel) + sum(pred)), 2)
# Relevance binaire : une régression logistique par étiquette, seuil de 25 %
proba <- list()
for (e in etiquettes) {
d <- data.frame(X, cible = paniers[[e]])
m <- glm(cible ~ ., data = d[idx, ], family = binomial)
proba[[e]] <- predict(m, d[-idx, ], type = "response")
cat(e, "| F1 :", f1(paniers[[e]][-idx] == 1, proba[[e]] > 0.25), "\n")
}
# Chaîne : parmesan réappris avec sauce_tomate comme variable (prédite en test)
d <- data.frame(X, sauce_tomate = paniers$sauce_tomate, cible = paniers$parmesan)
m <- glm(cible ~ ., data = d[idx, ], family = binomial)
d_test <- d[-idx, ]
d_test$sauce_tomate <- as.integer(proba$sauce_tomate > 0.5)
cat("parmesan en chaîne | F1 :", f1(d_test$cible == 1, predict(m, d_test, type = "response") > 0.25), "\n")
# Produits à suggérer en caisse : classification multi-label en Python
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.multioutput import MultiOutputClassifier, ClassifierChain
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
tickets = pd.read_csv("tickets_caisse.csv")
paniers = pd.crosstab(tickets["id_ticket"], tickets["produit"]).clip(upper=1) # 1 ligne par ticket
# 5 étiquettes à prédire ensemble ; variables : le reste du panier
etiquettes = ["beurre", "sauce_tomate", "parmesan", "chips", "vin_rouge"]
X_train, X_test, Y_train, Y_test = train_test_split(paniers.drop(columns=etiquettes), paniers[etiquettes], test_size=0.3, random_state=42)
# Relevance binaire : un modèle indépendant par étiquette
separes = MultiOutputClassifier(LogisticRegression(max_iter=1000)).fit(X_train, Y_train)
proba_sep = pd.DataFrame([p[:, 1] for p in separes.predict_proba(X_test)], index=etiquettes).T
# Chaîne : parmesan est prédit après sauce_tomate et profite de cette information
chaine = ClassifierChain(LogisticRegression(max_iter=1000), order=[1, 2, 0, 3, 4]).fit(X_train, Y_train)
proba_ch = pd.DataFrame(chaine.predict_proba(X_test), columns=etiquettes)
# Seuil de 25 % : on suggère un produit dès qu'il a une chance sur quatre d'être acheté
for nom, proba in [("séparés", proba_sep), ("chaîne", proba_ch)]:
print(nom, "| F1 par étiquette :", f1_score(Y_test, proba > 0.25, average=None).round(2))
print("Suggestions pour le 1er ticket test :", proba_ch.iloc[0].round(2).to_dict())
En multiclasse, chaque cas appartient à une seule classe parmi plusieurs : un chiffre est un 3 ou un 8. En multi-label, un cas peut recevoir plusieurs étiquettes à la fois, ou aucune : un article peut parler de sport et de santé.
Une suite de classifieurs binaires, un par étiquette, où chacun reçoit en plus les prédictions des précédents. Elle capte les liens entre étiquettes, que la relevance binaire ignore. L'ordre des étiquettes dans la chaîne influence le résultat.
Plusieurs mesures coexistent. Le Hamming loss compte la part d'étiquettes mal prédites. L'exactitude par sous-ensemble exige que toutes les étiquettes soient justes, ce qui est très sévère. Le F1 par étiquette, puis sa moyenne, reste le plus parlant pour le métier.
La brique utilisée ici pour chaque étiquette : rapide, probabilités exploitables.
Voir la fiche → l'approche par règlesTrouve les produits achetés ensemble sans rien prédire. Plus simple pour une analyse de paniers.
Voir la fiche → l'autre façon de suggérerRecommande des produits proches de ceux déjà choisis, à partir de leurs caractéristiques.
Voir la fiche →Dataistudio forme les équipes au machine learning et à l'IA, sur des cas concrets.
Nous utilisons des cookies de mesure d'audience et de suivi publicitaire pour comprendre la fréquentation du site et l'efficacité de nos annonces. Rien n'est déposé sans votre accord. En savoir plus