gemma-3-270m-it-p2.8 / px_modules.py
neuralworm's picture
Upload folder using huggingface_hub
757ff71 verified
Raw
History Blame
4.82 kB
"""
gemma3-px — Pure Architectural Modules
==========================================
Zero-shot only. No trainable parameters beyond what is strictly necessary.
No OpenMythos baggage (no ACT, no LoRA, no probes, no epsilon).
Three modules:
LTIInjection — the core recurrence signal: h_new = trans_out + gamma*(e_norm - h)
ADCInjection — adaptive variant: gamma scales with instability (1-phi)
StabilityMonitor — parameter-free Phi / Lambda / Eta heuristics (logging only)
"""
import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import Optional
# ---------------------------------------------------------------------------
# 1. LTI Injection (Pure, fixed gamma)
# ---------------------------------------------------------------------------
class LTIInjection(nn.Module):
"""
Linear Time-Invariant anchor injection.
Provides 'Computational Headroom' by pulling h back toward the
frozen input embedding e whenever it drifts.
Formula:
h_new = transformer_out + gamma * (LayerNorm(e) - h)
Identity at t=0 if gamma=0. Optimal empirical gamma: 0.08.
"""
def __init__(self, dim: int, gamma: float = 0.08):
super().__init__()
self.gamma = gamma
# Affine=False: no trainable params, pure normalization
self.input_norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
def forward(
self,
h: torch.Tensor,
e: torch.Tensor,
transformer_out: torch.Tensor,
) -> torch.Tensor:
e_norm = self.input_norm(e.to(torch.float32)).to(h.dtype)
return transformer_out + self.gamma * (e_norm - h)
# ---------------------------------------------------------------------------
# 2. ADC Injection (Adaptive Dynamic Correction)
# ---------------------------------------------------------------------------
class ADCInjection(nn.Module):
"""
Adaptive variant of LTI: effective gamma = base_gamma + alpha*(1-phi).
When phi is high (state stable) → injection is gentle.
When phi drops (state drifting) → injection strengthens automatically.
No trainable parameters.
Args:
dim: hidden size
base_gamma: minimum injection strength (default 0.06)
alpha: maximum additional strength at full instability (default 0.10)
"""
def __init__(self, dim: int, base_gamma: float = 0.06, alpha: float = 0.10):
super().__init__()
self.base_gamma = base_gamma
self.alpha = alpha
self.input_norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)
def forward(
self,
h: torch.Tensor,
e: torch.Tensor,
transformer_out: torch.Tensor,
phi: float = 1.0, # Φ from previous loop (1.0 = fully stable)
) -> torch.Tensor:
instability = max(0.0, 1.0 - phi)
effective_gamma = self.base_gamma + self.alpha * instability
e_norm = self.input_norm(e.to(torch.float32)).to(h.dtype)
return transformer_out + effective_gamma * (e_norm - h)
# ---------------------------------------------------------------------------
# 3. Stability Monitor (no parameters — logging / diagnostics only)
# ---------------------------------------------------------------------------
class StabilityMonitor:
"""
Parameter-free heuristics for Phi (Φ), Lambda (λ), and Eta (η).
Phi — cosine similarity between consecutive hidden states (stability).
Lambda— cosine distance between current h and anchor e (drift).
Eta — variance-based entropy estimate (uncertainty).
"""
@staticmethod
def calculate_phi(h_new: torch.Tensor, h_old: torch.Tensor) -> torch.Tensor:
"""Φ ∈ [0,1]: 1 = identical state, 0 = orthogonal."""
B = h_new.shape[0]
# Safe FP32 for FP16 models
h_n_f32 = h_new.view(B, -1).to(torch.float32)
h_o_f32 = h_old.view(B, -1).to(torch.float32)
return F.cosine_similarity(h_n_f32, h_o_f32, dim=-1).mean()
@staticmethod
def detect_lambda(h: torch.Tensor, e: torch.Tensor) -> torch.Tensor:
"""λ ∈ [0,1]: 0 = h == e (no drift), 1 = fully diverged."""
B = h.shape[0]
sim = F.cosine_similarity(h.view(B, -1), e.view(B, -1), dim=-1).mean()
return (1.0 - sim).clamp(0.0, 1.0)
@staticmethod
def calculate_eta(h: torch.Tensor) -> torch.Tensor:
"""η ∈ [0,1]: variance-based uncertainty proxy. Recalibrated for Gemma-3 (var~67)."""
var = torch.var(h.to(torch.float32), dim=-1).mean()
# Scale 67.5 to ~0.5.
# (67.5 / 67.5) * 10 - 5 = 5 (sigmoid -> 0.99)
# (50 / 67.5) * 10 - 5 = 2.4 (sigmoid -> 0.9)
# (30 / 67.5) * 10 - 5 = -0.5 (sigmoid -> 0.37)
return torch.sigmoid((var / 67.5) * 10.0 - 5.0)