khtst-rust / scripts /61_treino_v070.py
PowerMachine's picture
v0.7.0: FNH gate de punição + árvore de pesos indexada (arestas duplas) + quebra-cabeça do Pensamento + NLP/NLG + decodificador especulativo + auto-ajuste SOM limitado + correções v070-1/2/3 — 73/73 gates, 84/84 cargo, provas r-28..r-32
4dbc907 verified
Raw History Blame Contribute Delete
8.45 kB
#!/usr/bin/env python3
"""61_treino_v070.py — v0.7.0: treino REAL (fases A/B/C) + árvore de pesos
indexada com métricas por módulo + FNH com punição REAL da fase C + painel
de telemetria v070 (r-28 §5, r-32).
Pipeline com dados REAIS (Wikipédia PT-BR, streaming controlado):
fase A — tokenizador GSQ+RCO (300 passos);
fase B — gerador NCM (300 passos, teto 300s);
fase C — treino conjunto (180 passos, teto 420s) — telemetria de punição;
árvore — contagens de parâmetros por módulo (estimativas documentadas)
+ métricas REAIS por módulo da telemetria das fases;
FNH — gate alimentado pela punição NORMALIZADA medida na fase C.
Modo RESUME: se a telemetria da fase C já existe com dump final, extrai as
métricas dela (não re-treina — o fundo pode matar processos sem erro/OOM).
Saída: resultados/treino_v070.json
"""
import json, os, sys, time
CONTAGENS = { # estimativas documentadas (a árvore INDEXA; métricas medem)
"tronco": 10_000_000, "quantizador": 1_200_000, "som": 300_000,
"jepa": 900_000, "moe": 800_000, "pensamento": 400_000,
"verificador": 10_000, "fnh": 150_000, "nlp": 300_000,
"nlg": 250_000, "acoplador": 60_000,
}
def extrai_fase_c(caminho):
"""Extrai as métricas do dump FINAL da telemetria da fase C."""
with open(caminho) as f:
linhas = [json.loads(l) for l in f]
dumps = [l["dados"] for l in linhas if l.get("tipo") == "dump"]
if not dumps:
return None
d = dumps[-1]
def serie(k):
return d.get(k, []) if isinstance(d.get(k), list) else []
def v(k, i=-1):
s = serie(k)
return s[i][1] if s else 0.0
n_passos = len(serie("perda"))
return {
"passos": n_passos,
"ce_inicial": v("perda", 0), "ce_final": v("perda"),
"ce_gatilhada_com_final": v("ce_gatilhada_com"),
"ce_gatilhada_sem_final": v("ce_gatilhada_sem"),
"confianca_inicial": v("confianca_media", 0),
"confianca_final": v("confianca_media"),
"confianca_pos_correcao_final": v("confianca_pos_correcao"),
"taxa_gatilho_media": (sum(x[1] for x in serie("taxa_gatilho"))
/ max(1, len(serie("taxa_gatilho")))),
"ece_final": v("ece_pos_calibracao"),
"temperatura_calibrada": v("temperatura_calibrada"),
"norma_grad_final": v("norma_grad"),
}
def main():
pasta = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, pasta)
os.makedirs(os.path.join(pasta, "resultados"), exist_ok=True)
import khtst_rust as K
cfg = K.Config(os.path.join(pasta, "configs", "base_rust.json"))
ck_tok = os.path.join(pasta, "resultados", "tokenizador_conceitos.json")
ck_ger = os.path.join(pasta, "resultados", "gerador_conceitos.json")
tel_c = os.path.join(pasta, "resultados", "telemetria_fase_c.jsonl")
bpe = K.Bpe.carregar(os.path.join(pasta, "dados", "bpe.json"))
seqs = []
with open(os.path.join(pasta, "dados", "shard_treino.jsonl")) as f:
for linha in f:
ids = bpe.codificar(json.loads(linha)["texto"])
for i in range(0, max(1, len(ids) - 256), 128):
seqs.append(ids[i:i + 256])
seqs = seqs[:1400]
rel = {"versao": "0.7.0", "dados": {"sequencias": len(seqs),
"fonte": "wikimedia/wikipedia 20231101.pt"}, "fases": {}}
print(f"sequências de treino: {len(seqs)} (ctx=256)", flush=True)
# -------------------------------- fase A
if not os.path.exists(ck_tok):
print("=== FASE A — tokenizador (GSQ+RCO Stiefel) ===", flush=True)
t0 = time.time()
saida = K.treinar_fase_a(cfg, seqs, caminho_telemetria=None,
caminho_checkpoint=ck_tok)
rel["fases"]["a"] = {**saida["resumo"], "tempo_s": time.time() - t0}
else:
print("fase A: checkpoint presente — reutilizando", flush=True)
# -------------------------------- fase B
if not os.path.exists(ck_ger):
print("=== FASE B — gerador NCM ===", flush=True)
t0 = time.time()
saida_b = K.treinar_fase_b(cfg, seqs, caminho_tokenizador=ck_tok,
caminho_telemetria=None,
caminho_checkpoint=ck_ger, teto_seg=300.0)
rel["fases"]["b"] = {**saida_b["resumo"], "tempo_s": time.time() - t0}
else:
print("fase B: checkpoint presente — reutilizando", flush=True)
# -------------------------------- fase C (com resume)
resume = None
if os.path.exists(tel_c):
resume = extrai_fase_c(tel_c)
if resume and resume.get("passos", 0) >= 100:
print(f"fase C: telemetria presente ({resume['passos']} passos) — "
"extraindo métricas (resume)", flush=True)
if resume is None:
print("=== FASE C — treino conjunto (punição p/ FNH) ===", flush=True)
t0 = time.time()
saida_c = K.treinar_fase_c(cfg, seqs, caminho_tokenizador=ck_tok,
passos=180, caminho_gerador=ck_ger,
caminho_telemetria=tel_c, teto_seg=420.0)
rc = saida_c["resumo"]
rc["tempo_s"] = time.time() - t0
rel["fases"]["c"] = rc
else:
rel["fases"]["c"] = resume
rc = rel["fases"]["c"]
print(f" CE {rc.get('ce_inicial', 0):.4f} -> {rc.get('ce_final', 0):.4f} | "
f"conf {rc.get('confianca_inicial', 0):.4f} -> {rc.get('confianca_final', 0):.4f} | "
f"gatilho {rc.get('taxa_gatilho_media', 0):.3f} | ECE {rc.get('ece_final', 0):.4f}",
flush=True)
# -------------------------------- árvore de pesos (v0.7.0)
print("=== ÁRVORE DE PESOS — métricas por módulo ===", flush=True)
arv = K.ArvorePesos.nova(CONTAGENS)
assert arv.invariantes_ok(), "T-A1 invariantes"
arv.definir_metrica("tronco", "confianca", rc.get("confianca_final", 0.0))
arv.definir_metrica("quantizador", "perda",
rel["fases"].get("a", {}).get("perda_final", 0.0))
arv.definir_metrica("quantizador", "punicao",
rel["fases"].get("a", {}).get("delta_ort_max", 0.0) * 1e6)
arv.definir_metrica("nlg", "perda", rel["fases"].get("b", {}).get("perda_final", 0.0))
arv.definir_metrica("pensamento", "confianca",
rc.get("confianca_pos_correcao_final", 0.0))
# punição do pensamento: ECE (erro de calibração) + (1 − taxa_gatilho)
arv.definir_metrica("pensamento", "punicao",
rc.get("ece_final", 0.0) * 5.0)
arv.definir_metrica("verificador", "punicao", rc.get("ece_final", 0.0))
tot_conf = arv.agregar("confianca")
tot_puni = arv.agregar("punicao")
arv.regular("khtst", 0.1, 0.5) # T-A3 exemplo de regulação
rel["arvore"] = {
"invariantes": arv.invariantes_ok(),
"total_confianca": tot_conf, "total_punicao": tot_puni,
"dump": arv.dump(),
}
print(f" invariantes OK | Σconf={tot_conf:.4f} Σpunicao={tot_puni:.4f}", flush=True)
# -------------------------------- FNH (v0.7.0) — punição REAL
print("=== FNH — gate de punição ===", flush=True)
# punição normalizada: ECE da calibração (0 = perfeito) mapeado por
# 5× (teto ECE aceitável 0,2) — sinal REAL da fase C
pun_norm = min(1.0, rc.get("ece_final", 0.0) / 0.2)
fnh = K.demo_fnh()
rel["fnh"] = {
"punicao_normalizada_fase_c": pun_norm,
"abacao_sintetica": fnh["resumo"],
"gates": {
"gate_abre_com_punicao_alta":
fnh["resumo"]["punicao_alta"]["gate_final"] > 0.5,
"gate_fecha_com_punicao_baixa":
fnh["resumo"]["punicao_baixa"]["gate_final"] == 0.0,
"rotacao_aprende": fnh["resumo"]["punicao_alta"]["theta_norma"] > 0.0,
"so_n_exato": fnh["resumo"]["punicao_alta"]["delta_ort"] < 1e-6,
},
}
print(f" π(C)={pun_norm:.3f} | alta: gate {fnh['resumo']['punicao_alta']['gate_final']:.3f}, "
f"θ {fnh['resumo']['punicao_alta']['theta_norma']:.4f}, "
f"δ_ort {fnh['resumo']['punicao_alta']['delta_ort']:.1e}", flush=True)
with open(os.path.join(pasta, "resultados", "treino_v070.json"), "w") as f:
json.dump(rel, f, indent=1, ensure_ascii=False)
print("OK: resultados/treino_v070.json", flush=True)
if __name__ == "__main__":
main()