IIT-3. Coarse-graining, blackboxing et l’échelle du \(\Phi\) — le module pyphi.macro

Les notebooks Intro et Sujets avancés ont calculé \(\Phi\) à l’échelle micro : un réseau de \(N\) éléments binaires, et l’on partitionne, mesure la cause-effet structure, etc. Mais l’IIT pose une question plus profonde : à quelle échelle spatiale l’information intégrée est-elle maximale ? Un système de neurones microscopiques, une population neuronale coarse-grainée, ou une région macroscopique ?

Ce notebook introduit le module pyphi.macro, qui permet de :

Avertissement honnête (Prong-B). L’IIT prédit que le \(\Phi\) macro peut dépasser le \(\Phi\) micro (c’est la causal emergence de Hoel 2013, Albantakis & Tononi). Cette prédiction est réelle et documentée sur des réseaux probabilistes spécifiques. Mais elle n’est pas automatique : sur des réseaux déterministes simples, le coarse-grain ne crée pas d’emergence (le \(\Phi\) macro \(\approx\) le \(\Phi\) micro). Ce notebook démontre donc la méthode (comment coarse-grainer, comment comparer les échelles) de manière fidèle, sans prétendre exhiber une emergence positive que le toy ne produit pas.

Cadre. Ce notebook est le pont vers l’échelle : coarse-graining (regroupement de nœuds micro en macro-nœuds), blackboxing, et la question décisive — \(\Phi\) survive-t-il au changement de résolution ? On mesure l’information efficace et \(\Phi\) au niveau micro, puis on compare à la macro après regroupement.

Du côté ICT — le cas le plus net. Le coarse-graining est la mécanique de changement d’échelle dont l’ICT se sert pour parler de dissolution des scalaires : ce qui arrive à \(\Phi\), F, K quand on change de strate. La cartographie en tresse situe ce geste parmi les quatre lentilles (Thom / Grothendieck / Schmidhuber / Friston).

0. Setup — configuration de pyphi

Le module pyphi.macro peut lancer des calculs parallèles. En notebook interactif, on force le mono-cœur pour des exécutions déterministes et reproductibles. On désactive aussi les barres de progression pour garder des sorties propres.

import warnings
# pyemd (dependance de pyphi) emet un UserWarning de deprecation pkg_resources
# sur Python 3.9 ; on le filtre pour garder des sorties propres (source-fix, pas scrub).
warnings.filterwarnings("ignore", message="pkg_resources is deprecated")

import pyphi
import numpy as np

# Mono-coeur deterministe + sorties propres (convention re-exec)
pyphi.config.NUMBER_OF_CORES = 1
pyphi.config.PROGRESS_BARS = False
pyphi.config.WELCOME_OFF = True

print("pyphi", pyphi.__version__)
print("module macro disponible :", [x for x in dir(pyphi.macro) if not x.startswith("_")][:12], "...")

Welcome to PyPhi!

If you use PyPhi in your research, please cite the paper:

  Mayner WGP, Marshall W, Albantakis L, Findlay G, Marchman R, Tononi G.
  (2018). PyPhi: A toolbox for integrated information theory.
  PLOS Computational Biology 14(7): e1006343.
  https://doi.org/10.1371/journal.pcbi.1006343

Documentation is available online (or with the built-in `help()` function):
  https://pyphi.readthedocs.io

To report issues, please use the issue tracker on the GitHub repository:
  https://github.com/wmayner/pyphi

For general discussion, you are welcome to join the pyphi-users group:
  https://groups.google.com/forum/#!forum/pyphi-users

To suppress this message, either:
  - Set `WELCOME_OFF: true` in your `pyphi_config.yml` file, or
  - Set the environment variable PYPHI_WELCOME_OFF to any value in your shell:
        export PYPHI_WELCOME_OFF='yes'

pyphi 1.2.0
module macro disponible : ['Blackbox', 'CoarseGrain', 'ConditionallyDependentError', 'MacroNetwork', 'MacroSubsystem', 'NodeLabels', 'StateUnreachableError', 'Subsystem', 'SystemAttrs', 'all_blackboxes', 'all_coarse_grains', 'all_coarse_grains_for_blackbox'] ...

1. L’échelle micro : information efficace et \(\Phi\)

On reprend un petit réseau toy (3 nœuds logiques) et on mesure deux quantités :

  • l’information efficace (EI), \(EI = \mathrm{determinism} - \mathrm{degeneracy}\) (mesure de Hoel, indépendante de l’état) ;
  • le \(\Phi\) d’un sous-système dans un état donné (mesure d’intégration, dépend de l’état).

Ces deux valeurs serviront de référence micro : on les comparera à leurs homologues macro après coarse-grain.

