# Parameters
nb_name = "ICT-35d-HumorTypologyBreakdown-SAE-Python"
layers = {"early": 4, "mid": 12, "late": 19}
n_layers_model = 24
n_draws = 2048
seed = 42
n_boot = 4000Statut épistémique — Sans verdict à ce jour : aucune ligne de la matrice de dissociations ne concerne ce notebook ; son statut épistémique sera porté par la matrice le cas échéant.
ICT-35d – HumorTypologyBreakdown-SAE : le verdict survit-il à la forme de la blague ? (#14035, tranche finale)
ICT-35b a mesuré le différentiel humour→unfun des 30 paires prises ensemble à la couche 12/24 (INCONCLUSIVE), ICT-35c a montré que le verdict survit à la profondeur (early/mid/late, INCONCLUSIVE stable, top-5 disjoints). Restaient deux critères du protocole #14035 :
- critère 4 de la phase 1 — stabilité inter-formes : pun, sociale/non-topical, topical. Un signal noyé dans l’agrégat de 30 paires hétérogènes peut exister dans une seule forme — c’est l’objection que cette tranche lève (ou confirme) ;
- critère d’acceptance — effets rapportés avec IC et taille d’effet, pas seulement des seuils binaires.
Cette tranche mesure les mêmes 6 traces (3 couches × trained/control, aucun run GPU nouveau) en les découpant par type selon une annotation figée avant toute mesure par type. Elle énonce ensuite ce que le protocole implique pour la phase 2 interventionnelle, et porte le verdict final de l’issue.
# -*- coding: utf-8 -*-
# Setup. Reproduction du corpus humour (meme geste que ICT-35b/35c) :
# les cellules code [26..33] de la section echelle du banc consolide
# (GameTheory-18c, absorption #14032) sont
# executees dans un namespace isole. La reproduction exige OPENROUTER_API_KEY
# dans l'environnement (verifiee par les cellules endpoint de GT-24b ; aucune
# n'appelle l'API ici).
from collections import Counter
from pathlib import Path
import sys
import numpy as np
import pandas as pd
ROOT = Path.cwd()
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from ict.humor_pairs import build_pairs, load_corpus_dur, validate_pairs
from ict.humor_typology import (
BORDERLINE, MIN_PER_TYPE, PAIR_TYPES, TYPES,
bootstrap_mean_ic, feature_z, final_verdict, per_pair_deltas,
split_by_type, validate_typology, zone_matrices,
)
from ict.humor_pairs import measure_humor_differential
corpus = load_corpus_dur()
pairs = build_pairs(corpus)
validate_pairs(pairs)
validate_typology(pairs)
by_type = split_by_type(pairs)
print(f"{len(pairs)} paires validées ; annotation par type :")
for t in TYPES:
markes = sum(1 for p in by_type[t] if p["id"] in BORDERLINE)
print(f" {t:9s} {len(by_type[t]):2d} paires (dont {markes} cas frontière)")
print(f"plancher déclaré par type : {MIN_PER_TYPE} paires")
apercu = pd.DataFrame([
{"id": p["id"], "type": PAIR_TYPES[p["id"]],
"frontiere": "*" if p["id"] in BORDERLINE else "",
"setup": p["setup"][:52]}
for p in pairs
])
apercu[setup] Catégories : ['humour_reussi', 'rire_sans_recadrage', 'recadrage_sans_rire', 'offensif_compris_non_partage', 'rien']
[setup] LLM endpoint : https://openrouter.ai/api/v1
[setup] LLM model : anthropic/claude-haiku-4.5
[fetch] cache hit : argumentum_scenarii.csv
[fetch] upstream master @d68170c521 : docs(corpus): #458 liste de relecture native (38) -- 2 ouvertes, 6 confirmations
[parse] 167 scénarios Argumentum chargés
[parse] catégories : {'histoire': 17, 'mythologie': 27, 'relation intime': 36, 'vie professionnelle': 30, 'vie personnelle': 25, 'pop culture': 18, 'politique': 14}
[parse] sous-catégories (21) : {'antiquité': 6, 'moyen-âge et temps modernes': 6, '20e et 21e siècle': 5, 'contes': 10, 'religions': 11, 'littérature': 6, 'drague et séduction': 9, 'vie de couple': 16, 'romance': 11, 'interactions professionnelles': 14, 'relations au travail': 8, 'gestion et administration': 9, 'Bandes dessinées': 5, 'cinéma & télévision': 7, 'science': 6, 'gouvernance': 4, 'manoeuvres et collusion': 6, 'campagne': 4, 'famille et enfance': 8, 'voisins et amis': 11, 'loisirs et espace public': 5}
[parse] 167 instances retenues (champs FR)
[parse] exemple : id=1.1.1 titre='La mère de César et Cléopâtre'
baratineur='Aurelia Cotta, mère de César' -> piocheur='Jules César'
[label] distribution après annotation manuelle : {'rien': 46, 'recadrage_sans_rire': 27, 'humour_reussi': 55, 'rire_sans_recadrage': 25, 'offensif_compris_non_partage': 14}
[corpus] total : 120 instances
[corpus] distribution par label : {'rire_sans_recadrage': 14, 'recadrage_sans_rire': 13, 'rien': 38, 'humour_reussi': 48, 'offensif_compris_non_partage': 7}
[corpus] distribution par source : {'ArgumentumGames/Argumentum': 60, 'blague-manuelle': 30, 'declaration-factuelle': 20, 'edge-case-curated': 10}
[corpus] humour_reussi : 48 instances OK
[corpus] rire_sans_recadrage : 14 instances OK
[corpus] recadrage_sans_rire : 13 instances OK
[corpus] offensif_compris_non_partage : 7 instances OK
[corpus] rien : 38 instances OK
30 paires validées ; annotation par type :
pun 13 paires (dont 2 cas frontière)
topical 12 paires (dont 1 cas frontière)
sociale 5 paires (dont 2 cas frontière)
plancher déclaré par type : 5 paires
| id | type | frontiere | setup | |
|---|---|---|---|---|
| 0 | joke-p02 | pun | Pourquoi les développeurs confondent Halloween... | |
| 1 | joke-p03 | pun | Il y a 10 types de personnes au monde : | |
| 2 | joke-p04 | topical | Un SQL entre dans un bar, voit deux tables et ... | |
| 3 | joke-p05 | sociale | Combien d'ingénieurs faut-il pour changer une ... | |
| 4 | joke-p06 | pun | Je suis tombé amoureuse d'une fonction quadrat... | |
| 5 | joke-p07 | topical | Un null et un undefined entrent dans un bar. | |
| 6 | joke-p08 | pun | Je voulais te raconter une blague sur UDP... | |
| 7 | joke-p09 | sociale | Le père Noël a-t-il déjà eu un problème de pil... | |
| 8 | joke-p10 | pun | * | Pourquoi le café est-il si bon au travail ? |
| 9 | joke-p11 | pun | J'ai essayé d'écrire une blague sur les corout... | |
| 10 | joke-p12 | topical | Docker, Kubernetes, Prometheus, Grafana. On m'... | |
| 11 | joke-p13 | sociale | * | Mon compilateur et moi on a une relation stabl... |
| 12 | joke-p14 | pun | J'ai un ami palindrome. | |
| 13 | joke-p15 | topical | Les regex sont comme des licornes : | |
| 14 | joke-p16 | sociale | * | Un physicien, un biologiste et un chimiste voi... |
| 15 | joke-p18 | topical | Si Dieu existe, il est Objective-C : | |
| 16 | joke-p19 | pun | Le temps est une illusion. | |
| 17 | joke-p20 | pun | * | Un photon entre dans un bar et commande une bi... |
| 18 | joke-p21 | pun | J'ai une blague sur les matrices, mais | |
| 19 | joke-p22 | topical | * | Un chat roux dans une salle de serveurs est da... |
| 20 | joke-p23 | sociale | Pourquoi les plongeurs plongent-ils toujours e... | |
| 21 | joke-p24 | topical | Le HTML n'est pas un langage de programmation. | |
| 22 | joke-p25 | topical | Si vous pensez que personne ne s'intéresse à v... | |
| 23 | joke-p26 | topical | Comment debug-on un avion ? | |
| 24 | joke-p27 | pun | Mieux vaut avoir un git pull que | |
| 25 | joke-p28 | topical | Mon chat a appris Python. | |
| 26 | joke-p29 | topical | Les submodules Git, c'est comme les voisins : | |
| 27 | joke-p30 | topical | Il était une fois un UTF-8 qui ne savait pas o... | |
| 28 | edge-04 | pun | 'I told my wife she was drawing her eyebrows t... | |
| 29 | edge-05 | pun | 'I'm on a whiskey diet. |
Protocole par type – statistiques pré-registrées inchangées, inference additionnelle déclarée
Ce qui est rejoué tel quel (pré-registre c.5743321902, null corrigé c.5743498870) : sur chaque sous-ensemble de paires, la mesure measure_humor_differential — delta_pair vs null croisé (σ brasse les unfun entre paires, ≥2048 tirages), delta_ctrl (contrôle de distance d’édition), z features par flip de signe intra-paire. Le verdict FEATURE_CANDIDATE exige delta_pair > p99(null) ET delta_pair > 1.5·delta_ctrl ET ≥3 features |z|>3 du même côté.
Ce qui est ajouté (critère d’acceptance IC + taille d’effet) : IC bootstrap percentile (4000 tirages, seed 42) sur le delta_pair par paire, d de Cohen uni-varié, et un contrôle familial — la distribution du max |z| sous le même null, pour qu’un |z|>3 isolé ne puisse plus être invoqué face à 32 768 tests simultanés. Aucun nouveau critère de détection n’est inventé : les add-ons déclarent la précision des jambes existantes.
Figsée avant mesure par type : l’annotation (PAIR_TYPES), les seeds, les seuils. La phase 2 interventionnelle, elle, ne peut démarrer que « pour les seules features candidates pré-enregistrées » — la lecture 6 énonce ce que les jambes mesurées impliquent.
# Chargement des 6 traces (aucune capture nouvelle : celles d'ICT-35b/35c,
# manifestes re-verifies) + matrices de zones par paire pour les jambes d'inference.
zones_all = {}
for tag, layer in layers.items():
for variant in ("trained", "control"):
p = ROOT / "traces" / f"humor35b_qwen35-2b-base_layer{layer}of{n_layers_model}_{variant}.npz"
z = zone_matrices(p, pairs)
zones_all[(tag, variant)] = z
d_sae = z["humour"].shape[1]
print(f"{tag:5s} L{layer:2d}/{n_layers_model} {variant:7s}: zones {z['humour'].shape}, d_sae={d_sae}")early L 4/24 trained: zones (30, 32768), d_sae=32768
early L 4/24 control: zones (30, 32768), d_sae=32768
mid L12/24 trained: zones (30, 32768), d_sae=32768
mid L12/24 control: zones (30, 32768), d_sae=32768
late L19/24 trained: zones (30, 32768), d_sae=32768
late L19/24 control: zones (30, 32768), d_sae=32768
Lecture 2 – Les mêmes traces, relues par paire
Les six traces sont celles committées par 35b (mid) et 35c (early/late), manifestes re-vérifiés à l’ouverture (modèle, SAE, couche, seed). Les matrices de zones (humour, unfun, ctrl_edit, une ligne par paire, vecteur moyen des activations SAE top-50 de la zone punchline) sont le substrat de toutes les jambes qui suivent : découpage par type = sélection de lignes, aucune recomputation cachée.
# Mesure pre-registree par type x couche x variant (18 jambes).
# Meme fonction que 35b/35c, appliquee au sous-ensemble de paires du type.
rows = []
legs = []
for tag, layer in layers.items():
for variant in ("trained", "control"):
p = ROOT / "traces" / f"humor35b_qwen35-2b-base_layer{layer}of{n_layers_model}_{variant}.npz"
for t in TYPES:
subset = by_type[t]
r = measure_humor_differential(p, subset, n_draws=n_draws, seed=seed)
leg = f"L{layer}/{t}/{variant}"
legs.append({"leg": leg, **{k: r[k] for k in ("verdict",)}})
rows.append({
"jambe": leg, "n": len(subset),
"delta_pair": round(r["delta_pair"], 1),
"delta_ctrl": round(r["delta_ctrl"], 1),
"ratio_vs_ctrl": round(r["ratio_vs_ctrl"], 3),
"n_|z|>3": r["n_features_over3"],
"verdict": r["verdict"],
})
tbl = pd.DataFrame(rows)
tbl| jambe | n | delta_pair | delta_ctrl | ratio_vs_ctrl | n_|z|>3 | verdict | |
|---|---|---|---|---|---|---|---|
| 0 | L4/pun/trained | 13 | 18.8 | 20.1 | 0.936 | 0 | INCONCLUSIVE |
| 1 | L4/topical/trained | 12 | 18.6 | 20.0 | 0.929 | 0 | INCONCLUSIVE |
| 2 | L4/sociale/trained | 5 | 20.0 | 21.4 | 0.933 | 0 | INCONCLUSIVE |
| 3 | L4/pun/control | 13 | 19.4 | 19.3 | 1.006 | 0 | INCONCLUSIVE |
| 4 | L4/topical/control | 12 | 19.4 | 19.1 | 1.016 | 0 | INCONCLUSIVE |
| 5 | L4/sociale/control | 5 | 19.1 | 18.8 | 1.017 | 0 | INCONCLUSIVE |
| 6 | L12/pun/trained | 13 | 28.7 | 29.9 | 0.959 | 0 | INCONCLUSIVE |
| 7 | L12/topical/trained | 12 | 28.5 | 30.0 | 0.950 | 0 | INCONCLUSIVE |
| 8 | L12/sociale/trained | 5 | 30.3 | 32.1 | 0.942 | 0 | INCONCLUSIVE |
| 9 | L12/pun/control | 13 | 22.4 | 22.9 | 0.981 | 0 | INCONCLUSIVE |
| 10 | L12/topical/control | 12 | 22.3 | 22.4 | 0.997 | 0 | INCONCLUSIVE |
| 11 | L12/sociale/control | 5 | 21.2 | 22.0 | 0.962 | 0 | INCONCLUSIVE |
| 12 | L19/pun/trained | 13 | 93.9 | 97.9 | 0.959 | 0 | INCONCLUSIVE |
| 13 | L19/topical/trained | 12 | 92.5 | 97.8 | 0.946 | 0 | INCONCLUSIVE |
| 14 | L19/sociale/trained | 5 | 98.2 | 106.3 | 0.924 | 0 | INCONCLUSIVE |
| 15 | L19/pun/control | 13 | 70.9 | 70.1 | 1.011 | 0 | INCONCLUSIVE |
| 16 | L19/topical/control | 12 | 70.0 | 68.0 | 1.029 | 0 | INCONCLUSIVE |
| 17 | L19/sociale/control | 5 | 67.5 | 65.9 | 1.025 | 0 | INCONCLUSIVE |
Lecture 3 – Le tableau des 18 jambes
À lire jambe par jambe : le ratio_vs_ctrl (proche de 1 = le différentiel humour→unfun n’excède pas une simple édition de texte de même distance), le compte de features |z|>3 (le seuil pré-registré de détection), et le verdict agrégé. La comparaison avec l’agrégat de 30 paires (35b : ratio 0.97, 0 feature |z|>3 ; 35c : stable aux trois profondeurs) est le point de référence — une jambe par type ne « révèle » un signal que si elle s’en écarte davantage que sa propre incertitude.
# IC bootstrap + d de Cohen sur le delta_pair PAR PAIRE, par type x couche (trained).
rows_ic = []
for tag, layer in layers.items():
z = zones_all[(tag, "trained")]
for t in TYPES:
idx = [i for i, p in enumerate(pairs) if PAIR_TYPES[p["id"]] == t]
d = per_pair_deltas({"humour": z["humour"][idx], "unfun": z["unfun"][idx],
"ctrl_edit": z["ctrl_edit"][idx]})
ic_p = bootstrap_mean_ic(d["delta_pair"], n_boot=n_boot, seed=seed)
ic_c = bootstrap_mean_ic(d["delta_ctrl"], n_boot=n_boot, seed=seed)
rows_ic.append({
"jambe": f"L{layer}/{t}", "n": len(idx),
"delta_pair_moy": round(ic_p["mean"], 1),
"IC95": f"[{ic_p['ic_lo']:.0f}, {ic_p['ic_hi']:.0f}]",
"d_cohen": round(ic_p["cohens_d"], 2),
"ctrl_moy": round(ic_c["mean"], 1),
"ctrl_IC95": f"[{ic_c['ic_lo']:.0f}, {ic_c['ic_hi']:.0f}]",
})
tbl_ic = pd.DataFrame(rows_ic)
tbl_ic| jambe | n | delta_pair_moy | IC95 | d_cohen | ctrl_moy | ctrl_IC95 | |
|---|---|---|---|---|---|---|---|
| 0 | L4/pun | 13 | 17.6 | [15, 20] | 3.95 | 17.9 | [16, 20] |
| 1 | L4/topical | 12 | 19.8 | [18, 22] | 4.90 | 21.3 | [19, 23] |
| 2 | L4/sociale | 5 | 17.6 | [17, 18] | 15.84 | 18.8 | [18, 20] |
| 3 | L12/pun | 13 | 26.3 | [23, 30] | 3.97 | 26.4 | [23, 29] |
| 4 | L12/topical | 12 | 29.6 | [27, 32] | 5.87 | 31.1 | [29, 33] |
| 5 | L12/sociale | 5 | 27.5 | [27, 28] | 28.86 | 28.3 | [27, 30] |
| 6 | L19/pun | 13 | 86.2 | [76, 96] | 4.40 | 87.2 | [77, 96] |
| 7 | L19/topical | 12 | 95.5 | [86, 104] | 5.88 | 104.2 | [98, 110] |
| 8 | L19/sociale | 5 | 92.7 | [87, 100] | 10.66 | 94.0 | [87, 101] |
Lecture 4 – Les intervalles parlent avant les seuils
Le critère d’acceptance demandait des effets « avec IC et taille d’effet » : les voici. Deux lectures structurent l’interprétation. (1) IC vs contrôle : si l’IC95 du delta_pair recouvre largement celui du contrôle de distance d’édition, la « mesure » ne distingue pas supprimer l’humour de réécrire la fin de la phrase — aucun détecteur ne peut vivre là. (2) d de Cohen par effectif : avec n = 5 (sociale), un d même élevé porte un IC si large qu’aucune feature candidate n’y serait pré-enregistrable honnêtement. Les largeurs se lisent comme la puissance déclarée de chaque jambe, pas comme un échec.
# Controle familial : max |z| observe vs distribution du max |z| sous le null
# (flip intra-paire) -- par type x couche, jambe trained.
rows_fw = []
for tag, layer in layers.items():
z = zones_all[(tag, "trained")]
for t in TYPES:
idx = [i for i, p in enumerate(pairs) if PAIR_TYPES[p["id"]] == t]
r = feature_z({"humour": z["humour"][idx], "unfun": z["unfun"][idx],
"ctrl_edit": z["ctrl_edit"][idx]}, n_draws=n_draws, seed=seed)
rows_fw.append({
"jambe": f"L{layer}/{t}", "max|z| observe": round(r["observed_max_abs_z"], 2),
"max|z| null p95": round(r["null_max_p95"], 2),
"p_familial": round(r["familywise_p"], 3),
"n_|z|>3 brut": r["n_over3"],
})
tbl_fw = pd.DataFrame(rows_fw)
tbl_fw| jambe | max|z| observe | max|z| null p95 | p_familial | n_|z|>3 brut | |
|---|---|---|---|---|---|
| 0 | L4/pun | 2.31 | 2.53 | 0.371 | 0 |
| 1 | L4/topical | 2.40 | 2.64 | 0.269 | 0 |
| 2 | L4/sociale | 2.08 | 2.16 | 0.234 | 0 |
| 3 | L12/pun | 2.10 | 2.57 | 0.808 | 0 |
| 4 | L12/topical | 2.41 | 2.52 | 0.138 | 0 |
| 5 | L12/sociale | 2.11 | 2.19 | 0.116 | 0 |
| 6 | L19/pun | 2.46 | 2.58 | 0.125 | 0 |
| 7 | L19/topical | 2.33 | 2.58 | 0.337 | 0 |
| 8 | L19/sociale | 1.78 | 2.09 | 0.939 | 0 |
Lecture 5 – Ce que la multiplicité fait aux seuils isolés
Avec 32 768 features testées simultanément, attendre quelques |z| > 3 par jambe est le comportement du hasard, pas un signal : c’est exactement ce que la colonne max|z| null p95 quantifie — le maximum qu’un null pur produit en moyenne 5 fois sur 100. Un signal réel devrait dépasser ce plafond ; un compte n_|z|>3 brut non nul sous un p_familial élevé est du bruit de multiplicité, et se lit comme tel. Ce contrôle n’était pas dans le pré-registre de 35b : il est ajouté ici comme déclaration de précision (le critère de détection |z|>3 reste inchangé), pour que le verdict final ne repose pas sur des seuils que la multiplicité affaiblit.
# Phase 2 : enonce structurel -- le protocole ne peut pas demarrer.
# "Pour les seules features candidates pre-enregistrees" (body #14035) :
# le compte de jambes FEATURE_CANDIDATE sur les 18 mesurees decide.
n_cand = sum(1 for l in legs if l["verdict"] == "FEATURE_CANDIDATE")
print(f"Jambes mesurées : {len(legs)} (3 types x 3 couches x trained/control)")
print(f"Jambes FEATURE_CANDIDATE : {n_cand}")
print(f"Agrégat 30 paires (35b/35c, mesures committées) : 0 candidate aux 3 profondeurs,")
print(f"top-5 disjoints entre couches et trained/control (Jaccard 0.00).")
if n_cand == 0:
print("=> AUCUNE feature candidate pré-enregistrée n'existe : la phase 2")
print(" interventionnelle (clamp/ablation vs clamp aléatoire) n'a pas")
print(" d'objet. La rouvrir exigerait une nouvelle phase 1, pas un bypass.")
else:
print("=> Des candidates par type existent : la phase 2 reprend sur elles")Jambes mesurées : 18 (3 types x 3 couches x trained/control)
Jambes FEATURE_CANDIDATE : 0
Agrégat 30 paires (35b/35c, mesures committées) : 0 candidate aux 3 profondeurs,
top-5 disjoints entre couches et trained/control (Jaccard 0.00).
=> AUCUNE feature candidate pré-enregistrée n'existe : la phase 2
interventionnelle (clamp/ablation vs clamp aléatoire) n'a pas
d'objet. La rouvrir exigerait une nouvelle phase 1, pas un bypass.
Lecture 6 – Pourquoi la phase 2 est vide, et ce que ce n’est pas
Le protocole de l’issue reserve la phase interventionnelle aux « seules features candidates pré-enregistrées » — un garde-fou explicite contre l’ablation à la carte jusqu’à trouver quelque chose. Les jambes agrégées (35b : 0 feature |z|>3 ; 35c : 1 sur toute l’expérience, top-5 disjoints) et les 18 jambes par type mesurées ci-dessus bornent le même constat. Une phase 2 lancée quand même n’ablaterait pas « l’humour » : elle ablaterait des features choisies après coup, et son résultat serait non interprétable — c’est précisément la confusion explication/mécanisme que le titre de l’issue interdit.
Ceci n’est pas l’affirmation que le modèle « n’a pas » de représentation de l’humour : c’est la constatation mesurée qu’avec ce SAE, ce modèle, ce banc et cette puissance (n=30 agrégé, n=13/12/5 par type), aucune feature stable n’a survécu au protocole. La différence entre les deux énoncés est le statut épistémique de la série.
# Verdict final de l'issue #14035 (enumeration fermee du body).
verdict = final_verdict(legs)
print("Verdict final :", verdict["verdict"])
print(f" jambes observationnelles : {verdict['n_legs']} (par type, cette tranche)")
print(f" jambes candidate : {verdict['n_candidate_legs']}")
print()
print("Bornes apportées par les tranches précédentes (mesures committées) :")
print(" ICT-35 (pilote HLS) : INCONCLUSIVE borné, baseline lexicale")
print(" ICT-35b (SAE, agrégat) : INCONCLUSIVE, 0 feature |z|>3, contrôle clôt")
print(" ICT-35c (3 profondeurs) : INCONCLUSIVE stable, top-5 disjoints")Verdict final : AUCUNE_FEATURE_STABLE
jambes observationnelles : 18 (par type, cette tranche)
jambes candidate : 0
Bornes apportées par les tranches précédentes (mesures committées) :
ICT-35 (pilote HLS) : INCONCLUSIVE borné, baseline lexicale
ICT-35b (SAE, agrégat) : INCONCLUSIVE, 0 feature |z|>3, contrôle clôt
ICT-35c (3 profondeurs) : INCONCLUSIVE stable, top-5 disjoints
Lecture 7 – Le verdict, ses limites, et ce qu’il ferme
AUCUNE_FEATURE_STABLE : dans l’énumération fermée du protocole (CAUSAL_SELECTIF / CORRELATION_SEULE / AUCUNE_FEATURE_STABLE / INCONCLUSIVE), c’est l’énoncé le plus fort que les données portent — plus fort que INCONCLUSIVE, car les jambes ne sont pas restées indécises : elles ont borné (différentiel sous le bruit permuté, ratio au contrôle ≈ 1, rien ne survit au contrôle familial, aucune stabilité inter-formes ni inter-profondeurs).
Limites, déclarées : (1) locale au couple Qwen3.5-2B-Base × SAE-Res-W32K-L0.50, au banc GT-24b et aux 30 paires — rien ne transpose à un autre modèle, SAE ou corpus ; (2) la jambe sociale (n=5) est déclarée sous-alimentée par construction ; (3) absence de preuve n’est pas preuve d’absence — un SAE plus large, un banc plus équilibré ou une couche non échantillonnée pourraient porter un signal que ce protocole ne pouvait pas voir. Ce que le verdict ferme : l’hypothèse d’une feature SAE stable de l’humour lisible dans ce substrat-ci, et avec elle la possibilité d’une phase 2 honnête sur ces traces.
# EXERCICE 1 -- Robustesse de l'annotation : reclasser les 5 cas frontiere.
# Les paires BORDERLINE ont deux mecanismes reels ; le classement retenu est
# arbitraire. Reclasser joke-p10 et joke-p13 en 'sociale', joke-p16 en
# 'topical', puis rejouer la cellule de mesure par type : le tableau des
# verdicts change-t-il ? (Reponse attendue : non -- les effectifs bougent de
# +/-1, les ratio restent dans le bruit. A verifier, pas a presumer.)
# TODO etudiant : construire PAIR_TYPES_ALT et comparer les 18 verdicts.
print("Exercice a completer : robustesse de l'annotation aux 5 cas frontiere")Exercice a completer : robustesse de l'annotation aux 5 cas frontiere
# EXERCICE 2 -- IC a 90 % : que gagne-t-on en precision ?
# Les IC95 de la lecture 4 sont larges parce que n est petit. Reprendre
# bootstrap_mean_ic avec alpha=0.10 sur la jambe L12/pun : l'IC se resserre,
# mais recouvre-t-il toujours le controle de distance d'edition ?
# TODO etudiant : rejouer la cellule IC avec alpha=0.10 et commenter.
print("Exercice a completer : IC a 90 pourcent sur la jambe L12/pun")Exercice a completer : IC a 90 pourcent sur la jambe L12/pun
# EXERCICE 3 -- Seuil |z|>2.5 : le compte brut monte-t-il, le controle familial cede-t-il ?
# Baisser le seuil de detection augmente mecaniquement le compte brut. Reprendre
# feature_z et compter les |z|>2.5 par jambe : si le max|z| observe reste sous
# le max|z| null p95, le surplus de comptes est-il autre chose que du bruit ?
# TODO etudiant : compter n_|z|>2.5 sur 3 jambes et confronter au null p95.
print("Exercice a completer : seuil |z|>2.5 vs controle familial")Exercice a completer : seuil |z|>2.5 vs controle familial
Conclusion et voir aussi
Cette tranche finale de #14035 complète le triptyque : le pilote a posé la baseline lexicale, la tranche 1 a mesuré l’agrégat sur SAE, la tranche 2 a éprouvé la profondeur, celle-ci éprouve la forme et rapporte les effets avec leur incertitude. Le verdict final AUCUNE_FEATURE_STABLE est l’énoncé le plus fort que les données portent, et il ferme la phase 1 honnêtement : la phase 2 n’a pas d’objet sur ces traces, et toute reprise passe par une nouvelle phase 1 (SAE plus large, banc équilibré), pas par un contournement du garde-fou « candidates pré-enregistrées ».
- ICT-35-HumorCausalProbe-Pilot-Python — étage 0, baseline de shortcuts lexicaux
- ICT-35b-HumorCausalPairs-SAE-Python — tranche 1, paires minimales sur SAE
- ICT-35c-HumorDepthProfile-SAE-Python — tranche 2, le verdict aux trois profondeurs
- GameTheory-18c-Humour-Banc-Python — le banc consolide (#14032), source des paires
- Sources humor computationnel :
G:\Mon Drive\MyIA\IA\Bibliographie IA\MachineLearning\Computational Humor\