HAKO-v2 / hako_v2 /verification.py
PowerMachine's picture
HAKO-V2: fontes GPT-2 x2 + DINOv2, metricas SOM + verificacoes M1-M4
4f42a02 verified
Raw History Blame Contribute Delete
5.56 kB
"""Verificacoes matematicas do HAKO-V2 em runtime (teoremas corrigidos).
V2-M1 (T-ATTVAR / Minkowski): alpha e combinacao convexa => Var(z_attn) <=
max_e Var(v_e), qualquer tau. Verificacao empirica por banco.
V2-M2 (Dirichlet / passo seguro): energia de Dirichlet do Tree-GNN publicado
deve ser monotona nao-crescente nos passos registrados; ajuste do passo
com eta <= 2/lambda_max (lambda_max estimado por iteracao de potencia
no operador de mensagem W_msg).
V2-M3 (cota de Rademacher): R <= sqrt(1+(K-1)*rho_bar)/sqrt(K) com rho_bar a
correlacao media entre valores de especialistas; reportada por banco.
V2-M4 (Lemma 1 BPE): treino sharded == sequencial (verificador publicado).
"""
from __future__ import annotations
from typing import Dict, List
import numpy as np
import torch
def verify_moe_contraction(sys_, zs_list: List[dict], n_max: int = 128) -> Dict:
"""V2-M1: para cada banco presente, Var_i(z_attn) <= max_e Var_i(v_e)."""
moe = sys_.moe
out: Dict[str, Dict] = {}
with torch.no_grad():
for name in list(moe.banks):
zs = [d[name] for d in zs_list if name in d][:n_max]
if len(zs) < 8:
continue
Z = torch.stack(zs) # (n, d_src)
bankd = moe.banks[name]
K, A = bankd["K"], bankd["n_adapters"]
Wv = getattr(moe, f"Wv_{name}")
V = torch.stack([torch.stack(
[Wv @ (Z[i] @ getattr(moe, f"Ad_{name}_{e % A}"))
for i in range(Z.shape[0])]) for e in range(K)]) # (K,n,N)
var_e = V.var(dim=1).mean(dim=1) # (K,)
var_max = float(var_e.max())
# z_attn com alpha real do mecanismo publicado
zN = torch.stack([sys_.forward_sample({name: z}, train=False)["z"]
for z in zs[:32]])
zt = []
for zi, z_s in zip(zN, zs[:32]):
out_f, _ = moe(zi, {name: z_s})
zt.append(out_f)
var_attn = float(torch.stack(zt).var(dim=0).mean())
ok = var_attn <= var_max * 1.05 + 1e-9
out[name] = {
"var_attn": round(var_attn, 6),
"var_max_especialista": round(var_max, 6),
"razao": round(var_attn / max(var_max, 1e-12), 4),
"ok": bool(ok),
}
return {"teorema": "T-ATTVAR (Minkowski, combinacao convexa, tau livre)",
"bancos": out, "passou": all(v["ok"] for v in out.values())}
def verify_dirichlet(sys_) -> Dict:
"""V2-M2: energia registrada pelo Tree-GNN publicado deve nao-crescer;
lambda_max do operador estimado por iteracao de potencia em W_msg."""
tgnn = sys_.tgnn
energies = [float(e) for e in tgnn.last_energy] if tgnn.last_energy else []
W = tgnn.W_msg.detach()
v = torch.randn(W.shape[1])
v /= v.norm()
lam = 0.0
for _ in range(64):
w = W @ v
nrm = w.norm()
if nrm < 1e-12:
break
v = w / nrm
lam = float(nrm)
eta_safe = 2.0 / max(lam, 1e-9)
mono = all(energies[i + 1] <= energies[i] + 1e-9
for i in range(len(energies) - 1))
return {
"teorema": "T-GNN Dirichlet monotono com eta <= 2/lambda_max",
"energias": [round(e, 6) for e in energies[:8]],
"monotona": bool(mono) if energies else None,
"lambda_max_estimado": round(lam, 4),
"eta_seguro_publicado": round(min(0.35, eta_safe), 4),
"passou": bool(mono),
}
def verify_rademacher(sys_, zs_list: List[dict]) -> Dict:
"""V2-M3: cota efetiva por banco com rho_bar medido."""
moe = sys_.moe
out = {}
with torch.no_grad():
for name in list(moe.banks):
zs = [d[name] for d in zs_list if name in d][:64]
if len(zs) < 16:
continue
Z = torch.stack(zs)
bankd = moe.banks[name]
K, A = bankd["K"], bankd["n_adapters"]
Wv = getattr(moe, f"Wv_{name}")
V = torch.stack([torch.stack(
[Wv @ (Z[i] @ getattr(moe, f"Ad_{name}_{e % A}"))
for i in range(Z.shape[0])]) for e in range(K)])
Vf = V.reshape(K, -1) # (K, n*N)
Vf = Vf - Vf.mean(dim=1, keepdim=True)
Vn2 = Vf / (Vf.norm(dim=1, keepdim=True) + 1e-9)
C = Vn2 @ Vn2.T # (K, K)
off = C - torch.eye(C.shape[0]) * torch.diag(C)
rho = float(off.abs().mean())
Keff = K
bound = float(np.sqrt(1.0 + (Keff - 1) * rho) / np.sqrt(Keff))
out[name] = {"rho_bar": round(rho, 4), "K": Keff,
"cota_rademacher": round(bound, 4)}
return {"teorema": "cota de Rademacher sqrt(1+(K-1)rho)/sqrt(K)",
"bancos": out, "passou": True}
def verify_bpe_lemma(corpus_docs) -> Dict:
"""V2-M4: verificador publicada do Lemma 1 (BPE aditivo)."""
from hako.tokenizer.byte_bpe import ByteBPETokenizer
small = [d[:120] for d in corpus_docs[:60] if d]
tok_full = ByteBPETokenizer(vocab_size=300, min_freq=2, shards=1)
tok_full.train(small, log_every=0)
tok_shard = ByteBPETokenizer(vocab_size=300, min_freq=2, shards=4)
tok_shard.train(small, log_every=0)
ok = tok_full.merge_history == tok_shard.merge_history
return {"teorema": "Lemma 1 (BPE chunk-atomico, sharded == sequencial)",
"merges": len(tok_full.merge_history), "passou": bool(ok)}