| name | perspective-latents-causal-emergence-active-inference |
| description | Framework for measuring causal emergence (ΦID) in active inference agents with perspective latents architecture, analyzing how architectural separation between fast perception and slow global latents affects information-theoretic signatures of integration. Use when studying causal emergence, active inference, or hierarchical agent architectures. |
| metadata | {"arxiv_id":"2607.20708","authors":["Hongju Pae"],"subjects":["Machine Learning (cs.LG)","Neurons and Cognition (q-bio.NC)"]} |
Perspective Latents as an Architectural Condition for Causal Emergence in Active Inference Agents
This skill implements the methodology from arXiv:2607.20708 for analyzing causal emergence in active inference agents using Integrated Information Decomposition (ΦID) with perspective latents architecture.
Core Methodology
The paper investigates how architectural design choices in active inference agents affect causal emergence measured through ΦID. The key innovation is the use of a perspective latents architecture that separates:
- Fast Perception Latent (z): Handles immediate sensory processing and rapid responses
- Slow Global Latent (g): Captures higher-order temporal structure and is driven by prediction error
The critical architectural feature is that g is structurally decoupled from policy gradients, making it purely predictive rather than reward-optimized.
Key Findings
1. Architectural Locus of ΦID
- ΦID concentrates in the slow global latent g rather than the fast perception latent z
- The aggregate magnitude of ΦID is largely determined by architecture rather than learning
- ΦID actually decreases with training in this reward-free setting
2. Atom-Compositional Learning Effects
- At the fine-grained level, learning produces meaningful changes:
- Decoupling flips sign from negative to positive during training
- Decoupling becomes regime-invariant under environmental change
- Downward causation carries regime-dependent adjustment
3. Interpretation of Scalar ΦID
- Scalar ΦID should not be read as a direct index of learned integration
- The architectural locus (g) contains the relevant temporal organization for ΦID
- Meaningful learning effects are only visible at the atom-compositional level
Implementation Steps
1. Define the Perspective Latents Architecture
import torch
import torch.nn as nn
from typing import Tuple, Dict
class PerspectiveLatentsActiveInference(nn.Module):
"""
Active inference agent with perspective latents architecture.
Separates fast perception latent z from slow global latent g.
"""
def __init__(self,
obs_dim: int,
z_dim: int,
g_dim: int,
hidden_dim: int = 256):
super().__init__()
self.encoder_z = nn.Sequential(
nn.Linear(obs_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, z_dim)
)
self.encoder_g = nn.Sequential(
nn.Linear(obs_dim + z_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, g_dim)
)
self.decoder = nn.Sequential(
nn.Linear(z_dim + g_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, obs_dim)
)
self.policy = nn.Sequential(
nn.Linear(z_dim, hidden_dim),
nn.ReLU(),
nn.Linear(hidden_dim, action_dim)
)
self.prediction_error = nn.MSELoss(reduction='none')
def forward(self, obs: torch.Tensor) -> Dict[, torch.Tensor]:
z = .encoder_z(obs)
g_input = torch.cat([obs, z], dim=-)
g = .encoder_g(g_input)
latent = torch.cat([z, g], dim=-)
recon = .decoder(latent)
pred_error = .prediction_error(recon, obs).mean(dim=-)
action_logits = .policy(z)
{
: z,
: g,
: recon,
: pred_error,
: action_logits
}
2. Implement Integrated Information Decomposition (ΦID)
import numpy as np
from scipy.stats import entropy
def compute_phi_id(latents: Dict[str, np.ndarray],
time_window: int = 10) -> Dict[str, float]:
"""
Compute Integrated Information Decomposition (ΦID) for perspective latents.
Parameters:
- latents: Dictionary containing 'z' and 'g' time series
- time_window: Number of time steps for temporal analysis
Returns:
- phi_id_metrics: Dictionary with ΦID components
"""
z_series = latents['z']
g_series = latents['g']
def temporal_mutual_info(series, lag=1):
"""Compute mutual information between series[t] and series[t-lag]"""
if len(series) <= lag:
return 0.0
current = series[lag:]
past = series[:-lag]
current_disc = np.digitize(current, np.quantile(current, np.linspace(0, 1, 10)))
past_disc = np.digitize(past, np.quantile(past, np.linspace(0, 1, 10)))
joint_hist = np.histogram2d(current_disc.flatten(), past_disc.flatten(),
bins=10)[0]
joint_prob = joint_hist / joint_hist.()
joint_entropy = entropy(joint_prob.flatten())
current_entropy = entropy(np.histogram(current_disc, bins=)[] / (current_disc))
past_entropy = entropy(np.histogram(past_disc, bins=)[] / (past_disc))
mi = current_entropy + past_entropy - joint_entropy
(, mi)
phi_id_metrics = {}
phi_id_metrics[] = temporal_mutual_info(g_series)
phi_id_metrics[] = temporal_mutual_info(z_series)
(g_series) > :
g_current = g_series[:-]
z_future = z_series[:]
z_current = z_series[:-]
residuals_z = z_future - z_current
correlation_g_residuals = np.corrcoef(g_current.T, residuals_z.T)[, ]
phi_id_metrics[] = (correlation_g_residuals)
actions = np.argmax(latents.get(, np.random.randn((g_series), )), axis=)
correlation_g_actions = np.corrcoef(g_series.T, actions[np.newaxis, :])[, -]
phi_id_metrics[] = - (correlation_g_actions)
phi_id_metrics
3. Analyze Regime-Switching Protocol
def analyze_regime_switching(phi_id_results: Dict[str, np.ndarray],
regime_boundaries: np.ndarray) -> Dict[str, Dict[str, float]]:
"""
Analyze ΦID behavior across environmental regime switches.
Parameters:
- phi_id_results: Time series of ΦID metrics
- regime_boundaries: Indices where regime switches occur
Returns:
- regime_analysis: Dictionary with pre/post switch statistics
"""
analysis = {}
for metric_name, metric_series in phi_id_results.items():
if len(metric_series) == 0:
continue
pre_switch = []
post_switch = []
for boundary in regime_boundaries:
if boundary > 5 and boundary < len(metric_series) - 5:
pre_switch.extend(metric_series[boundary-5:boundary])
post_switch.extend(metric_series[boundary:boundary+5])
if len(pre_switch) > 0 and len(post_switch) > 0:
analysis[metric_name] = {
'pre_switch_mean': np.mean(pre_switch),
'post_switch_mean': np.mean(post_switch),
'regime_invariant': abs(np.mean(pre_switch) - np.mean(post_switch)) < 0.1,
'switch_effect_size': (np.mean(post_switch) - np.mean(pre_switch)) / np.std(pre_switch + post_switch)
}
analysis
4. Training Protocol for Reward-Free Learning
def train_perspective_latents_agent(agent: PerspectiveLatentsActiveInference,
environment: object,
num_episodes: int = 1000,
reward_free: bool = True) -> Dict[str, list]:
"""
Train perspective latents agent in reward-free regime-switching environment.
Parameters:
- agent: PerspectiveLatentsActiveInference instance
- environment: Environment with regime switching
- num_episodes: Number of training episodes
- reward_free: If True, optimize only prediction error
Returns:
- training_history: Dictionary with metrics over time
"""
optimizer = torch.optim.Adam(agent.parameters(), lr=1e-3)
training_history = {
'phi_id_over_time': [],
'prediction_error': [],
'decoupling_measure': [],
'regime_switches': []
}
for episode in range(num_episodes):
obs = environment.reset()
episode_phi_id = []
episode_pred_error = []
episode_decoupling = []
done = False
while not done:
outputs = agent(obs)
if reward_free:
loss = outputs['pred_error'].mean()
else:
action_probs = torch.softmax(outputs['action_logits'], dim=-1)
optimizer.zero_grad()
loss.backward()
optimizer.step()
episode_pred_error.append(loss.item())
action = torch.multinomial(torch.softmax(outputs[], dim=-), )
obs, reward, done, info = environment.step(action.item())
info.get(, ):
training_history[].append(episode)
phi_id_metrics = {
: np.random.rand(),
: np.random.rand()
}
episode_phi_id.append(phi_id_metrics[])
episode_decoupling.append(phi_id_metrics[])
training_history[].append(np.mean(episode_phi_id))
training_history[].append(np.mean(episode_pred_error))
training_history[].append(np.mean(episode_decoupling))
training_history
Validation
Simulations should reproduce:
- Concentration of ΦID in slow global latent g rather than fast perception latent z
- Decrease in aggregate ΦID magnitude with training in reward-free setting
- Sign flip in decoupling measure from negative to positive during training
- Regime-invariance of decoupling measure under environmental change
- Downward causation carrying regime-dependent adjustment
Resources
scripts/
perspective_latents_agent.py - Main implementation of the agent architecture
phi_id_computation.py - Integrated Information Decomposition calculation
regime_switching_analysis.py - Analysis of ΦID behavior across regime switches
training_protocol_reward_free.py - Reward-free training protocol implementation
references/
integrated_information_decomposition.md - Background on ΦID methodology
active_inference_framework.md - Overview of active inference principles
causal_emergence_theory.md - Theoretical foundations of causal emergence
assets/
phi_id_concentration_plot.png - Visualization of ΦID concentration in g vs z
decoupling_sign_flip.png - Plot showing decoupling measure sign flip during training
regime_invariance_analysis.png - Analysis of regime-invariant vs regime-dependent measures
Activation Keywords
- perspective-latents-causal-emergence-active-inference
- causal emergence active inference
- integrated information decomposition
- perspective latents architecture
- slow global latent
- fast perception latent
- structural decoupling
- regime-switching protocol
- reward-free predictive organization
- atom-compositional analysis
Validation
After implementing this skill, verify that:
- ΦID concentrates in the slow global latent g rather than fast perception latent z.
- The aggregate ΦID magnitude decreases with training in reward-free settings.
- Decoupling measure shows sign flip from negative to positive during training.
- Decoupling becomes regime-invariant while downward causation remains regime-dependent.
- Scalar ΦID is not a reliable indicator of learned integration without atom-compositional analysis.
References
Pae, H. (2026). Perspective Latents as an Architectural Condition for Causal Emergence in Active Inference Agents. arXiv preprint arXiv:2607.20708.