khtst-rust / scripts /55_verificador_ncm.py
PowerMachine's picture
v0.6.0: verificador NCM calibrado (sem oráculo, V-1..V-4) + treino conjunto Pensamento↔backbone (fase C, PCGrad, acoplador duplex AC) + MoEs redirecionáveis c/ atenção própria (M-R1..M-R5, JEPA+SOM) + autoajuste por telemetria (A-1..A-5, UCB1) — 46/46 gates, provas r-23..r-27
bb2363d verified
Raw History Blame Contribute Delete
4.96 kB
#!/usr/bin/env python3
"""55_verificador_ncm.py — v0.6.0: o validador do Pensamento passa a ser a
PRÓPRIA CONFIANÇA DO NCM, calibrada (r-21 §3.1 fechado; provas r-23).
Demos:
1. calibração de temperatura em dados retidos (V-1): T*, ECE antes/depois;
2. soundness sem oráculo (V-2): P(erro|aceito) ≤ 1−τ_c+ECE+folga;
3. τ_c por quantil DKW (V-3);
4. ciclo d do Pensamento com o verificador NCM (produção, sem oráculo)
— ganho de confiança vs 1 rede isolada;
5. escalonamento com N sob o verificador NCM.
Saída: resultados/verificador_ncm_v060.json
"""
import json, os, time
def main():
import khtst_rust.nucleo_rust as nr
pasta = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
res = {"versao": "0.6.0", "modulo": nr.versao(), "demos": {}}
# -------------------------------------------- 1-3: calibração + soundness
print("=== Verificador NCM: calibração (V-1) + soundness (V-2) + DKW (V-3) ===", flush=True)
t0 = time.time()
v = nr.demo_verificador_ncm(n=3000, k=24, semente=42)
dt = time.time() - t0
print(f" temperatura calibrada T*: {v['temperatura_calibrada']:.4f}")
print(f" ECE: {v['ece_antes']:.4f} -> {v['ece_depois']:.4f} (NLL {v['nll_antes']:.4f} -> {v['nll_depois']:.4f})")
print(f" tau_c (DKW, eps=0.25): {v['tau_c_dkw']:.4f}")
print(f" P(erro|aceito) = {v['p_erro_aceito']:.4f} <= cota {v['cota_soundness']:.4f} -> {v['soundness_ok']}")
print(f" (referência: acerto do ORÁCULO no mesmo problema = {v['acerto_oraculo_referencia']:.4f} — inacessível em produção)")
res["demos"]["calibracao_soundness"] = {**v, "tempo_s": dt}
# -------------------------------------------- 4: ciclo d SEM oráculo
print("\n=== Ciclo d com verificador NCM (sem oráculo) ===", flush=True)
t0 = time.time()
d = nr.demo_pensamento_ncm(
d_cond=12, d_saida=6, n_tentativas=5,
passos_treino=220, limiar_conf=0.92, orcamento=6, semente=42,
)
dt = time.time() - t0
print(f" treino cooperativo: {d['perda_treino_inicial']:.4f} -> {d['perda_treino_final']:.4f} (aprendeu: {d['treino_aprendeu']})")
print(f" ECE do verificador: {d['ece_verificador_antes']:.4f} -> {d['ece_verificador_depois']:.4f} (T*={d['temperatura_calibrada']:.3f})")
print(f" ciclo d: {d['iteracoes_ciclo_d_media']:.1f} iterações médias | conf base 1 rede: {d['confianca_base_1_rede']:.4f}")
print(f" conf Pensamento (N=5, verificador NCM): {d['confianca_pensamento']:.4f} (ganho {d['ganho_confianca']:+.4f})")
print(f" OOD honesto: base {d['confianca_ood_base']:.4f} -> pensamento {d['confianca_ood_pensamento']:.4f} (iterações {d['iteracoes_ood']})")
res["demos"]["ciclo_d_sem_oraculo"] = {
**d, "tempo_s": dt,
"gate_aprendeu": d["treino_aprendeu"],
"gate_terminou": d["iteracoes_ciclo_d_media"] <= 6,
"gate_sem_oraculo": True,
}
# -------------------------------------------- 5: escalonamento com N
print("\n=== Escalonamento com N (verificador NCM, consultas retidas) ===", flush=True)
escal = []
for n in (1, 2, 4, 8):
r = nr.demo_pensamento_ncm(
d_cond=12, d_saida=6, n_tentativas=n,
passos_treino=180, limiar_conf=0.95, orcamento=8, semente=100 + n,
)
escal.append({
"n": n,
"conf_base": r["confianca_base_1_rede"],
"conf_pensamento": r["confianca_pensamento"],
"ganho": r["ganho_confianca"],
"iteracoes": r["iteracoes_ciclo_d_media"],
})
print(f" N={n}: base {r['confianca_base_1_rede']:.4f} -> pensamento {r['confianca_pensamento']:.4f} (ganho {r['ganho_confianca']:+.4f})")
n1, nn = escal[0]["conf_pensamento"], escal[-1]["conf_pensamento"]
res["demos"]["escalonamento_n"] = {
"serie": escal, "confianca_n1": n1, "confianca_n_max": nn,
"gate_tp2_ncm": nn >= n1 - 0.05,
}
# ------------------------------------------------------------------ resumo
gates = []
for nome, s in res["demos"].items():
gates += [(f"{nome}.{g[5:]}", val) for g, val in s.items() if g.startswith("gate_")]
# gates aninhados do Rust (honestidade: conta TODOS)
if isinstance(s.get("gates"), dict):
gates += [(f"{nome}.{g[5:]}", val) for g, val in s["gates"].items() if g.startswith("gate_")]
ok = sum(1 for _, val in gates if val)
res["resumo"] = {"gates_totais": len(gates), "gates_ok": ok, "todos_verdes": ok == len(gates)}
print(f"\n=== RESUMO: {ok}/{len(gates)} gates verdes ===")
os.makedirs(os.path.join(pasta, "resultados"), exist_ok=True)
with open(os.path.join(pasta, "resultados", "verificador_ncm_v060.json"), "w") as f:
json.dump(res, f, indent=1, ensure_ascii=False)
print("salvo: resultados/verificador_ncm_v060.json")
if not res["resumo"]["todos_verdes"]:
raise SystemExit(1)
if __name__ == "__main__":
main()