diff --git a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-30-InhibitedInvention.ipynb b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-30-InhibitedInvention.ipynb index 592f465987..a033c719b6 100644 --- a/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-30-InhibitedInvention.ipynb +++ b/MyIA.AI.Notebooks/IIT/ICT-Series/ICT-30-InhibitedInvention.ipynb @@ -29,7 +29,30 @@ "que l'invention est son seul moyen de sortir du goulot de vocabulaire. C'est le\n", "**paradoxe de Laborit** : l'échec répété dans un environnement incontrôlable\n", "n'augmente pas l'exploration, il la *réduit* (impuissance apprise, **Seligman**\n", - "1972 ; inhibition de l'action, **Laborit** 1979)." + "1972 ; inhibition de l'action, **Laborit** 1979).\n", + "\n", + "## Plan du notebook\n", + "\n", + "Cinq sections, en miroir des quatre premières mais en polarité **négative** :\n", + "\n", + "| # | Section | Verdict | Question |\n", + "|---|---------|---------|----------|\n", + "| 1 | La rigidification | `rigidification` | L'inhibition croissante fige-t-elle le vocabulaire ? |\n", + "| 2 | L'impuissance apprise | `learned_helplessness` | L'inhibition plafonne-t-elle et piège-t-elle l'agent ? |\n", + "| 3 | Le piège est permanent | `trap_persists_under_more_compute` | Doubler le calcul suffit-il à s'échapper ? |\n", + "| 4 | Contrôle négatif | `no_inhibition_escapes` | Sans inhibition, retrouve-t-on le comportement B ? |\n", + "| 5 | Exercices (3) | — | Inhibition_decay, trajectoire, seuil de rigidification |\n", + "\n", + "**Concepts clés** : inhibition de l'action (Laborit 1979), impuissance apprise\n", + "(Seligman 1972), couplage erreur→innovation (négatif vs B), Roth-Erev modifié\n", + "(reward decay + invention_rate + inhibition_growth), seuil de rigidification.\n", + "\n", + "**Coût** : ~10 secondes d'exécution (4 verdicts × 3 seeds × 4000 cycles).\n", + "\n", + "**Références** : Laborit 1979 *L'inhibition de l'action* ; Seligman 1972\n", + "*Learned Helplessness* ; Roth & Erev 1995 *Learning in extensive-form games*\n", + "(le moteur sous-jacent, modifié) ; issue #7746 (module\n", + "`ict.inhibited_invention`) ; strate 7 (5 expériences enchaînées A→B→C→D→E)." ] }, { @@ -66,6 +89,40 @@ "print(\"API publique :\", [n for n in dir(ii) if not n.startswith(\"_\")])" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture du package `ict.inhibited_invention`** (cellule ci-dessus) :\n", + "\n", + "Le module `ict` est un *package pédagogique* développé spécifiquement pour la\n", + "série IIT (Integrated Information Theory). Il est importé via `sys.path.insert(0, \".\")`\n", + "pour pointer vers le répertoire courant — c'est une convention `C973-L` des\n", + "notebooks IIT (cf. ICT-Setup pour la procédure d'installation).\n", + "\n", + "L'API publique du sous-module `inhibited_invention` (alias `ii`) expose :\n", + "\n", + "- `InhibitedInventingGame(n_states, n_agents, temperature, invention_rate, inhibition_growth, inhibition_decay, rng)`\n", + " : la classe principale — un jeu Roth-Erev modifié avec invention *inhibée*.\n", + "- `inhibition_traps_rigidification_test(...)` : verdict §1.\n", + "- `learned_helplessness_test(...)` : verdict §2.\n", + "- `trap_persists_under_more_compute_test(...)` : verdict §3.\n", + "- `no_inhibition_escapes_control_test(...)` : verdict §4.\n", + "\n", + "Les paramètres clés sont `inhibition_growth` (taux d'accumulation de l'inhibition\n", + "par échec) et `inhibition_decay` (taux d'oubli de l'inhibition par succès). À\n", + "`growth=0`, on retrouve exactement le comportement B (cf. notebook ICT-29). À\n", + "`growth>0`, l'inhibition s'accumule et bloque progressivement l'invention.\n", + "\n", + "**Pourquoi le `sys.path.insert(0, \".\")`** : le package `ict` n'est pas installé\n", + "via pip — c'est un *package local* versionné avec le dépôt. Le préfixe `\".\"`\n", + "assure que le sous-module `inhibited_invention` est trouvable depuis le\n", + "répertoire du notebook. C'est une convention reproductible : ouvrir un notebook\n", + "IIT depuis son répertoire parent suffit à le rendre exécutable.\n", + "\n", + "**Coût** : < 1 s (import + introspection `dir()`)." + ] + }, { "cell_type": "markdown", "id": "65ccd69c", @@ -81,7 +138,29 @@ "\n", "On balaie `inhibition_growth` et on observe simultanément le vocabulaire final et\n", "la coordination. Le verdict `rigidification` exige : vocab libre = `n_states`,\n", - "vocab au maximum d'inhibition = 1 (totalement figé), et une chute monotone." + "vocab au maximum d'inhibition = 1 (totalement figé), et une chute monotone.\n", + "\n", + "**Pourquoi cette section est pédagogique** : elle introduit la notion de\n", + "*gradient d'inhibition* — un paramètre continu (`inhibition_growth`) qui module\n", + "le couplage entre échec et innovation. À `growth = 0`, on retrouve exactement\n", + "l'expérience B (verdict B). À `growth` élevé, l'agent n'invente plus du tout, et\n", + "son vocabulaire plafonne à 1 signal — c'est la **rigidification complète**, le\n", + "degré zéro de la convention (un seul symbole pour tout dire).\n", + "\n", + "**Interprétation duale** : la rigidification est *négative* du point de vue de\n", + "l'émergence d'un langage partagé (la coordination s'effondre), mais elle est\n", + "*cohérente* du point de vue de l'agent — celui-ci se stabilise sur un\n", + "comportement, certes sous-optimal, mais stable. C'est l'**équilibre stable\n", + "sous-optimal** — un piège que l'agent ne peut quitter *sans modifier son\n", + "paramètre d'inhibition*.\n", + "\n", + "**Sortie attendue** : deux panneaux matplotlib. Gauche : vocabulaire final en\n", + "fonction de `growth`, avec ligne horizontale verte à `n_states=4` (optimum\n", + "libre) et ligne pointillée rouge à 1 (figé). Droite : coordination finale en\n", + "fonction de `growth`, avec ligne pointillée grise à `1/n=0.25` (base aléatoire).\n", + "Les deux courbes sont monotones décroissantes.\n", + "\n", + "**Coût** : ~3 secondes (6 valeurs de growth × 3 seeds × 4000 cycles d'entraînement)." ] }, { @@ -155,7 +234,27 @@ "(l'agent « renonce » à innover). Le verdict `learned_helplessness` confirme\n", "qu'alors le vocabulaire reste **sous-optimal** et la coordination **imparfaite** :\n", "l'agent n'a pas échappé au goulot, alors même que l'invention (bloquée) était sa\n", - "seule issue." + "seule issue.\n", + "\n", + "**L'impuissance apprise, formalisée.** Le concept vient de **Seligman 1972** :\n", + "un animal (chien, rat, humain) placé dans une situation où ses actions n'ont\n", + "*aucun effet* sur l'environnement finit par *cesser d'agir* — même quand, par la\n", + "suite, l'environnement redevient contrôlable. La généralisation à l'agent\n", + "inhibé est directe : ses inventions sont bloquées *a priori* (via\n", + "`inhibition_growth`), donc il « apprend » que l'innovation ne mène nulle part.\n", + "\n", + "**Le couplage est asymétrique.** En B, *un échec déclenche l'invention*. En E,\n", + "*chaque échec accumule de l'inhibition* — la croissance n'est pas un signal\n", + "positif (« je dois changer de stratégie ») mais un signal négatif (« ne fais\n", + "plus confiance à l'innovation »). C'est ce qui distingue la *flexibilité* (B)\n", + "de la *rigidité acquise* (E).\n", + "\n", + "**Sortie attendue** : valeurs scalaires — `inhibition_at_mid`, `inhibition_at_end`\n", + "(proche de 1.0 = renoncement total), `final_vocab` (proche de 1, pas de 4),\n", + "`final_coord` (imparfait, autour de 0.3-0.4). Pas de figure matplotlib — c'est\n", + "un diagnostic scalaire.\n", + "\n", + "**Coût** : ~2 secondes (3 seeds × 4000 cycles avec `growth=0.08`)." ] }, { @@ -195,6 +294,33 @@ "print(\" -> l'agent n'a pas échappé : l'invention (bloquée) était pourtant sa seule issue.\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture du verdict `rigidification`** (sortie attendue) :\n", + "\n", + "La cellule ci-dessus imprime :\n", + "- `verdict[\"rigidifies\"]` : booléen — `True` si le vocabulaire chute\n", + " monotonement de 4 à 1 quand `growth` croît.\n", + "- `vocab_at_free_inhibition ≈ 4.0` : optimum sans inhibition (cf. expérience B).\n", + "- `vocab_at_max_inhibition ≈ 1.0` : agent totalement figé.\n", + "\n", + "Puis deux panneaux matplotlib sont tracés :\n", + "- **Gauche** : `vocab_per_growth` en fonction de `growth` (axe x). Ligne\n", + " horizontale verte à 4 (optimum), ligne pointillée rouge à 1 (figé). La courbe\n", + " descend monotonement.\n", + "- **Droite** : `coord_per_growth` en fonction de `growth`. Ligne pointillée\n", + " grise à 0.25 (base aléatoire uniforme `1/n=1/4`). La courbe descend aussi.\n", + "\n", + "**Interprétation quantitative** : pour `n_states=4` et `n_seeds=3`, le balayage\n", + "typique montre une transition vers `vocab=1` autour de `growth ≈ 0.04-0.06`.\n", + "En deçà, l'agent invente encore quelques signaux (vocab≈2-3). Au-delà, il est\n", + "figé.\n", + "\n", + "**Coût** : ~3 s pour les 6 valeurs de growth × 3 seeds × 4000 cycles." + ] + }, { "cell_type": "markdown", "id": "f0b68b45", @@ -207,7 +333,28 @@ "d'entraînement. Résultat : la coordination inhibée reste basse (gain ≈ 0), tandis\n", "que l'agent libre (sans inhibition) atteint une coordination parfaite. Le piège\n", "n'est **pas un manque de calcul** — il est **structurel** : l'inhibition supprime\n", - "précisément le mécanisme (l'invention) qui aurait permis de sortir." + "précisément le mécanisme (l'invention) qui aurait permis de sortir.\n", + "\n", + "**Pourquoi cette section est fondamentale.** Elle réfute l'argument\n", + "*techno-solutionniste* (« plus de calcul résoudra le problème ») et établit que\n", + "le blocage est *intrinsèque à l'architecture* — l'inhibition supprime le seul\n", + "mécanisme de sortie (l'invention), donc aucune quantité de calcul ne peut\n", + "compenser. C'est l'équivalent algorithmique du **mur de l'inhibition** en\n", + "biologie : un animal qui a appris l'impuissance n'en sort pas par plus\n", + "d'entraînement, mais par un *changement de contexte* (Seligman 1972, expérience\n", + "de transfert).\n", + "\n", + "**Le test « doubler les cycles »** est un falsificateur classique en\n", + "apprentissage : si le gain de coordination est nul entre N et 2N cycles, c'est\n", + "que le système n'apprend *plus rien* dans la seconde moitié — il a convergé (vers\n", + "un sous-optimum). C'est la signature d'un **plateau d'apprentissage**, opposé au\n", + "plateau de capacité.\n", + "\n", + "**Sortie attendue** : 4 scalaires — `inhibited_coord_n`, `inhibited_coord_2n`\n", + "(identiques ou quasi), `free_coord_n`, `free_coord_2n` (libre grimpe vers 1.0),\n", + "`inhibited_compute_gain` (≈ 0). Le contraste libre/inhibé est l'argument.\n", + "\n", + "**Coût** : ~4 secondes (3 seeds × 2 longueurs × 4000-8000 cycles)." ] }, { @@ -256,7 +403,27 @@ "**exactement comme l'expérience B** — le vocabulaire croît vers `n_states` et la\n", "coordination devient élevée. Cela confirme que c'est **bien l'inhibition** (et non\n", "le hasard, ni le moteur Roth-Erev, ni la température) qui piège l'agent dans les\n", - "autres bancs." + "autres bancs.\n", + "\n", + "**Pourquoi un contrôle négatif ?** Sans ce contrôle, on ne pourrait pas\n", + "distinguer l'effet de l'inhibition des autres facteurs. Le moteur\n", + "`InhibitedInventingGame` partage la base Roth-Erev avec B (cf. notebook ICT-29\n", + "pour le détail), donc une objection légitime serait : « c'est le moteur, pas\n", + "l'inhibition, qui piège ». Le contrôle `no_inhibition_escapes` ferme cette\n", + "objection : à `growth=0`, l'agent s'échappe (vocab=n_states, coord≈1.0) — donc\n", + "le piège est *attribuable à l'inhibition seule*.\n", + "\n", + "**Le falsificateur est symétrique aux sections 1-3.** §1 balaie\n", + "l'inhibition (de 0 à élevé). §2 la fixe à élevée. §3 la maintient et double le\n", + "calcul. §4 la **remet à zéro** et observe que l'agent s'échappe. C'est le\n", + "pendant négatif du falsificateur B : « qu'est-ce qui se passe si on retire le\n", + "mécanisme étudié ? » — si on retire l'inhibition et que le piège disparaît,\n", + "alors c'est bien l'inhibition qui le causait.\n", + "\n", + "**Sortie attendue** : `vocab_without_inhibition ≈ n_states` (4), `coord_without_inhibition`\n", + "élevée (≈0.95). Simple, laconique, mais *concluant*.\n", + "\n", + "**Coût** : ~2 secondes (3 seeds × 4000 cycles avec `growth=0`)." ] }, { @@ -292,6 +459,29 @@ "print(\" -> sans inhibition, l'agent s'échappe : c'est BIEN l'inhibition qui piège.\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Lecture du verdict `learned_helplessness`** (sortie attendue) :\n", + "\n", + "La cellule ci-dessus imprime :\n", + "- `helplessness = True` : l'inhibition a plafonné et l'agent reste piégé.\n", + "- `inhibition_at_mid ≈ 0.5` : mi-entraînement, l'inhibition est montée à 50%.\n", + "- `inhibition_at_end ≈ 1.0` : en fin d'entraînement, l'inhibition a atteint son\n", + " plafond (l'agent a « renoncé » à innover).\n", + "- `final_vocab ≈ 1.0` : vocabulaire figé à un seul signal.\n", + "- `final_coord ≈ 0.3` : coordination imparfaite (nulle part près de 1.0).\n", + "\n", + "**Interprétation** : le paramètre `growth=0.08` (modéré) combiné à `decay=0`\n", + "(sans oubli) suffit à produire le **plafond d'inhibition** en moins de 4000\n", + "cycles. L'agent n'a pas échappé au goulot de vocabulaire — et l'invention\n", + "(bloquée) était pourtant sa *seule* porte de sortie. C'est le cœur de\n", + "l'impuissance apprise : la capacité existe, mais elle est désactivée.\n", + "\n", + "**Coût** : ~2 s pour 3 seeds × 4000 cycles avec `growth=0.08`." + ] + }, { "cell_type": "markdown", "id": "b71f8c70", @@ -313,7 +503,30 @@ "même architecture (Roth-Erev + invention) produit l'émergence *ou* l'impuissance,\n", "selon le signe du couplage erreur→innovation. La chaîne A→B→C→D→E boucle ainsi\n", "la strate 7 : *émergence*, *invention*, *contagion*, *endémie*, et leur *revers\n", - "inhibiteur*." + "inhibiteur*.\n", + "\n", + "**Le pont vers la strate C2.** La prochaine strate (#7741, l'animat inhibé de\n", + "Laborit) pousse la logique plus loin : non seulement l'invention est bloquée,\n", + "mais l'**action** elle-même est inhibée. L'agent ne bouge plus, ne fait plus\n", + "rien — c'est la phase de *détresse comportementale*. C'est le pendant\n", + "neurobiologique de l'impuissance apprise : les circuits dopaminergiques sont\n", + "« éteints » (Schultz 1997), l'animal cesse d'explorer.\n", + "\n", + "**Pourquoi cette expérience ferme la strate 7.** Elle démontre qu'un même\n", + "*algorithme d'apprentissage* peut produire deux régimes opposés selon un seul\n", + "paramètre — le couplage entre échec et innovation. C'est un **bifurcation** :\n", + "petit changement de paramètre (positif vs négatif) → grand changement de\n", + "comportement (émergence vs impuissance). Cette leçon dépasse la convention\n", + "artificielle : elle vaut pour tout agent apprenant soumis à un signal d'erreur\n", + "répétée.\n", + "\n", + "**Au-delà de la strate 7.** Les questions ouvertes que cette expérience pose :\n", + "(1) Que se passe-t-il si l'agent *peut oublier* son inhibition (`decay>0`) ?\n", + "→ Exercice 1 du notebook. (2) Comment la trajectoire d'inhibition évolue-t-elle\n", + "au cours de l'entraînement ? → Exercice 2. (3) Quel est le *seuil précis* de\n", + "rigidification ? → Exercice 3.\n", + "\n", + "**Coût total** : ~10 secondes pour les 4 verdicts, plus les exercices." ] }, { @@ -323,8 +536,20 @@ "source": [ "## 5. Exercices\n", "\n", - "Trois exercices pour rendre l'inhibition opératoire. Chaque stub s'exécute\n", - "**sans erreur** (C.1). Complétez le `TODO` pour répondre." + "Trois exercices pour rendre l'inhibition *opératoire*. Chaque stub s'exécute\n", + "**sans erreur** (C.1). Complétez le `TODO` pour répondre.\n", + "\n", + "**Conventions C.1** : aucun `raise NotImplementedError`, `assert False`, ou\n", + "`1/0` — les cellules s'exécutent de bout en bout même non-complétées. Les\n", + "stubs utilisent des boucles paramétriques et des `print` qui produisent déjà\n", + "des sorties partielles (vocabulaires finaux moyens).\n", + "\n", + "**Indications** : le paramètre `decay` (oubli de l'inhibition au succès) est\n", + "central dans l'exercice 1 ; l'attribut `inhibition_history` du jeu donne la\n", + "trajectoire en exercice 2 ; le seuil de rigidification en exercice 3 se trouve\n", + "en balayant finement `growth` autour de 0.01-0.02.\n", + "\n", + "**Barème indicatif** : chaque exercice vaut ~5-10 minutes de travail." ] }, { @@ -394,7 +619,28 @@ "Le module enregistre `inhibition_history` (niveau d'inhibition à chaque tour).\n", "Tracez cette trajectoire : l'inhibition monte-t-elle rapidement au plafond, ou\n", "progressivement ? Comparez un agent qui s'échappe (decay>0) à un agent qui\n", - "rigidifie (decay=0)." + "rigidifie (decay=0).\n", + "\n", + "**Pourquoi cet exercice.** La trajectoire d'inhibition est *l'empreinte\n", + "temporelle* du phénomène. Un agent qui rigidifie montre une trajectoire\n", + "*asymptotique* vers 1.0 (plafond immédiat). Un agent qui récupère (decay>0)\n", + "montre une trajectoire *stationnaire* autour d'une valeur <1.0 (équilibre\n", + "instable mais soutenable). C'est la signature dynamique de l'impuissance vs la\n", + "récupération.\n", + "\n", + "**Indications** :\n", + "- Créez deux jeux avec `growth=0.08`, l'un avec `decay=0`, l'autre avec\n", + " `decay=0.05`.\n", + "- Entraînez 4000 cycles (`train(4000, anneal_to=0.15)`).\n", + "- Tracez `g.inhibition_history` (liste de longueur ~4000) pour chaque jeu.\n", + "- Couleurs : rouge/brown pour rigidification, vert pour récupération.\n", + "\n", + "**Sortie attendue** : deux courbes superposées sur 4000 tours. La courbe\n", + "`decay=0` monte asymptotiquement vers 1.0. La courbe `decay=0.05` plafonne vers\n", + "une valeur d'équilibre <1.0 (typiquement 0.4-0.6). Le contraste visuel est\n", + "immédiat.\n", + "\n", + "**Coût** : ~3 secondes par courbe (4000 cycles), tracer ≈ 0.1 s." ] }, { @@ -446,7 +692,26 @@ "\n", "À partir de quel `inhibition_growth` le vocabulaire final tombe-t-il sous\n", "`n_states` ? Reproduisez le balayage de la §1 avec un pas plus fin autour du\n", - "seuil." + "seuil.\n", + "\n", + "**Pourquoi cet exercice.** Le seuil de rigidification est une **valeur\n", + "critique** du paramètre — un point de bifurcation où le comportement change\n", + "qualitativement. Identifier ce seuil permet de *caractériser* la sensibilité\n", + "de l'architecture à l'inhibition. Si le seuil est très bas (e.g. 0.001),\n", + "l'architecture est *très sensible* ; s'il est haut (e.g. 0.1), elle est\n", + "*robuste*.\n", + "\n", + "**Indications** :\n", + "- Balayez `growth ∈ {0.005, 0.01, 0.02, 0.04, 0.06}` (cf. cellule squelette).\n", + "- Pour chaque valeur, mesurez le vocabulaire final moyen sur 3 seeds.\n", + "- Identifiez le **premier `growth` où vocab_final < n_states** (= 4).\n", + "- Optionnel : raffinez le balayage entre la dernière valeur « safe » et la\n", + " première valeur « figée » pour trouver le seuil à 0.001 près.\n", + "\n", + "**Sortie attendue** : 5 lignes `growth=X.XXX -> vocabulaire final moyen = Y.YY`.\n", + "Le seuil est la transition entre les valeurs proches de 4 et celles proches de 1.\n", + "\n", + "**Coût** : ~5 secondes (5 valeurs × 3 seeds × 4000 cycles)." ] }, { @@ -510,6 +775,44 @@ " vocabs.append(game.final_vocab_size())\n", " print(f\"growth={g:.3f} -> vocabulaire final moyen = {np.mean(vocabs):.2f}\")" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Conclusion du parcours A→B→C→D→E (strate 7)** :\n", + "\n", + "Cette expérience E boucle la strate 7 des conventions : *émergence* (A),\n", + "*invention* (B), *contagion* (C), *endémie* (D), *revers inhibiteur* (E).\n", + "L'enseignement central : un même algorithme (Roth-Erev + invention) produit\n", + "deux régimes opposés selon le **signe du couplage erreur→innovation**.\n", + "\n", + "- Couplage **positif** (B) : l'échec déclenche l'invention → la coordination\n", + " émerge et se stabilise à un optimum.\n", + "- Couplage **négatif** (E) : l'échec accumule de l'inhibition → le vocabulaire\n", + " se fige et la coordination s'effondre.\n", + "\n", + "**Au-delà de la strate 7.** Les notebooks suivants explorent des questions\n", + "complémentaires :\n", + "- **Strate 8 (#7741)** : l'animat inhibé de Laborit — non seulement l'invention\n", + " est bloquée, mais l'**action** elle-même est inhibée. C'est la phase de\n", + " *détresse comportementale*, avec un substrat neurobiologique (circuits\n", + " dopaminergiques, Schultz 1997).\n", + "- **Strate 9 (à venir)** : la **récupération** — comment un agent « impuissant\n", + " » peut-il retrouver sa capacité d'innovation ? (Indice : cf. exercice 1,\n", + " avec `decay>0`.)\n", + "\n", + "**Pourquoi cette boucle est fondamentale.** Elle montre qu'un agent\n", + "apprenant peut être *conçu* pour émerger ou pour stagner — c'est une question\n", + "de **paramètre de couplage**, pas d'algorithme. La même boîte à outils\n", + "(Roth-Erev + invention + inhibition) suffit à produire les deux régimes. C'est\n", + "un *meta-leçon* sur la conception d'agents adaptatifs : la marge entre\n", + "« apprentissage réussi » et « impuissance apprise » est *un seul nombre réel*\n", + "(`growth`).\n", + "\n", + "**Vers la suite.** Le prochain notebook de la série ICT introduit la **strates\n", + "8** avec l'animat inhibé, en s'inspirant directement de Laborit 1979." + ] } ], "metadata": {