FP-Growth : pourquoi une règle à 90 % de confiance peut tromper

Confiance et fréquence de référence sur cent paniers synthétiques

Une règle d’association à 90 % de confiance peut être moins informative qu’une règle à 80 %. Tout dépend de la fréquence habituelle du produit recommandé. Si B apparaît déjà dans 95 % des paniers, le retrouver dans 90 % des paniers contenant A n’est pas un gain par rapport à cette référence.

Ce cas pratique complète le guide FP-Growth par un contre-exemple calculable à la main et reproductible en Python. Les cent paniers sont entièrement fabriqués pour expliquer les métriques : ils ne décrivent aucune boutique.

Cent paniers, quatre produits, deux règles

Effectif Nombre de paniers
A présent 10
B présent 95
A et B présents 9
C présent 10
D présent 10
C et D présents 8

Le CSV contient une ligne par panier, un identifiant et quatre colonnes booléennes. Un panier peut contenir plusieurs produits. Les lignes sans ces quatre produits sont conservées : elles représentent des paniers sans article de notre petit catalogue, et comptent dans le dénominateur de cent transactions.

Support, confiance, lift : faire les divisions

Le support de A→B correspond à la proportion de paniers contenant A et B : 9 / 100 = 0,09. La confiance conditionne sur A : 9 / 10 = 0,90. Le lift divise cette confiance par le support de B : 0,90 / 0,95 ≈ 0,9474. Ces définitions suivent la documentation des règles d’association de mlxtend.

Règle Support conjoint Confiance Fréquence du conséquent Lift
A→B 9 % 90 % B : 95 % 0,9474
C→D 8 % 80 % D : 10 % 8,0000

Avec A→B, le conséquent est légèrement moins fréquent en présence de l’antécédent que dans l’ensemble des paniers. Avec C→D, il est huit fois plus fréquent. Le classement par confiance privilégierait pourtant A→B. Le problème ne vient pas de FP-Growth : il vient de l’interprétation du critère choisi.

A vers B : confiance de 90 % pour une fréquence habituelle de 95 %. C vers D : 80 % pour une fréquence habituelle de 10 %.
Comparer la confiance à sa référence évite de confondre un produit fréquent et une association informative.

Ce que fait FP-Growth dans cet exemple

fpgrowth extrait les ensembles fréquents à partir des colonnes booléennes. Nous fixons un support minimal de 5 % et une taille maximale de deux produits pour garder une démonstration lisible. association_rules construit ensuite les règles dont la confiance atteint 80 %. Cinq règles passent ce filtre ; nous examinons deux règles définies dans le scénario. Consultez la référence de fpgrowth pour les paramètres.

Monter le support minimal à 9 % élimine C→D, dont le support conjoint n’est que de 8 %. Ce filtre peut être utile pour éviter des effectifs trop petits ; il peut aussi retirer une association intéressante pour un segment rare. Le seuil doit correspondre au problème et aux données disponibles.

Reproduire le calcul en Python

Télécharger les paniers CSV, le script et les quatre tests — ZIP gratuit. Exemple exécuté le 20 octobre 2026 avec Python 3.12.14 et mlxtend 0.25.0. Les versions directes sont fixées dans requirements.txt. Lancez python regles_paniers.py, puis python test_exemple.py.

"""100 paniers artificiels : une confiance élevée peut cacher un lift inférieur à 1."""
import json
from pathlib import Path
import pandas as pd
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from mlxtend.frequent_patterns import fpgrowth, association_rules

OUT = Path(__file__).resolve().parent


def paniers():
    presences = {
        "A": set(range(10)),
        "B": set(range(9)) | set(range(10, 96)),
        "C": set(range(40, 50)),
        "D": set(range(40, 48)) | {96, 97},
    }
    return pd.DataFrame({nom: [i in ids for i in range(100)]
                         for nom, ids in presences.items()}, dtype=bool)


