File size: 4,964 Bytes
bb2363d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #!/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()
|