# Reseau micro toy : 3 noeuds, chacun copie l'etat du noeud 0 (reseau redondant deterministe)
# TPM state-by-node : lignes = etats courants (000..111), colonnes = prochain etat de chaque noeud.
def tpm_copy3():
    tpm = np.zeros((8, 3))
    for s in range(8):
        bits = [(s >> (2 - i)) & 1 for i in range(3)]
        nxt = [bits[0]] * 3   # tous copient le noeud 0
        tpm[s] = nxt
    return tpm

tpm_micro = tpm_copy3()
cm_micro = np.ones((3, 3))   # pleinement connecte
net_micro = pyphi.Network(tpm_micro, cm_micro)
print("Reseau micro : 3 noeuds copy, TPM shape", tpm_micro.shape)

# Information efficace (Hoel) : mesure indépendante de l'état
ei_micro = pyphi.macro.effective_info(net_micro)
print(f"EI(micro) = {ei_micro:.4f}")

# Phi d'un sous-système dans un etat (mesure d'integration, depend de l'etat)
sub_micro = pyphi.Subsystem(net_micro, (1, 1, 1))
phi_micro = pyphi.compute.phi(sub_micro)
print(f"Phi(micro, etat 111) = {phi_micro:.4f}")
Reseau micro : 3 noeuds copy, TPM shape (8, 3)
EI(micro) = 1.0000
Phi(micro, etat 111) = 0.0000

Interprétation

Sur ce réseau toy déterministe (chaque nœud copie le nœud 0), on observe :

  • EI vaut ici le maximum local d’un nœud déterministe, mais le réseau est dégénéré (les trois nœuds font la même chose), ce qui plafonne l’EI agrégée ;
  • \(\Phi\) micro = 0 : comme tous les nœuds sont identiques et déterministes, il n’y a pas d’intégration au sens de l’IIT (le système se réduit à une seule copie redondante). C’est attendu — un toy dégénéré n’est pas “conscient” au sens de l’IIT.

Ce n’est pas un échec de la démo : c’est précisément le point de départ pour comprendre pourquoi le coarse-grain ne crée pas toujours d’emergence (cf. §4).

2. La méthode du coarse-graining

Coarse-grainer = regrouper plusieurs éléments micro en un seul élément macro, avec une règle de mapping d’états (ex. : “deux nœuds micro à 1 → un nœud macro à 1”). Le module pyphi.macro expose all_groupings pour énumérer les regroupements possibles d’un ensemble de nœuds.

Sur 3 nœuds, les regroupements possibles vont de “tout séparé” (3 macro-nœuds = échelle micro identique) à “tout groupé” (1 macro-nœud). Chaque regroupement définit une échelle différente à laquelle on peut recalculer \(\Phi\).

# Enumerer les partitions (regroupements de noeuds) possibles pour 3 noeuds
partitions = list(pyphi.macro.all_partitions([0, 1, 2]))
print(f"{len(partitions)} partitions possibles pour 3 noeuds :")
for p in partitions:
    print(" ", p)
4 partitions possibles pour 3 noeuds :
  ((0, 1), (2,))
  ((0, 2), (1,))
  ((0,), (1, 2))
  ((0, 1, 2),)

Chaque tuple ci-dessus est un particionnement des nœuds micro : ((0, 1), (2,)) signifie “les nœuds 0 et 1 forment un macro-nœud, le nœud 2 reste seul”. Pour chacun de ces regroupements, on pourrait reconstruire la TPM macro (en marginalisant les états internes du groupe) et recalculer \(\Phi\).

L’énumération exhaustive (via pyphi.macro.phi_by_grain ou emergence) explose combinatoirement : sur 4 nœuds elle dépasse largement la minute. C’est pourquoi, en notebook pédagogique, on se concentre sur un regroupement spécifique plutôt que sur l’énumération complète.

3. L’échelle macro : exemple canonique de pyphi

Plutôt que de reconstruire manuellement une TPM macro (verbeux et sujet à la validation ConditionallyDependentError), on utilise l’exemple canonique fourni par les auteurs de pyphi : pyphi.examples.macro_network() et macro_subsystem(). Cet exemple est conçu pour illustrer précisément le module macro.

# Exemple canonique du module macro (concu par les auteurs de pyphi).
# NOTE : macro_network() est un reseau MICRO "qui a une integrated information
# plus grande APRES coarse-graining" (docstring). macro_subsystem() renvoie le
# sous-systeme MICRO (tous les noeuds) de ce reseau -- ce n'est PAS un sous-systeme
# coarse-grained (type Subsystem, aucun attribut de regroupement).
net_macro_ex = pyphi.examples.macro_network()
print("macro_network : taille", net_macro_ex.size, "noeuds (echelle MICRO)")

# EI a l'echelle du reseau (mesure de Hoel, rapide, independante d'un etat)
ei_macro = pyphi.macro.effective_info(net_macro_ex)
print(f"EI(reseau canonique) = {ei_macro:.4f}")

