03 — Écart de couverture taxonomique : académique vs Argumentum
EPIC #10355 — fallacy detection via Qwen 3.5/3.6 FT+PT. Ce notebook requalifie le livrable “paysage des datasets” (notebook 02) en posant explicitement la mesure que l’Epic demande : les taxonomies académiques (Logic 13 + MAFALDA L2 23 = 27 classes après déduplication de 9 doublons) couvrent ~3 % des feuilles et ~2 % des nœuds de la taxonomie Argumentum (1408 nœuds / 894 feuilles) — un écart de plus d’un ordre de grandeur (~33× sur les feuilles, ~52× sur les nœuds) qui définit l’ambition du fine-tuning.
Pourquoi ce requalification séparée : le notebook 02 catalogue les datasets accessibles (cible externe) ; celui-ci mesure la couverture interne de la grille de référence Argumentum par les étiquettes académiques. Les deux sont complémentaires et répondent à des questions différentes. L’alignement label-à-label (quel sophisme académique mappe sur quelle feuille Argumentum) est traité par scripts/fallacy_detection/align_academic_to_argumentum.py (PR #10368) ; l’exploration hiérarchique native par scripts/fallacy_detection/argumentum_taxonomy_explorer.py (PR #10376). Ce notebook consolide la mesure stratégique pour le cadrage de l’Epic.
Méthodologie
Compter les feuilles Argumentum (les sophismes identifiables, ≠ nœuds internes de hiérarchie) depuis le CSV repo-local argumentum_fallacies_taxonomy.csv.
Énumérer les étiquettes académiques des deux taxonomies de référence :
MAFALDA (Helwe et al. 2023, arXiv:2311.09761) : taxonomie hiérarchique 3 niveaux, 23 classes fines L2 sous Pathos/Logos/Ethos.
Mesurer l’écart : ratio académique / Argumentum, et le nombre de feuilles Argumentum “non couvertes” par construction (celles sans cognat académique direct). Chaque chiffre est calculé firsthand ci-dessous (pas cité).
import csvfrom pathlib import Pathfrom collections import Counter# --- 1. Charger la taxonomie Argumentum (repo-local, 1408 noeuds) ---# Robuste au cwd (papermill peut lancer depuis repo-root ou le dossier notebook) :# on cherche le CSV en essayant plusieurs ancres relatives._CANDIDATES = [ Path("MyIA.AI.Notebooks/SymbolicAI/Argument_Analysis/data/argumentum_fallacies_taxonomy.csv"), Path("../SymbolicAI/Argument_Analysis/data/argumentum_fallacies_taxonomy.csv"), Path("../../SymbolicAI/Argument_Analysis/data/argumentum_fallacies_taxonomy.csv"),]CSV_PATH =next((c for c in _CANDIDATES if c.is_file()), None)assert CSV_PATH isnotNone, "Taxonomie introuvable depuis cwd="+str(Path.cwd())withopen(CSV_PATH, encoding="utf-8-sig", newline="") as f: rows =list(csv.DictReader(f))total_nodes =len(rows)# Feuille = noeud dont le 'path' n'est prefix d'aucun autre path.all_paths = {r["path"].strip() for r in rows if r.get("path")}leaves = [r for r in rowsif r["path"].strip() and r["path"].strip() !="0"andnotany(p.startswith(r["path"].strip() +".") for p in all_pathsif p != r["path"].strip())]families = Counter(r["Famille"].strip() for r in leaves if r.get("Famille", "").strip())print("=== Taxonomie Argumentum (repo-local, firsthand) ===")print(f" noeuds total : {total_nodes}")print(f" feuilles : {len(leaves)} (sophismes identifiables)")print(f" familles : {len(families)}")print(" par famille :")for fam, n in families.most_common():print(f" {fam:<28}{n}")ratio =len(leaves) / total_nodesinternals = total_nodes -len(leaves)print(f"\n ratio feuilles/noeuds = {ratio:.1%} (le reste = {internals} noeuds internes de hierarchie)")
=== Taxonomie Argumentum (repo-local, firsthand) ===
noeuds total : 1408
feuilles : 894 (sophismes identifiables)
familles : 7
par famille :
Influence 285
Tricherie 255
Insuffisance 102
Obstruction 77
Erreur mathématique 61
Erreur de raisonnement 61
Abus de langage 53
ratio feuilles/noeuds = 63.5% (le reste = 514 noeuds internes de hierarchie)
Exercice 1 — Distribution de profondeur des feuilles
Contexte. La cellule ci-dessus compte les feuilles par le critère de préfixe (path d’une feuille n’est préfixe d’aucun autre). La hiérarchie Argumentum descend jusqu’à la profondeur 4 (depth_max4) — mais où vivent réellement les feuilles identifiables ?
Objectif. Construire la distribution des profondeurs des feuilles (nombre de segments du path, ex. "1.2.3" → 3), identifier la profondeur modale, et vérifier le recomptage contre la colonne depth du CSV.
# Exercice 1 — Distribution de profondeur# Etape 1 : pour chaque feuille de leaves, profondeur = nb de segments du path.# Indice : path.split('.') puis Counter sur les profondeurs.# Etape 2 : valider le recomptage contre la colonne depth du CSV (meme convention ?).# Etape 3 : identifier la profondeur modale et commenter.profondeurs =None# TODO etudiant
2. Les étiquettes académiques (encodées depuis les papiers, cités)
Les deux taxonomies de référence pour la détection de sophismes par deep learning. Les listes ci-dessous sont encodées depuis les papiers (pas depuis Argumentum), de sorte que la mesure de couverture soit honnête.
# --- Logic / LogicClimate (Jin et al. 2022) : 13 types ---# Source: arXiv:2202.13758, Table 1 / dataset causalNLP/logical-fallacyLOGIC_13 = ["Appeal to authority", "Appeal to emotion", "Bandwagon","False cause", "Slippery slope", "Ad hominem","Strawman", "False dilemma", "Equivocation","Fallacy of division", "Hasty generalization", "Begging the question","Red herring",]assertlen(LOGIC_13) ==13, f"Logic-13 attendu, got {len(LOGIC_13)}"# --- MAFALDA L2 (Helwe et al. 2023) : 23 classes fines ---# Source: arXiv:2311.09761, hiérarchie 3-niveaux (L0 binaire, L1 Pathos/Logos/Ethos, L2 fin)MAFALDA_L2 = [# Logos (raisonnement)"Faulty generalization", "False cause", "Fallacy of logic","Appeal to authority", "Circular reasoning", "Equivocation","Begging the question", "Strawman", "Red herring", "Slippery slope","Fallacy of credibility", "Ad hominem", "Tu quoque",# Pathos (émotion)"Appeal to emotion", "Appeal to popularity", "Appeal to values","Appeal to fear", "Appeal to pity", "Fallacy of relevance",# Ethos (crédibilité)"Fallacy of deficiency", "Guilt by association", "Genetic fallacy","Sunk cost fallacy",]assertlen(MAFALDA_L2) ==23, f"MAFALDA L2 attendu, got {len(MAFALDA_L2)}"academic_all =sorted(set(LOGIC_13) |set(MAFALDA_L2))overlap =sorted(set(LOGIC_13) &set(MAFALDA_L2))print(f"=== Étiquettes académiques (encodées depuis les papiers) ===")print(f" Logic-13 (Jin 2022) : {len(LOGIC_13)}")print(f" MAFALDA L2 (Helwe 2023) : {len(MAFALDA_L2)}")print(f" union (de-dupliquee) : {len(academic_all)}")print(f" intersection : {len(overlap)} -> {overlap}")print(f"\n union distincte = {len(LOGIC_13) +len(MAFALDA_L2) -len(overlap)} "f"(= {len(LOGIC_13)} + {len(MAFALDA_L2)} - {len(overlap)} doublons)")
=== Étiquettes académiques (encodées depuis les papiers) ===
Logic-13 (Jin 2022) : 13
MAFALDA L2 (Helwe 2023) : 23
union (de-dupliquee) : 27
intersection : 9 -> ['Ad hominem', 'Appeal to authority', 'Appeal to emotion', 'Begging the question', 'Equivocation', 'False cause', 'Red herring', 'Slippery slope', 'Strawman']
union distincte = 27 (= 13 + 23 - 9 doublons)
Exercice 2 — Encoder une troisième taxonomie académique (Walton)
Contexte. La cellule ci-dessus encode deux taxonomies académiques (Logic/LogicClimate : 13 types ; MAFALDA : 23 classes L2). La référence encyclopédique classique est la classification des sophismes informels de Walton (A Pragmatic Theory of Fallacy, University of Alabama Press, 1995) — dont voici un extrait de 16 entrées : ad hominem, ad baculum (appel à la force), ad populum (appel au peuple), ad verecundiam (appel à l’autorité), ad misericordiam (appel à la pitié), ad ignorantiam (appel à l’ignorance), straw man, slippery slope, false dilemma, hasty generalization, post hoc, begging the question (pétition de principe), equivocation, red herring (ignoratio elenchi), tu quoque, composition.
Objectif. Encoder ces 16 entrées en set Python (même convention que logic_labels / mafalda_labels : chaînes EN normalisées), puis mesurer l’effet sur l’union dédupliquée academic_all et sur l’écart.
# Exercice 2 — Taxonomie Walton (Walton 1995, extrait 16 entrees)# Etape 1 : encoder les 16 entrees listees dans le markdown ci-dessus.# Indice : meme convention que logic_labels / mafalda_labels (ensemble de chaines EN).# Etape 2 : recalculer l'union de-dupliquee academic_all | walton_labels.# Etape 3 : l'ecart avec Argumentum se resserre-t-il de maniere significative ?walton_labels =None# TODO etudiant
3. L’écart — deux ordres de grandeur
La mesure qui requalifie le paysage : la totalité des étiquettes fallacy de l’état de l’art académique (deux datasets de référence) représente ~3 % des feuilles Argumentum, ~2 % des nœuds (mesurés ensuite à 3,0 % et 1,9 %).
# --- 3. Mesure de l'ecart ---academic_count =len(academic_all) # union de-dupliqueeleaf_count =len(leaves)node_count = total_nodescov_leaves = academic_count / leaf_countcov_nodes = academic_count / node_countgap_leaves = leaf_count - academic_countorder_leaves =round(academic_count / leaf_count *100, 1)print("=== Ecart de couverture : academia vs Argumentum ===")print(f" etiquettes academiques (union) : {academic_count}")print(f" feuilles Argumentum : {leaf_count}")print(f" noeuds Argumentum : {node_count}")print(f"")print(f" couverture / feuilles : {academic_count}/{leaf_count} = {cov_leaves:.1%}")print(f" couverture / noeuds : {academic_count}/{node_count} = {cov_nodes:.1%}")print(f" feuilles NON couvertes (par cardinalite) : {gap_leaves} "f"({(1-cov_leaves):.1%} de la grille)")print(f"")print(f" ==> Ecart ~ {1/cov_leaves:.0f}x sur les feuilles "f"({order_leaves}% de couverture) = {(0if order_leaves>=10else1)} "f"ordre(s) de grandeur environ.")print(f" ==> Pour couvrir Argumentum, l'Epic doit etiqueter/projecter "f"{gap_leaves} feuilles au-dela des {academic_count} classes academiques.")
=== Ecart de couverture : academia vs Argumentum ===
etiquettes academiques (union) : 27
feuilles Argumentum : 894
noeuds Argumentum : 1408
couverture / feuilles : 27/894 = 3.0%
couverture / noeuds : 27/1408 = 1.9%
feuilles NON couvertes (par cardinalite) : 867 (97.0% de la grille)
==> Ecart ~ 33x sur les feuilles (3.0% de couverture) = 1 ordre(s) de grandeur environ.
==> Pour couvrir Argumentum, l'Epic doit etiqueter/projecter 867 feuilles au-dela des 27 classes academiques.
Lecture de la mesure. Les deux pourcentages racontent la même histoire sous deux angles volontairement inversés : la couverture des feuilles dit quelle fraction de la grille Argumentum l’academia sait nommer ; la couverture des nœuds rapporte le même numérateur (27) à une base plus large (1408, qui compte aussi les niveaux intermédiaires) — elle est donc mécaniquement plus basse (1,9 % contre 3,0 %), parce que le dénominateur est plus grand, ni plus ni moins. La finesse (le facteur ×N de la synthèse) est la bonne métrique pour le cadrage : elle dit combien de distinctions la grille du cours demande que l’état de l’art académique n’a jamais opérationnalisées.
Deux précautions de méthode méritent d’être lues dans le code plutôt qu’ignorées : l’union dédupliquée des étiquettes académiques (compter Logic + MAFALDA avec leurs doublons surestimerait l’effort collectif — l’union ne déduplique que les noms identiques — un même sophisme nommé différemment dans les deux corpus y compte deux fois), et la comparaison par cardinalité, pas par identité — la mesure compte des tailles de vocabulaires ; l’exercice 3 descend au niveau des noms, où l’appariement devient lui-même un problème (traduction EN/FR, synonymies).
Conséquence pratique pour l’Epic : l’academia ne couvre que ~3 % des feuilles (3,0 %) ; entraîner un classifieur multi-classes sur la grille complète à partir des seuls corpus publiés est structurellement impossible — d’où le choix d’une Phase 2 qui construit son propre dataset sur la grille Argumentum plutôt que de mouler la grille sur les corpus existants.
Exercice 3 — L’intersection, pas seulement l’union
Contexte. L’écart ci-dessus compare les cardinalités (union dédupliquée des labels académiques vs feuilles Argumentum). Une autre question, plus fine : quels sophismes les deux camps nomment tous les deux ? Le CSV Argumentum est bilingue (colonnes text_fr, Simple_name_en, text_en) — la comparaison directe des noms FR contre des labels EN académiques donne vide, et c’est précisément le piège.
Objectif. Extraire les noms EN des feuilles Argumentum, normaliser (casse, tirets/espaces), intersecter avec academic_all, puis interpréter la taille de l’intersection obtenue.
# Exercice 3 — Intersection Argumentum (noms EN) et academique# Etape 1 : extraire les noms EN des feuilles (colonnes Simple_name_en ou text_en).# Indice : la comparaison brute FR vs EN donne vide -- c'est le point pedagogique.# Etape 2 : normaliser (minuscules, tirets/espaces) puis intersecter avec academic_all.# Etape 3 : mesurer |intersection| et interpreter : pourquoi reste-t-elle petite ?communs =None# TODO etudiant
4. Ce que cet écart signifie pour l’Epic (cadrage stratégique)
L’écart n’est pas un défaut des datasets académiques — ils sont délibérément coarse (13-23 classes pour la reproductibilité expérimentale). Argumentum est délibérément fine (894 feuilles, profondeur 0→10) car c’est la grille d’un jeu : identifier précisément une feuille obscure dans un contexte complexe. Les conséquences pour l’Epic :
Le fine-tuning “savoir” (FT) ne peut pas se contenter des 36 classes académiques — il doit apprendre la structure hiérarchique Argumentum (la méthode « on part du général, on descend dans l’arbre »). Le générateur de traces SFT (argumentum_taxonomy_explorer.py) produit ces descentes réelles.
Le post-training “méthode” (PT) est précisément ce que l’écart rend nécessaire : le modèle doit raisonner la descente (catégorie → sous-catégorie → feuille), pas juste classer parmi 13 types. C’est le comportement que le plugin IS-Epita incarne actuellement.
La couverture label-à-label (quel cognat académique mappe sur quelle feuille) est mesurée séparément par le module d’alignement (align_academic_to_argumentum.py, PR #10368) — l’alignement direct (80-87%) est un point d’ancrage pour le FT, pas une couverture exhaustive.
Conclusion honnête : l’Epic vise un objectif ~40× plus fin que l’état de l’art académique. La valeur du SFT/PT Argumentum est précisément dans ce que l’état de l’art ne couvre pas — les 860+ feuilles sans cognat académique direct.
# --- 4. Synthese chiffree pour le cadrage ---import datetimeprint("=== Synthese : cadrage strategique de l'Epic ===")print(f" Etat de l'art academique : {academic_count} classes (Logic {len(LOGIC_13)} + MAFALDA {len(MAFALDA_L2)}, union dedup)")print(f" Grille Argumentum : {leaf_count} feuilles / {node_count} noeuds / {len(families)} familles")print(f" Facteur de finesse : ~{leaf_count/academic_count:.0f}x (feuilles) / ~{node_count/academic_count:.0f}x (noeuds)")print(f" Feuilles 'hors academie' : {gap_leaves} ({(1-cov_leaves):.1%}) = territoire propre au FT+PT Argumentum")print()print(f" Date du calcul : {datetime.date.today().isoformat()} (firsthand sur le CSV repo-local).")
=== Synthese : cadrage strategique de l'Epic ===
Etat de l'art academique : 27 classes (Logic 13 + MAFALDA 23, union dedup)
Grille Argumentum : 894 feuilles / 1408 noeuds / 7 familles
Facteur de finesse : ~33x (feuilles) / ~52x (noeuds)
Feuilles 'hors academie' : 867 (97.0%) = territoire propre au FT+PT Argumentum
Date du calcul : 2026-08-30 (firsthand sur le CSV repo-local).