V3.2: corrigir 6 bugs + meta_T_moved (T_tracking_loss) + re-teste com Xeon IPEX 2.8 + AMX
a22ed76 verified Download src/bigru_t/training/hypothesis_monitor.py from PowerMachine/BiGRU_T_version: direct link, hf CLI and curl.
- Browser
- Download file 15.5 kB
-
https://huggingface.co/PowerMachine/BiGRU_T_version/resolve/main/src/bigru_t/training/hypothesis_monitor.py
- Command line
-
hf download hf://PowerMachine/BiGRU_T_version/src/bigru_t/training/hypothesis_monitor.py
-
curl -L -o hypothesis_monitor.py https://huggingface.co/PowerMachine/BiGRU_T_version/resolve/main/src/bigru_t/training/hypothesis_monitor.py
15.5 kB
| """hypothesis_monitor.py — Detector de ativação das hipóteses (L1-L4). | |
| Filosofia: "se as hipóteses não são ativadas durante punição, há um bug". | |
| Cada um dos 4 lemas tem uma condição de ativação observável: | |
| L1 (ModuleSelector): α = softmax(logits/T) — ativa quando há variação em α | |
| (entropy < log(K) - ε). Se entropy ≈ log(K), nenhum módulo é selecionado | |
| (todos com peso igual) — possível bug no temperature ou nos logits. | |
| L2 (GradientSurgery): ativa quando use_hyp=True e apply_gradient_surgery | |
| modifica os gradientes. Se ||g_hyp|| ≈ 0 ou projeção ortogonal ≈ 0, | |
| a cirurgia é no-op (possível bug: loss_hyp não tem gradiente). | |
| L3 (HypT): ativa quando loss > τ (modelo está "lutando"). Se loss > τ mas | |
| use_hyp=False (não foi ativada), é bug. Se use_hyp=True mas ||delta|| ≈ 0, | |
| a hipótese não contribui (possível bug: HypT morta ou stop_grad excessivo). | |
| L4 (MetaConfigurator): ativa a cada meta_interval passos. Se T e τ não mudam | |
| entre chamadas, o meta-otimizador está estagnado (possível bug: lr=0 ou | |
| gradientes None). | |
| O monitor mantém contadores e dispara alertas quando: | |
| - Punishment_count > 0 mas activation_count = 0 (hipótese nunca ativada) | |
| - Activation_count > 0 mas delta_norm_medio < epsilon (HypT morta) | |
| - T ou τ não mudam em N chamadas do meta (estagnação) | |
| - Entropy do L1 saturada (> 0.95 * log(K)) — sem seleção real | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| import math | |
| from collections import deque | |
| from dataclasses import dataclass, field | |
| from typing import Optional | |
| import torch | |
| logger = logging.getLogger(__name__) | |
| class LemmaState: | |
| """Snapshot do estado de ativação de cada lema em um step.""" | |
| step: int | |
| # L1 | |
| alpha_entropy: float = 0.0 | |
| alpha_max: float = 0.0 | |
| alpha_active_modules: int = 0 | |
| temperature: float = 1.0 | |
| l1_activated: bool = False # True se entropy < 0.95 * log(K) | |
| # L2 | |
| l2_applied: bool = False | |
| grad_main_norm: float = 0.0 | |
| grad_hyp_norm: float = 0.0 | |
| orth_proj_norm: float = 0.0 | |
| # L3 | |
| loss_main: float = 0.0 | |
| tau: float = float("inf") | |
| use_hyp_activated: bool = False # True se use_hyp=True | |
| delta_norm: float = 0.0 # ||delta||₂ — se 0, HypT morta | |
| punishment_triggered: bool = False # True se loss > τ | |
| # L4 | |
| T_new: float = 1.0 | |
| tau_new: float = 1.0 | |
| sharpness: float = 0.0 | |
| l4_meta_called: bool = False | |
| l4_T_moved: bool = False | |
| l4_tau_moved: bool = False | |
| # Circular Reasoning (Teorema 4) | |
| crw_converged: bool = False | |
| crw_w2_final: float = 0.0 | |
| crw_q_avg: float = 1.0 | |
| crw_contraction_valid: bool = False | |
| class HypothesisMonitorReport: | |
| """Relatório final do monitor.""" | |
| total_steps: int = 0 | |
| punishment_steps: int = 0 # steps com loss > τ | |
| hyp_activated_steps: int = 0 # steps com use_hyp=True | |
| hyp_activated_during_punishment: int = 0 # ⚠️ chave: punição E ativação | |
| delta_zero_when_activated: int = 0 # ⚠️ bug: HypT morta | |
| l1_entropy_saturated_steps: int = 0 # ⚠️ bug: sem seleção | |
| l2_zero_grad_hyp_steps: int = 0 # ⚠️ bug: loss_hyp sem grad | |
| l4_T_stagnation: int = 0 # ⚠️ bug: T não move | |
| l4_tau_stagnation: int = 0 # ⚠️ bug: τ não move | |
| crw_converged_steps: int = 0 | |
| crw_contraction_invalid_steps: int = 0 # ⚠️ bug: W₂ cresceu | |
| last_T: float = 1.0 | |
| last_tau: float = 1.0 | |
| history: list = field(default_factory=list) | |
| def has_bug(self) -> bool: | |
| """True se algum bug provável foi detectado.""" | |
| # Punição ocorreu mas hipótese nunca ativada — BUG CRÍTICO | |
| if self.punishment_steps > 0 and self.hyp_activated_during_punishment == 0: | |
| return True | |
| # Hipótese ativada mas delta sempre zero — HypT morta | |
| if self.hyp_activated_steps > 0 and self.hyp_activated_steps == self.delta_zero_when_activated: | |
| return True | |
| # L1 saturada em mais de 80% dos steps | |
| if self.total_steps > 5 and self.l1_entropy_saturated_steps > 0.8 * self.total_steps: | |
| return True | |
| # CRW com contração inválida em mais de 50% dos steps | |
| if self.crw_contraction_invalid_steps > 0.5 * max(1, self.total_steps): | |
| return True | |
| return False | |
| def bug_summary(self) -> list[str]: | |
| bugs = [] | |
| if self.punishment_steps > 0 and self.hyp_activated_during_punishment == 0: | |
| bugs.append( | |
| f"CRÍTICO: {self.punishment_steps} passos de punição (loss>τ) " | |
| f"mas hipótese nunca ativada — verifique tau e use_hypothesis" | |
| ) | |
| if self.hyp_activated_steps > 0 and self.hyp_activated_steps == self.delta_zero_when_activated: | |
| bugs.append( | |
| f"CRÍTICO: hipótese ativada {self.hyp_activated_steps}x mas " | |
| f"||delta|| sempre zero — HypT morta ou stop_grad excessivo" | |
| ) | |
| if self.total_steps > 5 and self.l1_entropy_saturated_steps > 0.8 * self.total_steps: | |
| bugs.append( | |
| f"ALERTA: L1 entropy saturada em {self.l1_entropy_saturated_steps}/{self.total_steps} " | |
| f"passos — module_selector não está selecionando" | |
| ) | |
| if self.l4_T_stagnation > 3: | |
| bugs.append( | |
| f"ALERTA: T não mudou em {self.l4_T_stagnation} chamadas meta — " | |
| f"meta_otim estagnado" | |
| ) | |
| if self.crw_contraction_invalid_steps > 0.5 * max(1, self.total_steps): | |
| bugs.append( | |
| f"ALERTA: CRW contração inválida em " | |
| f"{self.crw_contraction_invalid_steps}/{self.total_steps} passos — " | |
| f"W₂ cresceu em vez de contrair" | |
| ) | |
| return bugs | |
| class HypothesisMonitor: | |
| """Monitora ativação dos 4 lemas + CircularReasoning durante o treino. | |
| Uso: | |
| monitor = HypothesisMonitor(max_history=100) | |
| # No loop de treino, após cada micro-batch: | |
| state = monitor.record( | |
| step=global_step, | |
| alpha=aux["alpha"], # (K,) tensor | |
| entropy_reg=aux["entropy_reg"], | |
| loss_main=loss_main.item(), | |
| tau=model.tau.item(), | |
| use_hyp=use_hyp, | |
| delta=delta, | |
| temperature=meta_cfg.temperature, | |
| circular_info=aux.get("circular_info"), | |
| ) | |
| # Após cada meta step: | |
| monitor.record_meta(T_new, tau_new, sharpness) | |
| # Ao final: | |
| report = monitor.summary() | |
| if report.has_bug: | |
| for bug in report.bug_summary: | |
| logger.error(bug) | |
| """ | |
| def __init__( | |
| self, | |
| max_modules: int = 8, | |
| delta_epsilon: float = 1e-4, | |
| meta_stagnation_epsilon: float = 1e-4, | |
| history_size: int = 200, | |
| ): | |
| self.max_modules = max_modules | |
| self.delta_epsilon = delta_epsilon | |
| self.meta_stagnation_epsilon = meta_stagnation_epsilon | |
| self.history_size = history_size | |
| self._history: deque = deque(maxlen=history_size) | |
| # Acumuladores para relatório | |
| self._punishment_steps = 0 | |
| self._hyp_activated_steps = 0 | |
| self._hyp_activated_during_punishment = 0 | |
| self._delta_zero_when_activated = 0 | |
| self._l1_entropy_saturated_steps = 0 | |
| self._l2_zero_grad_hyp_steps = 0 | |
| self._crw_converged_steps = 0 | |
| self._crw_contraction_invalid_steps = 0 | |
| # Meta tracking (L4) | |
| self._last_T: float = 1.0 | |
| self._last_tau: float = 1.0 | |
| self._T_stagnation_count: int = 0 | |
| self._tau_stagnation_count: int = 0 | |
| self._meta_calls: int = 0 | |
| # L2 tracking | |
| self._last_l2_applied: bool = False | |
| self._last_grad_hyp_norm: float = 0.0 | |
| self._last_orth_proj_norm: float = 0.0 | |
| def record( | |
| self, | |
| step: int, | |
| alpha: Optional[torch.Tensor] = None, | |
| entropy_reg: float = 0.0, | |
| loss_main: float = 0.0, | |
| tau: float = float("inf"), | |
| use_hyp: bool = False, | |
| delta: Optional[torch.Tensor] = None, | |
| temperature: float = 1.0, | |
| circular_info: Optional[dict] = None, | |
| l2_applied: bool = False, | |
| grad_main_norm: float = 0.0, | |
| grad_hyp_norm: float = 0.0, | |
| orth_proj_norm: float = 0.0, | |
| ) -> LemmaState: | |
| """Registra estado de um step. Retorna LemmaState para inspeção imediata.""" | |
| # L1: entropy e max(alpha) | |
| if alpha is not None: | |
| alpha = alpha.detach().float() | |
| # alpha pode ser (K,) ou (B, K) — reduzir para (K,) | |
| if alpha.dim() > 1: | |
| alpha = alpha.mean(dim=0) | |
| alpha_entropy = float(-(alpha * torch.log(alpha + 1e-10)).sum().item()) | |
| alpha_max = float(alpha.max().item()) | |
| alpha_active = int((alpha > 0.01).sum().item()) | |
| # L1 ativa se entropy < 0.95 * log(K) (seleção real está acontecendo) | |
| max_entropy = math.log(self.max_modules) | |
| l1_activated = alpha_entropy < 0.95 * max_entropy | |
| if not l1_activated: | |
| self._l1_entropy_saturated_steps += 1 | |
| else: | |
| alpha_entropy = 0.0 | |
| alpha_max = 0.0 | |
| alpha_active = 0 | |
| l1_activated = False | |
| # L3: punição e delta | |
| punishment_triggered = loss_main > tau | |
| if punishment_triggered: | |
| self._punishment_steps += 1 | |
| if use_hyp: | |
| self._hyp_activated_steps += 1 | |
| if punishment_triggered: | |
| self._hyp_activated_during_punishment += 1 | |
| # Verifica se delta é significativo | |
| if delta is not None: | |
| delta_norm = float(delta.detach().float().norm().item()) | |
| if delta_norm < self.delta_epsilon: | |
| self._delta_zero_when_activated += 1 | |
| else: | |
| delta_norm = 0.0 | |
| self._delta_zero_when_activated += 1 | |
| else: | |
| delta_norm = 0.0 | |
| # L2 tracking (será preenchido por record_l2 após backward) | |
| self._last_l2_applied = l2_applied | |
| self._last_grad_hyp_norm = grad_hyp_norm | |
| self._last_orth_proj_norm = orth_proj_norm | |
| if l2_applied and grad_hyp_norm < 1e-10: | |
| self._l2_zero_grad_hyp_steps += 1 | |
| # Circular Reasoning | |
| crw_converged = False | |
| crw_w2_final = 0.0 | |
| crw_q_avg = 1.0 | |
| crw_contraction_valid = True | |
| if circular_info is not None: | |
| crw_converged = bool(circular_info.get("converged", False)) | |
| crw_w2_final = float(circular_info.get("w2_final", 0.0)) | |
| crw_q_avg = float(circular_info.get("q_empirical_avg", 1.0)) | |
| crw_contraction_valid = bool(circular_info.get("contraction_valid", True)) | |
| if crw_converged: | |
| self._crw_converged_steps += 1 | |
| if not crw_contraction_valid: | |
| self._crw_contraction_invalid_steps += 1 | |
| state = LemmaState( | |
| step=step, | |
| alpha_entropy=alpha_entropy, | |
| alpha_max=alpha_max, | |
| alpha_active_modules=alpha_active, | |
| temperature=temperature, | |
| l1_activated=l1_activated, | |
| l2_applied=l2_applied, | |
| grad_main_norm=grad_main_norm, | |
| grad_hyp_norm=grad_hyp_norm, | |
| orth_proj_norm=orth_proj_norm, | |
| loss_main=loss_main, | |
| tau=tau, | |
| use_hyp_activated=use_hyp, | |
| delta_norm=delta_norm, | |
| punishment_triggered=punishment_triggered, | |
| T_new=self._last_T, | |
| tau_new=self._last_tau, | |
| l4_meta_called=False, | |
| crw_converged=crw_converged, | |
| crw_w2_final=crw_w2_final, | |
| crw_q_avg=crw_q_avg, | |
| crw_contraction_valid=crw_contraction_valid, | |
| ) | |
| self._history.append(state) | |
| return state | |
| def record_meta( | |
| self, | |
| T_new: float, | |
| tau_new: float, | |
| sharpness: float = 0.0, | |
| ) -> None: | |
| """Registra resultado de um passo do MetaConfigurator (L4).""" | |
| self._meta_calls += 1 | |
| # Detecta estagnação | |
| if abs(T_new - self._last_T) < self.meta_stagnation_epsilon: | |
| self._T_stagnation_count += 1 | |
| else: | |
| self._T_stagnation_count = 0 | |
| if abs(tau_new - self._last_tau) < self.meta_stagnation_epsilon: | |
| self._tau_stagnation_count += 1 | |
| else: | |
| self._tau_stagnation_count = 0 | |
| self._last_T = T_new | |
| self._last_tau = tau_new | |
| def summary(self) -> HypothesisMonitorReport: | |
| """Gera relatório final com detecção de bugs.""" | |
| report = HypothesisMonitorReport( | |
| total_steps=len(self._history), | |
| punishment_steps=self._punishment_steps, | |
| hyp_activated_steps=self._hyp_activated_steps, | |
| hyp_activated_during_punishment=self._hyp_activated_during_punishment, | |
| delta_zero_when_activated=self._delta_zero_when_activated, | |
| l1_entropy_saturated_steps=self._l1_entropy_saturated_steps, | |
| l2_zero_grad_hyp_steps=self._l2_zero_grad_hyp_steps, | |
| l4_T_stagnation=self._T_stagnation_count, | |
| l4_tau_stagnation=self._tau_stagnation_count, | |
| crw_converged_steps=self._crw_converged_steps, | |
| crw_contraction_invalid_steps=self._crw_contraction_invalid_steps, | |
| last_T=self._last_T, | |
| last_tau=self._last_tau, | |
| history=[s.__dict__ for s in list(self._history)[-20:]], # últimos 20 | |
| ) | |
| return report | |
| def log_summary(self) -> None: | |
| """Imprime relatório no log.""" | |
| r = self.summary() | |
| logger.info("=" * 60) | |
| logger.info("HIPÓTESE MONITOR — RELATÓRIO DE ATIVAÇÃO") | |
| logger.info("=" * 60) | |
| logger.info(f" Total steps: {r.total_steps}") | |
| logger.info(f" Punição (loss > τ): {r.punishment_steps}") | |
| logger.info(f" Hipótese ativada (use_hyp=True): {r.hyp_activated_steps}") | |
| logger.info(f" Hipótese ativada DURANTE punição: {r.hyp_activated_during_punishment}") | |
| logger.info(f" ||delta||≈0 quando ativada: {r.delta_zero_when_activated}") | |
| logger.info(f" L1 entropy saturada: {r.l1_entropy_saturated_steps}") | |
| logger.info(f" L2 grad_hyp≈0: {r.l2_zero_grad_hyp_steps}") | |
| logger.info(f" L4 T estagnado: {r.l4_T_stagnation}") | |
| logger.info(f" L4 τ estagnado: {r.l4_tau_stagnation}") | |
| logger.info(f" CRW convergiu: {r.crw_converged_steps}") | |
| logger.info(f" CRW contração inválida: {r.crw_contraction_invalid_steps}") | |
| logger.info(f" T final: {r.last_T:.4f}") | |
| logger.info(f" τ final: {r.last_tau:.4f}") | |
| if r.has_bug: | |
| logger.error("=" * 60) | |
| logger.error("⚠️ BUGS DETECTADOS:") | |
| for bug in r.bug_summary: | |
| logger.error(f" - {bug}") | |
| logger.error("=" * 60) | |
| else: | |
| logger.info(" ✓ Nenhum bug crítico detectado pelo monitor") | |
| logger.info("=" * 60) | |
| __all__ = ["HypothesisMonitor", "HypothesisMonitorReport", "LemmaState"] | |