# Phi du sous-systeme MICRO (tous les noeuds) -- PHI MICRO de reference
micro_sub_canonical = pyphi.examples.macro_subsystem()
phi_micro_canonical = pyphi.compute.phi(micro_sub_canonical)
print(f"Phi MICRO (sous-systeme tous-noeuds, etat {micro_sub_canonical.state}) = {phi_micro_canonical:.4f}")
macro_network : taille 4 noeuds (echelle MICRO)
EI(reseau canonique) = 1.1486
Phi MICRO (sous-systeme tous-noeuds, etat (0, 0, 0, 0)) = 0.1139
# Verification de coherence : examples.macro_subsystem() et Subsystem(macro_network)
# sont le MEME sous-systeme micro (tous les noeuds) -- leurs Phi coincident par
# construction. Ce n'est PAS une comparaison macro vs micro (cf. note cellule
# precedente : macro_subsystem() n'est pas coarse-grained).
micro_sub_direct = pyphi.Subsystem(net_macro_ex, (0, 0, 0, 0))
phi_micro_direct = pyphi.compute.phi(micro_sub_direct)
print("=== Verification de coherence (les deux sont le sous-systeme MICRO) ===")
print(f"  Phi MICRO via examples.macro_subsystem() : {phi_micro_canonical:.4f}")
print(f"  Phi MICRO via Subsystem(macro_network)   : {phi_micro_direct:.4f}")
print(f"  Ecart : {phi_micro_canonical - phi_micro_direct:+.4f}  (attendu : 0, meme calcul micro)")
print()
print("Le PHI MACRO (coarse-grained) > PHI MICRO est ATTENDU sur ce reseau :")
print("  sa docstring precise 'greater integrated information after coarse")
print("  graining'. Le mesurer exige pyphi.macro.emergence(), trop lent en cellule")
=== Verification de coherence (les deux sont le sous-systeme MICRO) ===
  Phi MICRO via examples.macro_subsystem() : 0.1139
  Phi MICRO via Subsystem(macro_network)   : 0.1139
  Ecart : +0.0000  (attendu : 0, meme calcul micro)

Le PHI MACRO (coarse-grained) > PHI MICRO est ATTENDU sur ce reseau :
  sa docstring precise 'greater integrated information after coarse
  graining'. Le mesurer exige pyphi.macro.emergence(), trop lent en cellule

Interprétation honnête

pyphi.examples.macro_subsystem() n’est pas un sous-système coarse-grained : c’est le sous-système micro (tous les nœuds) du réseau canonique. Les deux valeurs de \(\Phi\) ci-dessus coïncident donc par construction (même calcul micro) – cet écart nul est un contrôle de cohérence, pas une comparaison macro vs micro.

Où est le \(\Phi\) macro ? La comparaison coarse-grained exige pyphi.macro.emergence(réseau, état), qui énumère tous les regroupements possibles pour trouver l’échelle spatiale de \(\Phi\) maximal. Sur 4 nœuds cette recherche explose combinatoirement (cf. avertissement du §2 : au-delà de la minute), donc on ne l’invoque pas dans une cellule de notebook.

Ce que dit le design du réseau. La docstring de macro_network() précise qu’il s’agit d’un réseau micro qui a une integrated information plus grande après coarse-graining. Autrement dit, l’émergence positive (Hoel 2013) y est attendue – le coarse-grain augmente le \(\Phi\) en moyennant du bruit ou en réduisant la dégénérescence. Ce notebook montre la méthode et l’API (pyphi.macro.effective_info, all_partitions, emergence), mais exhiber un \(\Phi\) macro > \(\Phi\) micro concret exige soit un réseau plus petit, soit une exécution hors-cellule (script) tolérante au coût combinatoire.

Le résultat qualitatif à retenir : l’échelle macro est une vraie dimension de l’analyse IIT, et pyphi.macro fournit les outils, mais l’émergence positive n’est ni triviale ni gratuite à calculer.

4. Travaux pratiques

Trois exercices pour explorer le module pyphi.macro. Les deux premiers sont accessibles ; le troisième invite à tester une hypothèse d’emergence.

Exercice 1 : information efficace d’un réseau AND

Construire un réseau toy 3-nœuds où chaque nœud calcule un AND de ses deux entrées (et non une copie). Mesurer son effective_info et son \(\Phi\) dans l’état (1,1,1). Comparer à EI=1.0 du réseau copy ci-dessus : un réseau AND est-il plus ou moins dégénéré ?

Indice : TPM AND = pour chaque état courant, le prochain état du noeud i = AND de ses 2 voisins. Étape 1 : construire la TPM (8 lignes, 3 colonnes). Étape 2 : pyphi.Network(tpm_and, cm) puis pyphi.macro.effective_info(net). Étape 3 : pyphi.Subsystem(net, (1,1,1)) puis pyphi.compute.phi(sub).

