khtst-rust / scripts /40_treinar.py
PowerMachine's picture
v0.5.0: suíte SOM-4D + suíte JEPA (12) + tecnologia Pensamento + telemetria Theil–Sen — 29/29 gates verdes (provas r-18..r-22)
e26f4cc verified
Raw History Blame Contribute Delete
3.91 kB
#!/usr/bin/env python3
"""40_treinar.py — Fases A (tokenizador) e B (gerador) do KHTST_RUST.
Uso: python3 scripts/40_treinar.py [--fase a|b|ab] [--teto_min N]
Protocolo (n-04 §4): A = nested dropout + commitment + GSQ/RCO Stiefel;
B = MLE exato sobre hierarquias congeladas + corrupção κ + MTP + JEPA + PCGrad.
Teto de tempo wall-clock (leitura honesta): para no limite e reporta."""
import argparse, json, os, sys, time
def carregar_sequencias(pasta, bpe, qual):
import khtst_rust as K
b = K.Bpe.carregar(os.path.join(pasta, "dados", "bpe.json"))
seqs = []
with open(os.path.join(pasta, "dados", f"shard_{qual}.jsonl")) as f:
for linha in f:
t = json.loads(linha)["texto"]
ids = b.codificar(t)
# janelas de 256 tokens (ctx) — deslocamento 128 (50% sobreposição)
for i in range(0, max(1, len(ids) - 256), 128):
seqs.append(ids[i:i + 256])
return seqs
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--fase", default="ab", choices=["a", "b", "ab"])
ap.add_argument("--teto_min", type=float, default=10.0)
args = ap.parse_args()
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"))
bpe = K.Bpe.carregar(os.path.join(pasta, "dados", "bpe.json"))
# ajusta passos ao teto de tempo: estimativa por benchmark rápido
relatorio = {"fases": {}}
if args.fase in ("a", "ab"):
print("=== FASE A — tokenizador de conceitos (GSQ+RCO Stiefel) ===", flush=True)
seqs = carregar_sequencias(pasta, bpe, "treino")
print(f"sequências de treino: {len(seqs)} (ctx=256)", flush=True)
cb = None
t0 = time.time()
saida = K.treinar_fase_a(
cfg, seqs,
caminho_telemetria=os.path.join(pasta, "resultados", "telemetria_fase_a.jsonl"),
caminho_checkpoint=os.path.join(pasta, "resultados", "tokenizador_conceitos.json"),
)
dt = time.time() - t0
r = saida["resumo"]
relatorio["fases"]["a"] = r
print(json.dumps(r, indent=1, ensure_ascii=False))
print(f"fase A: {dt:.0f}s | Δperda {r['perda_inicial']:.3f}→{r['perda_final']:.3f} "
f"| acc_recon {r['acc_recon']:.3f} | δ_ort_max {r['delta_ort_max']:.2e} "
f"| perp_codebook {r['perplexidade_codebook']:.1f} "
f"| monotonia_prefixo {r['monotonia_prefixo']:.2f} "
f"| escore_aprendizado {r['escore_aprendizado']:.3f}", flush=True)
if args.fase in ("b", "ab"):
print("=== FASE B — gerador next-concept (MLE exato + κ + MTP + JEPA + PCGrad) ===", flush=True)
seqs = carregar_sequencias(pasta, bpe, "treino")
t0 = time.time()
saida = K.treinar_fase_b(
cfg, seqs,
caminho_tokenizador=os.path.join(pasta, "resultados", "tokenizador_conceitos.json"),
caminho_telemetria=os.path.join(pasta, "resultados", "telemetria_fase_b.jsonl"),
caminho_checkpoint=os.path.join(pasta, "resultados", "gerador_conceitos.json"),
)
dt = time.time() - t0
r = saida["resumo"]
relatorio["fases"]["b"] = r
print(json.dumps(r, indent=1, ensure_ascii=False))
print(f"fase B: {dt:.0f}s | ΔCE {r['perda_inicial']:.3f}→{r['perda_final']:.3f} "
f"| acc_conceitos {r['acc_conceitos']:.3f} "
f"| escore_aprendizado {r['escore_aprendizado']:.3f}", flush=True)
with open(os.path.join(pasta, "resultados", "resumo_treino.json"), "w") as f:
json.dump(relatorio, f, indent=1, ensure_ascii=False)
print("resumo salvo em resultados/resumo_treino.json")
if __name__ == "__main__":
main()