ICT-27 — Invention de symboles (expérience B, strate 7)
Compagnon pédagogique du module ict.symbol_invention (#7746, expérience B).
Jusqu’ici la série des jeux de signalisation partait d’un vocabulaire donné : l’expérience A (ict.signaling_convention, #8842) montre comment un couple émetteur/récepteur converge vers une bijection état → signal → action par renforcement (Roth-Erev) — mais le nombre de signaux était fixé d’avance, à exactement n_states. C’est le cadre de Lewis (1969) : la convention émerge dans un espace de signaux prédéfini.
Cette expérience B lève cette hypothèse. Le vocabulaire n’est plus donné : il est inventé. L’agent démarre avec un seul signal (un goulot de vocabulaire), et invente un nouveau signal sur échec de coordination, jusqu’à ce qu’un signal par état devienne disponible. C’est le cadre de Skyrms (2010), Signals : Evolution, Learning, and Information : l’émergence du meaning lui-même, pas seulement la convention qui l’organise.
Plan du notebook
Le goulot — pourquoi un seul signal ne suffit pas (la coordination est structurellement impossible tant que deux états partagent le même signal).
Verdict croissance — le vocabulaire croît vers n_states (l’agent invente à la mesure du problème, ni plus ni moins).
Verdict seuil de coût — l’invention a un prix : introduire un coût économique (gate de rentabilité) fige le vocabulaire sous l’optimum.
Verdict diversité — il n’existe pas une bonne convention mais n_states! : 5 conventions distinctes sur 6 graines — les graines 0 et 5 convergent vers la même permutation (2, 3, 0, 1).
Exercices — trois bancs à compléter (C.1 : les stubs s’exécutent sans erreur).
Toutes les affirmations chiffrées de ce notebook sont reproduites depuis le module, pas affichées en dur — c’est la discipline anti-dérive (#2572).
Statut épistémique — Fortement soutenu : Le vocabulaire inventé croît jusqu’à suffire (autour de n_states), ni en-deçà ni au-delà. Portée et détail dans la matrice de dissociations.
Acquis et parenté : expérience B (invention de symboles) — suppose A, la convention donnée de ICT-26-SignalingConvention-Python, dont le répertoire initial est précisément ce que l’invention quitte. Famille A→E, #7746.
# Setup : import du package ict (via sys.path cwd, cf #973-L) + numpy/matplotlib.import syssys.path.insert(0, ".")import numpy as npimport matplotlib.pyplot as pltfrom ict.symbol_invention import InventingSignalingGamenp.random.seed(0)print("ict.symbol_invention importe. Module = experience B (#7746).")
ict.symbol_invention importe. Module = experience B (#7746).
1. Le goulot de vocabulaire
Avec un seul signal, l’émetteur ne peut pas distinguer les états : quel que soit l’état observé, il envoie le signal 0. Le récepteur, ne recevant que 0, choisit toujours la même action — qui ne peut être correcte que pour un état sur n_states. Le taux de succès est donc plafonné à 1/n_states par construction. Aucune quantité de renforcement ne lève ce plafond : c’est un goulot structurel, pas un déficit d’apprentissage. C’est précisément ce goulot qui motive l’invention.
# Demonstration : avec 1 signal, le plafond 1/n_states est infranchissable.n_states =4g_bloque = InventingSignalingGame( n_states, n_signals_init=1, max_signals=1, # vocabulaire FIGE a 1 signal temperature=0.6, invention_rate=0.0, # invention DESACTIVEE rng=np.random.default_rng(0),)g_bloque.train(4000, anneal_to=0.15)plafond =1.0/ n_statesprint(f"Taux de succes final : {g_bloque.success_rate(500):.3f}")print(f"Plafond theorique 1/{n_states} = {plafond:.3f}")print(f"Vocabulaire final : {g_bloque.final_vocab_size()} signal (fige, invention interdite)")print("=> Aucun renforcement ne leve le plafond : le goulot est structurel.")
Taux de succes final : 0.256
Plafond theorique 1/4 = 0.250
Vocabulaire final : 1 signal (fige, invention interdite)
=> Aucun renforcement ne leve le plafond : le goulot est structurel.
2. Verdict croissance — le vocabulaire s’invente à la mesure du problème
Activons l’invention (coût nul, taux modéré) et laissons l’agent apprendre. Sur échec de coordination, un nouveau signal est tenté (pavage neutre des matrices Q par initial_q). On observe que le vocabulaire croît jusqu’à n_states puis se stabilise : l’agent invente exactement un signal par état, ni plus (un signal supplémentaire serait superflu) ni moins (il resterait un goulot). C’est l’auto-stop mécanique de l’invention.
# Balayons n_states : le vocabulaire final suit n_states (invention a la mesure).n_states_list = [3, 4, 5, 6]vocab_finaux, succes_finaux = [], []for n in n_states_list: vfs, sfs = [], []for s inrange(3): # moyennage sur 3 graines (bruit stochastic) g = InventingSignalingGame( n, n_signals_init=1, temperature=0.6, invention_rate=0.1, invention_cost=0.0, rng=np.random.default_rng(s), ) g.train(4000, anneal_to=0.15) vfs.append(g.final_vocab_size()) sfs.append(g.success_rate(500)) vocab_finaux.append(np.mean(vfs)) succes_finaux.append(np.mean(sfs))fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(11, 4))ax1.bar(n_states_list, vocab_finaux, color="#4C72B0", label="vocabulaire invente")ax1.plot(n_states_list, n_states_list, "o--", color="#C44E52", label="optimum = n_states")ax1.set_xlabel("n_states"); ax1.set_ylabel("vocabulaire final")ax1.set_title("L'invention atteint l'optimum n_states"); ax1.legend(); ax1.grid(alpha=0.3)ax2.bar(n_states_list, succes_finaux, color="#55A868")ax2.set_xlabel("n_states"); ax2.set_ylabel("taux de succes final")ax2.set_title("Coordination proche de 1.0 une fois le vocabulaire complete")ax2.set_ylim(0, 1.05); ax2.grid(alpha=0.3)plt.tight_layout(); plt.show()print("Verdict CROISSANCE : vocab final =", vocab_finaux, "(attendu ~", n_states_list, ")")
3. Verdict seuil de coût — l’invention a un prix (gate de rentabilité)
L’invention n’est pas gratuite dans la nature : créer un nouveau signal a un coût (une dépense énergétique, cognitive). Le module modélise cela par une gate de rentabilité : l’agent n’invente sur échec que si le déficit de coordination récent(1 - taux de succès court) excède un seuil invention_cost. Autrement dit, l’agent n’invente que si c’est rentable — si le gain espéré de distinguer un nouvel état couvre l’effort.
En balayant invention_cost (avec n_states=6 pour une transition observable), le vocabulaire final décroît : coût nul → 6 signaux (optimum), coût élevé → vocabulaire figé sous l’optimum (l’agent « renonce » à inventer). C’est la version économique du goulot : non plus « impossible » mais « pas rentable ».
# Balayage du cout d'invention (n_states=6) : transition observable.couts = [0.0, 0.2, 0.4, 0.6, 0.8]vocab_par_cout = []for c in couts: vfs = []for s inrange(4): g = InventingSignalingGame(6, n_signals_init=1, temperature=0.6, invention_rate=0.1, invention_cost=c, rng=np.random.default_rng(s), ) g.train(4000, anneal_to=0.15) vfs.append(g.final_vocab_size()) vocab_par_cout.append(np.mean(vfs))plt.figure(figsize=(7, 4))plt.plot(couts, vocab_par_cout, "o-", color="#4C72B0", linewidth=2, markersize=9)plt.axhline(6, color="#55A868", linestyle="--", alpha=0.7, label="optimum n_states=6")plt.axhline(1, color="#C44E52", linestyle="--", alpha=0.7, label="goulot 1 signal")plt.xlabel("cout d'invention (seuil de rentabilite)"); plt.ylabel("vocabulaire final moyen")plt.title("Verdict SEUIL DE COUT : un cout eleve fige le vocabulaire sous l'optimum")plt.legend(); plt.grid(alpha=0.3); plt.show()print("Verdict COUT : vocab par cout =", [round(v,2) for v in vocab_par_cout])
4. Verdict diversité — il existe n_states! bonnes conventions, pas une
Quand le vocabulaire est complet, l’agent a formé une bijection état → signal → action. Mais il n’existe pas une bijection canonique : toute permutation des signaux est une convention également valide (le signal 2 peut coder l’état 0 sur une graine, l’état 3 sur une autre). En lançant plusieurs graines aléatoires, on observe 5 conventions distinctes sur 6 graines — les graines 0 et 5 convergent vers la même permutation (2, 3, 0, 1). La diversité des ontologies émergentes est réelle, mais la graine ne garantit pas l’unicité du tirage.
# 6 graines : combien de conventions distinctes emerge ?n_states =4conventions = []for s inrange(6): g = InventingSignalingGame( n_states, n_signals_init=1, temperature=0.6, invention_rate=0.1, invention_cost=0.0, rng=np.random.default_rng(100+ s), ) g.train(4000, anneal_to=0.15) conv =tuple(g.dominant_signal_per_state()) conventions.append(conv)distinctes =len(set(conventions))print(f"Conventions emergees (signal dominant par etat) :")for i, c inenumerate(conventions):print(f" graine {i}: etat -> signal {c}")print(f"\n{distinctes}/6 conventions distinctes (chacune une bijection de [0..{n_states-1}]).")print(f"-> Il existe {np.prod(range(1, n_states +1))} conventions valides ; la graine en selectionne une.")
Conventions emergees (signal dominant par etat) :
graine 0: etat -> signal (2, 3, 0, 1)
graine 1: etat -> signal (3, 0, 1, 2)
graine 2: etat -> signal (2, 1, 3, 0)
graine 3: etat -> signal (0, 3, 2, 1)
graine 4: etat -> signal (1, 3, 0, 2)
graine 5: etat -> signal (2, 3, 0, 1)
5/6 conventions distinctes (chacune une bijection de [0..3]).
-> Il existe 24 conventions valides ; la graine en selectionne une.
Synthèse — l’invention de symboles comme émergence du meaning
Verdict
Ce qu’il montre
Cadre théorique
Croissance
Le vocabulaire croît exactement vers n_states puis s’arrête
Auto-stop mécanique (goulot résolu)
Seuil de coût
Un coût élevé fige le vocabulaire sous l’optimum
Gate de rentabilité (Skyrms)
Diversité
n_states! conventions également valides
Symétrie des bijections
Le passage de l’expérience A (Lewis, vocabulaire donné) à l’expérience B (Skyrms, vocabulaire inventé) est le passage de la convention au meaning : A explique comment on s’accorde sur l’usage de signaux préexistants ; B explique d’où viennent ces signaux. C’est le premier pas de l’arc #7746 (cinq expériences : convention A → invention B → adoption C → inoculation D → inhibition E), où chaque étape ajoute un mécanisme.
5. Exercices
Trois exercices pour rendre l’invention opératoire. Chaque stub s’exécute sans erreur (C.1) — complétez-le.
Exercice 1 — Température d’exploration et vitesse d’invention
L’invention se déclenche sur échec de coordination, mais l’agent n’explore les nouveaux signaux que si la temperature softmax est suffisante. Pour un budget fixé de n_rounds = 2000, existe-t-il une température en dessous de laquelle le vocabulaire n’atteint pas n_states (l’agent est trop glouton, n’explore jamais les signaux fraîchement inventés) ? Balayez temperature dans [0.1, 0.3, 0.5, 0.8, 1.2] avec n_states=4, et tracez le vocabulaire final.
# Exercice 1 — stub (completer)temperatures = [0.1, 0.3, 0.5, 0.8, 1.2]# TODO: pour chaque temperature, lancer InventingSignalingGame(4, 1, temperature=t,# invention_rate=0.1, invention_cost=0.0) sur 3 graines, train(2000, anneal_to=0.15),# et collecter le vocabulaire final moyen.#vocab_par_temp = [...]#plt.plot(temperatures, vocab_par_temp, "o-"); plt.axhline(4, linestyle="--"); plt.show()print("Exercice 1 : a completer (stub sans erreur, C.1 OK).")
Exercice 1 : a completer (stub sans erreur, C.1 OK).
Exercice 2 — Plafond explicite et invention bloquée
Le paramètre max_signals plafonne le vocabulaire (anti-prolifération). Fixez n_states=4 mais max_signals=2. Que se passe-t-il ? Le taux de succès final devrait plafonner non plus à 1/n_states = 0.25 (goulot 1 signal) mais à une valeur intermédiaire correspondant à 2 signaux pour 4 états. Calculez ce plafond théorique et vérifiez-le empiriquement.
# Exercice 2 — stub (completer)# TODO: lancer InventingSignalingGame(4, 1, max_signals=2, temperature=0.6,# invention_rate=0.1, invention_cost=0.0), train(4000, anneal_to=0.15).# plafond_2_signaux = ... # theorique pour 4 etats, 2 signaux# print(f"Succes final = {g.success_rate(500):.3f}, plafond theo = {plafond_2_signaux:.3f}")print("Exercice 2 : a completer (stub sans erreur, C.1 OK).")
Exercice 2 : a completer (stub sans erreur, C.1 OK).
Exercice 3 — Asymétrie des états et invention ciblée
Jusqu’ici les états étaient uniformes. Donnez une distribution asymétriquestate_dist (ex. un état très fréquent, trois rares) avec n_states=4. L’agent va-t-il quand même inventer 4 signaux, ou se contenter de moins (les états rares ne génèrent pas assez d’échecs pour rentabiliser leur signal dédié) ? Construisez state_dist = [0.7, 0.1, 0.1, 0.1], lancez l’invention, et comparez le vocabulaire final au cas uniforme.
# Exercice 3 — stub (completer)# TODO: lancer InventingSignalingGame(4, 1, temperature=0.6, invention_rate=0.1,# invention_cost=0.0, state_dist=[0.7, 0.1, 0.1, 0.1]), train(4000, anneal_to=0.15).# Comparer vocab final a celui du cas uniforme (state_dist=None, i.e. equiprobable).# print(f"Vocab asymetrique = {...}, vocab uniforme = {...}")print("Exercice 3 : a completer (stub sans erreur, C.1 OK).")
Exercice 3 : a completer (stub sans erreur, C.1 OK).