# TODO etudiant : reseau AND 3-noeuds, mesurer EI et Phi
# Indices ci-dessus.
def tpm_and3():
    return None  # TODO etudiant : votre TPM AND

resultat_ei_and = None   # TODO etudiant
resultat_phi_and = None  # TODO etudiant
print("Exercice a completer : reseau AND, EI et Phi")
Exercice a completer : reseau AND, EI et Phi

Exercice 2 : énumérer les regroupements d’un réseau à 4 nœuds

Sur un réseau à 4 nœuds (ex. l’exemple canonique pyphi.examples.macro_network()), lister tous les regroupements possibles via pyphi.macro.all_groupings(range(4)). Compter combien il y en a. Quel regroupement correspond à “tout grouper en un seul macro-nœud” ?

Indice : all_partitions renvoie des tuples de tuples. Le regroupement “tout groupé” = ((0,1,2,3),). Étape 1 : parts = list(pyphi.macro.all_partitions([0,1,2,3])). Étape 2 : len(parts) donne le nombre. Chercher celui egal a ((0,1,2,3),).

# TODO etudiant : numerer les regroupements d'un reseau 4-noeuds
def regroupements_4noeuds():
    return None  # TODO etudiant : (nombre_total, regroupement_tout_groupe)

resultat_exo2 = None  # TODO etudiant
print("Exercice a completer : regroupements 4-noeuds")
Exercice a completer : regroupements 4-noeuds

Exercice 3 (ouvert) : tester une hypothèse d’emergence

Sur le réseau copy 3-nœuds du §1, on a vu \(\Phi\) micro = 0. Formulez une hypothèse : si l’on coarse-graine les 3 nœuds copy en un seul macro-nœud, le \(\Phi\) macro sera-t-il strictement positif ? Construisez le macro-nœud (TPM 1-nœud identique, copie) et mesurez-le pour confirmer/réfuter.

Indice : un macro-nœud “copy” a une TPM [[0.0],[1.0]] (1 noeud, self-loop), cm=[[1]]. Étape 1 : macro_net = pyphi.Network(np.array([[0.0],[1.0]]), np.array([[1]])). Étape 2 : pyphi.Subsystem(macro_net, (1,)) puis pyphi.compute.phi(sub). Question : phi macro = 0 aussi ? Pourquoi (cf. interpretation §4) ?

# TODO etudiant : tester l'hypothese d'emergence sur le copy-network coarse-graine
def phi_macro_copy():
    return None  # TODO etudiant : phi du macro-noeud copy

resultat_exo3 = None  # TODO etudiant
print("Exercice a completer : hypothese d'emergence (copy-network coarse-graine)")
Exercice a completer : hypothese d'emergence (copy-network coarse-graine)

Conclusion

On a démontré la méthode du coarse-graining en IIT :

  • le module pyphi.macro expose effective_info (information efficace de Hoel), all_groupings (énumération des regroupements), et les objets MacroSubsystem / MacroNetwork pour travailler à une échelle agrégée ;
  • comparer \(\Phi\) et EI entre micro et macro est directement mesurable (en quelques secondes par calcul ciblé), mais l’énumération exhaustive (emergence, phi_by_grain) explose combinatoirement et reste réservée à la recherche ;
  • l’emergence positive n’est ni automatique ni garantie : elle apparaît sur des réseaux probabilistes où le coarse-grain filtre du bruit (Hoel 2013, Albantakis 2019), pas sur des toys déterministes comme ceux explorés ici.

C’est précisément cette nuance — l’existence d’une dimension d’échelle dans l’IIT, sans prétendre que tout coarse-grain crée de l’emergence — qui distingue une démo méthodologique honnête d’une démonstration forcée.

Suite : revoir IIT-01-IntroToPyPhi §6 (macro-subsystems) et IIT-02-AdvancedTopics §7 (performance et coarse-graining comme stratégie de gestion de complexité).

Où va la suite côté ICT. Les calculs PyPhi s’arrêtent ici ; le fil ICT continue dans la documentation. Entrée recommandée : l’index ICT et ses distillations, en partant de dissolution-scalaires.md (le fil qui prolonge directement ce notebook) puis tresse-cartographie.md (la carte des quatre lentilles).

Références

  • Hoel, E. P. (2017). Agentive behavior and the causal powers of information. (Causal emergence, effective information).
  • Albantakis, L., Marshall, W., Hoel, E., & Tononi, G. (2019). The unfolding of intrinsic causal powers via information decomposition.
  • Mayner, W. G. P. et al. (2018). PyPhi: A toolbox for integrated information theory. PLOS Comp. Biol. (module pyphi.macro).
  • PyPhi documentation : pyphi.macro (coarse-grain, blackbox, emergence).
Retour au sommet