Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,666 changes: 1,666 additions & 0 deletions MyIA.AI.Notebooks/IIT/ICT-Series/ICT-42-InoculationBifurcation-Pilot.ipynb

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions MyIA.AI.Notebooks/IIT/ICT-Series/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,13 @@ La **strate 5 commence ici** : le substrat mesuré n'est plus un système dynami
| [ICT-21c-SAECatastrophes](ICT-21c-SAECatastrophes.ipynb) | **Catastrophes du dictionnaire SAE — forme & dynamique** (livrable 2 de #8236) — perturbations appariées à trois échelles (1.7B/2B/9B) × deux régimes (trained/control), banc numpy-only sur les traces ICT-21 : forme (Gini, enrichissement top-500 par registre — le trained recrute 2-3× plus de features et les spécialise), dynamique (ablation vives/mortes/aléatoire : f50_vives 0.004→0.07 selon l'échelle trained, path-divergence 0.53-0.82), inoculation **absente** au banc figé (négatif propre), confrontation au FVU réel GPU (L0 constant, fidélité effondrée) *(GPU-free, traces committées)* | [#8236](https://github.com/jsboige/CoursIA/issues/8236) |
| [ICT-25-InoculationRL](ICT-25-InoculationRL.ipynb) | **InoculationRL — GRPO à récompense hackable × inoculation** *(GPU)*. Capstone final de la strate 5 et **pont ICT↔PostTraining** : reproduit, dans les poids à échelle jouet, le phénomène de dérive de persona sous récompense hackable (arXiv 2511.18397). Deux bras d'entraînement GRPO identiques sauf le system prompt (N non inoculé / I inoculé), certifié `rewardspy` (le hack est appris dans les deux), panel persona + éval comportementale hors-domaine. Gates 20-21 falsifiables ; résultat négatif honnête possible (« non reproduit à cette échelle ») | [#5105](https://github.com/jsboige/CoursIA/issues/5105) |
| [ICT-35-HumorCausalProbe-Pilot](ICT-35-HumorCausalProbe-Pilot.ipynb) | **HumorCausalProbe-Pilot — étage 0 : baseline de shortcuts lexicaux** *(strate 5, GPU-free)* : substrat HLS (banc humour dur GT-28b, 120 instances annotées), sans confusion explication/mécanisme — l'étage 0 pose la baseline lexicale AVANT toute phase SAE, les phases suivantes restant aval ([#5635](https://github.com/jsboige/CoursIA/issues/5635), [#8236](https://github.com/jsboige/CoursIA/issues/8236), [#5105](https://github.com/jsboige/CoursIA/issues/5105)) | [#14035](https://github.com/jsboige/CoursIA/issues/14035) |
| [ICT-35b-HumorCausalPairs-SAE](ICT-35b-HumorCausalPairs-SAE.ipynb) | **HumorCausalPairs-SAE — paires minimales, substrat SAE** *(strate 5, tranche 1 de #14035)* : le pilote ICT-35 mesurait l'humour sur un substrat HLS lexical (verdict `INCONCLUSIVE` borné) ; ici le substrat devient le **SAE** Qwen-Scope avec un design expérimental plus fin — des **paires minimales** où seul varie le texte de punchline (humour committé vs punchline neutralisée « unfun », même setup token à token). 30 paires sur les blagues manuelles + 2 one-liners edges du banc GT-24b (instances Argumentum exclues du pairing, champ texte tronqué). Verdict : **INCONCLUSIVE** — amplitude du différentiel trained sous le bruit permuté, top-5 features disjoints du contrôle | [#14035](https://github.com/jsboige/CoursIA/issues/14035) |
| [ICT-35c-HumorDepthProfile-SAE](ICT-35c-HumorDepthProfile-SAE.ipynb) | **HumorDepthProfile-SAE — le verdict survit-il à la profondeur ?** *(strate 5, tranche 2 de #14035)* : l'objection à un résultat mesuré à une seule profondeur — une incongruité comique peut être précoce (lexicale, couches 3-8) ou tardive (pragmatique, couches 18-22) — est levée en mesurant les mêmes 30 paires à **trois profondeurs** (early `--layer-frac 0.1667`, mid, late `0.8333`, captures early/late neuves GPU local, contrôle = permutation seedée des input embeddings à chaque couche) | [#14035](https://github.com/jsboige/CoursIA/issues/14035) |
| [ICT-36-FLens-FactoredGeometry](ICT-36-FLens-FactoredGeometry.ipynb) | **F-Lens, mode factored-geometry — sous-espaces et additivité** *(grain autonome, CPU uniquement, primitives numpy-only)* : la lecture par sous-espaces factored et son test d'additivité, sans dépendre du contrat de traces — le mode factored-geometry du toolkit multi-instrument | [#15478](https://github.com/jsboige/CoursIA/issues/15478), Epic [#15475](https://github.com/jsboige/CoursIA/issues/15475) |
| [ICT-37-FLens-BeliefState](ICT-37-FLens-BeliefState.ipynb) | **F-Lens, mode belief-state — probing linéaire et géométrie prédictive held-out** : un état prédictif suffisant du processus est-il lisible par sonde linéaire, mesuré held-out ? Consomme le contrat de traces ([#15476](https://github.com/jsboige/CoursIA/issues/15476) — split/fit IDs via `ict_trace`) | [#15477](https://github.com/jsboige/CoursIA/issues/15477), Epic [#15475](https://github.com/jsboige/CoursIA/issues/15475) |
| [ICT-38-SLens-SelfLocation](ICT-38-SLens-SelfLocation.ipynb) | **S-Lens — la représentation porte-t-elle la bonne référence ?** *(strate 5, GPU requis, POC expérimental)* : quand la valeur à produire se trouve à une position déterminée par le **contenu** (et non par la position absolue du token), bancs synthétiques à vérité terrain exacte — lecture par tête et intervention causale appariée | [#15814](https://github.com/jsboige/CoursIA/issues/15814) |
| [ICT-39-CompositionRegards](ICT-39-CompositionRegards.ipynb) | **Composition de regards** *(opération 12 « Composer des regards »)* : distinguer la lecture avant (`get`/`play`) de la demande arrière (`put`/`coplay`), les composer réellement, et construire le témoin falsifiable où deux regards composés divergent de leurs lectures isolées — prérequis légers (fonctions, composition, modulo 3) | [#12204](https://github.com/jsboige/CoursIA/issues/12204) |
| [ICT-42-InoculationBifurcation-Pilot](ICT-42-InoculationBifurcation-Pilot.ipynb) | **Inoculation et bifurcation représentationnelle — pilote multi-échelle** *(strate 5, GPU-free à la lecture, traces GPU pré-calculées)* : jalon 3 de l'Épic [#8236](https://github.com/jsboige/CoursIA/issues/8236) — la première expérience de la série qui **intervient** sur le réseau au lieu de l'observer. Un panel de 16 features SAE différentielles (code/prose, dérivées GPU-free des références de chaque échelle) est partiellement supprimé (`h' = h − α·δ`) à mi-profondeur, intensité croissante α ∈ {0, 0.25, 0.5, 0.75, 1}, et la divergence des activations SAE est mesurée **au residual final** — après propagation non-linéaire par toutes les couches aval — sur deux échelles (Qwen3-1.7B-Base, Qwen3.5-2B-Base, SAE W32K-L0_50). Ordre-paramètre m(α), netteté (pente max, facteur de rupture vs réponse proportionnelle), profil token-par-token, comparaison cross-échelle + concordance de Spearman par prompt. Résultat : **dissociation de forme** — le 1.7B répond massivement dès α = 0.25 (36 % de sa valeur finale) puis sature sous-proportionnellement (facteur de rupture 2.77 < 4, pente max au premier cran α* = 0.125) ; le 2B absorbe puis **bascule tardivement** (facteur 8.11 > 4, α* = 0.625), transition portée par prose_fr (×11) et dialogue (×10.8) quand code_python reste proportionnel (×4.05) ; Spearman prompts cross-échelle négatif aux quatre intensités (−0.25 à −0.66). *Contrôle de plomberie α = 0 : ids top-k identiques et divergence L1 exactement nulle vs extraction sans hook.* **Contrôle permuté (phase 6)** : sous panel aléatoire de même taille (seed, hors panel différentiel), la réponse chute de 4× à 28× et la bascule super-linéaire du 2B disparaît (m(1)/m(0.25) = 1.18 vs 8.11 sous panel différentiel) — signature portée par le panel, avec le confondant d'activité mesuré (tirage 80-770× moins actif). **Contrôle apparié en norme (phase 6b)** : sous tirage restreint à la bande d'activité [m/8, 8m] (le panel occupe les rangs 1-19 de la distribution d'activité — une bande ×2 n'y laisse que 1-4 candidats), la réponse **revient** (m(1) = 0.1235 au 2B, 5.6× le tirage uniforme, ordre de grandeur du panel) mais la super-linéarité est divisée par 2.4 (×3.38 vs ×8.11) et la sélectivité par jeu disparaît (×3.2-3.9 homogène vs prose_fr ×11.1 sous panel) : **la norme porte l'amplitude, le contenu du panel porte la discrimination** — révision assumée de la lecture de la phase 6. Limites assumées : pas d'hystérésis (clamp par passe), appariement par le bas (tirage réalisé à ~58-67% de l'activité du panel), divergence dans l'espace top-k uniquement, panels indépendants → comparaison de forme, jamais d'amplitude | [#8236](https://github.com/jsboige/CoursIA/issues/8236) |

### Distillation externe — hors strates

Expand Down
11 changes: 10 additions & 1 deletion MyIA.AI.Notebooks/IIT/ICT-Series/ict/sae_traces.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,8 @@ def assert_sae_topk_compatible(k_sae: int, k_requested: int) -> None:

def trace_filename(variant: str, layer: int, *, model: str = "",
default_model: str = "", n_layers: int | None = None,
n_clamp: int = 0, prefix: str = "ict21_sae") -> str:
n_clamp: int = 0, clamp_scale: float | None = None,
prefix: str = "ict21_sae") -> str:
"""Nom de fichier de trace **discriminant par echelle**.

Defaut historique conserve a l'octet pour le modele de reference (les
Expand All @@ -416,8 +417,16 @@ def trace_filename(variant: str, layer: int, *, model: str = "",
sans lui, un run 2B et un run 9B a la meme couche 16 ecrivent **le meme
nom** et le second efface le premier en silence — perte de donnees, pas
seulement confusion.

``clamp_scale`` (experience pilote #8236) : intensite alpha du clamp,
h' = h - alpha * delta. Le suffixe ``_s{alpha}`` n'est insere **que si**
alpha s'ecarte de 1.0 — a intensite unitaire le nom reste byte-identique
au defaut historique, et les traces existantes a clamp plein ne se
retrouvent pas dupliquees sous deux noms.
"""
clamp = f"_clamp{n_clamp}" if n_clamp else ""
if clamp_scale is not None and n_clamp and abs(clamp_scale - 1.0) > 1e-9:
clamp += f"_s{clamp_scale:g}"
if model and default_model and model != default_model:
slug = model.rstrip("/").split("/")[-1].lower().replace(".", "")
depth = f"layer{layer}of{n_layers}" if n_layers else f"layer{layer}"
Expand Down
Loading
Loading