def regles(df, support=.05):
    frequents = fpgrowth(df, min_support=support, use_colnames=True, max_len=2)
    return association_rules(frequents, num_itemsets=len(df),
                             metric="confidence", min_threshold=.8)


def extraire(rules, a, b):
    ligne = rules[(rules["antecedents"] == frozenset([a])) &
                  (rules["consequents"] == frozenset([b]))].iloc[0]
    return {"regle": a + " -> " + b,
            **{k: float(ligne[k]) for k in ["support", "confidence", "lift", "consequent support"]}}


def experience():
    df = paniers()
    df.to_csv(OUT / "paniers_synthetiques.csv", index_label="panier_id")
    rules = regles(df)
    retenues = [extraire(rules, "A", "B"), extraire(rules, "C", "D")]
    pd.DataFrame(retenues).to_csv(OUT / "deux_regles.csv", index=False)
    fig, ax = plt.subplots(figsize=(9, 4.8), layout="constrained")
    x = [0, 1]
    ax.bar([v-.18 for v in x], [r["confidence"] for r in retenues], .36,
           label="Confiance P(conséquent | antécédent)", color="#167c80")
    ax.bar([v+.18 for v in x], [r["consequent support"] for r in retenues], .36,
           label="Fréquence du conséquent dans tous les paniers", color="#e0a13b")
    ax.set(xticks=x, xticklabels=["A → B : lift ≈ 0,95", "C → D : lift = 8"],
           ylim=(0, 1.23), ylabel="Proportion", title="Une confiance de 90 % peut être moins informative que 80 %")
    ax.legend(loc="upper center", fontsize=9)
    fig.savefig(OUT / "figure.png", dpi=160)
    plt.close(fig)
    return {"paniers": len(df), "effectifs": {c: int(df[c].sum()) for c in df},
            "regles": retenues, "regles_generees": len(rules)}


if __name__ == "__main__":
    resultats = experience()
    (OUT / "resultats.json").write_text(json.dumps(resultats, indent=2), encoding="utf-8")
    print(json.dumps(resultats, indent=2))

Un lift élevé ne suffit toujours pas à recommander

Dans notre deuxième règle, dix paniers seulement contiennent C. Huit cooccurrences construites pour une démonstration ne suffisent pas à valider une politique de recommandation. Un lift de huit ne signifie pas que montrer D multipliera les ventes par huit : l’association observée ne mesure pas l’effet d’une intervention.

Avant de retenir une règle dans un vrai projet, examinez ses effectifs, sa stabilité sur une période ultérieure et sa pertinence métier. Une promotion commune, une catégorie de clients ou une contrainte de stock peuvent expliquer une cooccurrence. Les règles choisies après exploration de centaines de combinaisons demandent aussi une validation sur des données séparées.

Pour préparer cette validation, gardez la période récente à l’écart, calculez les règles sur la période ancienne et évaluez les mêmes règles sur la période récente. Ne changez pas simultanément la définition d’un panier, les produits inclus et le seuil : vous ne sauriez plus expliquer l’écart.

Un exercice pour prolonger le cas

Modifiez seulement les paniers contenant B : faites passer sa fréquence globale de 95 % à 90 %, en conservant neuf cooccurrences avec A et dix paniers A. Avant d’exécuter, prévoyez le lift. Il doit devenir exactement un. Puis expliquez pourquoi une confiance de 90 % reste insuffisante pour conclure à une association positive.

Pour travailler les fichiers d’entrée, utilisez les cinq exercices CSV corrigés. Le catalogue de cas pratiques propose d’autres exemples où un score isolé peut tromper.

About Salah YAHIAOUI

Salah YAHIAOUI publie sur The Pingouin des tutoriels Python et des décryptages sur l’intelligence artificielle. Les cas pratiques récents précisent leurs données, leurs tests et leurs limites. À propos, méthode éditoriale et contact.

View all posts by Salah YAHIAOUI →