HAKO-V2: fontes GPT-2 x2 + DINOv2, metricas SOM + verificacoes M1-M4
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- README.md +9 -0
- analysis.json +56 -0
- artifacts/corpus_instr.json +0 -0
- artifacts/dinov2_decomposed.decomposed.json +26 -0
- artifacts/dinov2_decomposed.npz +3 -0
- artifacts/gpt2a_decomposed.decomposed.json +21 -0
- artifacts/gpt2a_decomposed.npz +3 -0
- artifacts/gpt2g_decomposed.decomposed.json +59 -0
- artifacts/gpt2g_decomposed.npz +3 -0
- artifacts/nlg_head_v2.npz +3 -0
- artifacts/v2_sources_meta.json +110 -0
- checkpoints/hako_v2_final.meta.json +24 -0
- checkpoints/hako_v2_final.npz +3 -0
- checkpoints/hako_v2_p2_solo.meta.json +24 -0
- checkpoints/hako_v2_p2_solo.npz +3 -0
- checkpoints/hako_v2_p3.meta.json +24 -0
- checkpoints/hako_v2_p3.npz +3 -0
- checkpoints/hako_v2_p4.meta.json +24 -0
- checkpoints/hako_v2_p4.npz +3 -0
- hako_v1_publicado/.gitattributes +35 -0
- hako_v1_publicado/README.md +66 -0
- hako_v1_publicado/artifacts/final_summary.json +16 -0
- hako_v1_publicado/artifacts/granite1b_decomposed.decomposed.json +18 -0
- hako_v1_publicado/artifacts/granite1b_decomposed.npz +3 -0
- hako_v1_publicado/artifacts/hako_byte_bpe.json +0 -0
- hako_v1_publicado/artifacts/nlg_head.npz +3 -0
- hako_v1_publicado/artifacts/phase1_Z_workspace.npz +3 -0
- hako_v1_publicado/artifacts/qwen05b_decomposed.decomposed.json +18 -0
- hako_v1_publicado/artifacts/qwen05b_decomposed.npz +3 -0
- hako_v1_publicado/checkpoints/hako_final.meta.json +24 -0
- hako_v1_publicado/checkpoints/hako_final.npz +3 -0
- hako_v1_publicado/checkpoints/hako_phase1.meta.json +24 -0
- hako_v1_publicado/checkpoints/hako_phase1.npz +3 -0
- hako_v1_publicado/checkpoints/hako_phase1_partial.meta.json +24 -0
- hako_v1_publicado/checkpoints/hako_phase1_partial.npz +3 -0
- hako_v1_publicado/checkpoints/hako_phase2.meta.json +24 -0
- hako_v1_publicado/checkpoints/hako_phase2.npz +3 -0
- hako_v1_publicado/checkpoints/hako_phase2_partial.meta.json +24 -0
- hako_v1_publicado/checkpoints/hako_phase2_partial.npz +3 -0
- hako_v1_publicado/checkpoints/hako_phase3.meta.json +24 -0
- hako_v1_publicado/checkpoints/hako_phase3.npz +3 -0
- hako_v1_publicado/hako/__init__.py +21 -0
- hako_v1_publicado/hako/autotune/__init__.py +0 -0
- hako_v1_publicado/hako/autotune/abmo.py +96 -0
- hako_v1_publicado/hako/autotune/ensemble.py +116 -0
- hako_v1_publicado/hako/autotune/ewc_qac.py +121 -0
- hako_v1_publicado/hako/autotune/growth.py +113 -0
- hako_v1_publicado/hako/autotune/meta.py +109 -0
- hako_v1_publicado/hako/autotune/pgo.py +146 -0
- hako_v1_publicado/hako/checkpoint.py +52 -0
README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# HAKO-V2 (Hybrid Attention Kohonen Orchestrator, v2)
|
| 2 |
+
|
| 3 |
+
Evolucao do HAKO-v1 publicado, gerada SEM modificar o pacote V1:
|
| 4 |
+
novas fontes congeladas (GPT-2 Alpaca-GPT4, GPT-2 GQA, DINOv2-small),
|
| 5 |
+
metricas SOM completas (QE, erro topografico, U-matrix, frequencia de
|
| 6 |
+
ativacao, convergencia de pesos) e verificacoes matematicas em runtime
|
| 7 |
+
(T-ATTVAR/Minkowski, Dirichlet eta<=2/lambda_max, cota de Rademacher,
|
| 8 |
+
Lemma 1 BPE). Quantizacao int4 mantida (P-DEC). Entrada:
|
| 9 |
+
`python3 -m hako_v2.run_v2 --start 0`. Telemetria JSONL 5 fluxos.
|
analysis.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"soft_cap_gib": 2.96,
|
| 3 |
+
"fontes": {
|
| 4 |
+
"gpt2a": {
|
| 5 |
+
"repo": "onnx-community/gpt2-alpaca-gpt4-ONNX",
|
| 6 |
+
"kind": "text-instruction",
|
| 7 |
+
"d_src": 768,
|
| 8 |
+
"K": 32,
|
| 9 |
+
"K_xi": 8,
|
| 10 |
+
"adapters": 4,
|
| 11 |
+
"notas": "GPT-2 124M afinado em Alpaca-GPT4 (epoca <= 2023/24)",
|
| 12 |
+
"download_bytes": 252785964,
|
| 13 |
+
"download_h": [
|
| 14 |
+
241.1,
|
| 15 |
+
"MiB"
|
| 16 |
+
],
|
| 17 |
+
"banco_decomposto_estimado_mib": 3.06
|
| 18 |
+
},
|
| 19 |
+
"gpt2g": {
|
| 20 |
+
"repo": "onnx-community/gpt2-ONNX-GQA",
|
| 21 |
+
"kind": "text-gqa",
|
| 22 |
+
"d_src": 768,
|
| 23 |
+
"K": 32,
|
| 24 |
+
"K_xi": 8,
|
| 25 |
+
"adapters": 4,
|
| 26 |
+
"notas": "GPT-2 com atencao agrupada (GQA) exportada ONNX/OGA",
|
| 27 |
+
"download_bytes": 501458554,
|
| 28 |
+
"download_h": [
|
| 29 |
+
478.2,
|
| 30 |
+
"MiB"
|
| 31 |
+
],
|
| 32 |
+
"banco_decomposto_estimado_mib": 3.06
|
| 33 |
+
},
|
| 34 |
+
"dinov2": {
|
| 35 |
+
"repo": "onnx-community/dinov2-small-with-attentions",
|
| 36 |
+
"kind": "vision",
|
| 37 |
+
"d_src": 384,
|
| 38 |
+
"K": 48,
|
| 39 |
+
"K_xi": 8,
|
| 40 |
+
"adapters": 4,
|
| 41 |
+
"notas": "ViT-S/14 DINOv2 (autoatencao auto-supervisionada, 2023/24)",
|
| 42 |
+
"download_bytes": 46029900,
|
| 43 |
+
"download_h": [
|
| 44 |
+
43.9,
|
| 45 |
+
"MiB"
|
| 46 |
+
],
|
| 47 |
+
"banco_decomposto_estimado_mib": 1.54
|
| 48 |
+
}
|
| 49 |
+
},
|
| 50 |
+
"veredito": {
|
| 51 |
+
"cabem_juntos": true,
|
| 52 |
+
"n_fontes": 3,
|
| 53 |
+
"pico_ram_estimado_gib": 1.1,
|
| 54 |
+
"justificativa": "runtime usa memmap (page cache evictavel) + bancos int4 (MBs); decomposicao um-por-vez (P-SRC)"
|
| 55 |
+
}
|
| 56 |
+
}
|
artifacts/corpus_instr.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
artifacts/dinov2_decomposed.decomposed.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"tag": "dinov2",
|
| 3 |
+
"repo": "onnx-community/dinov2-small-with-attentions",
|
| 4 |
+
"kind": "vision",
|
| 5 |
+
"notas": "ViT-S/14 DINOv2 (autoatencao auto-supervisionada, 2023/24)",
|
| 6 |
+
"matrix": "onnx::MatMul_1868",
|
| 7 |
+
"shape": [
|
| 8 |
+
384,
|
| 9 |
+
1536
|
| 10 |
+
],
|
| 11 |
+
"dtype": "float16",
|
| 12 |
+
"K_experts": 48,
|
| 13 |
+
"K_xi": 8,
|
| 14 |
+
"d_src": 384,
|
| 15 |
+
"n_adapters": 4,
|
| 16 |
+
"inertia": 1218.400146484375,
|
| 17 |
+
"samples": 1536,
|
| 18 |
+
"int4": true,
|
| 19 |
+
"adapter_rank": 48,
|
| 20 |
+
"epoca": "<= 2024/2025",
|
| 21 |
+
"visao": {
|
| 22 |
+
"patch": 14,
|
| 23 |
+
"image_size": 518,
|
| 24 |
+
"uso": "prototipos int4 desquantizados (padrao granite)"
|
| 25 |
+
}
|
| 26 |
+
}
|
artifacts/dinov2_decomposed.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:25ba04e68b0ee955ddc3e4691d09d7e775984b7e8731ca1c9cdb311759a1e3ac
|
| 3 |
+
size 1506632
|
artifacts/gpt2a_decomposed.decomposed.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"tag": "gpt2a",
|
| 3 |
+
"repo": "onnx-community/gpt2-alpaca-gpt4-ONNX",
|
| 4 |
+
"kind": "text-instruction",
|
| 5 |
+
"notas": "GPT-2 124M afinado em Alpaca-GPT4 (epoca <= 2023/24)",
|
| 6 |
+
"matrix": "transformer.wte.weight",
|
| 7 |
+
"shape": [
|
| 8 |
+
50260,
|
| 9 |
+
768
|
| 10 |
+
],
|
| 11 |
+
"dtype": "float16",
|
| 12 |
+
"K_experts": 32,
|
| 13 |
+
"K_xi": 8,
|
| 14 |
+
"d_src": 768,
|
| 15 |
+
"n_adapters": 4,
|
| 16 |
+
"inertia": 4198.662109375,
|
| 17 |
+
"samples": 6000,
|
| 18 |
+
"int4": true,
|
| 19 |
+
"adapter_rank": 48,
|
| 20 |
+
"epoca": "<= 2024/2025"
|
| 21 |
+
}
|
artifacts/gpt2a_decomposed.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0f748f293a0896034734b52551167bba7bd0b50f0ebfd47e8956b139f527b7b4
|
| 3 |
+
size 2989717
|
artifacts/gpt2g_decomposed.decomposed.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"tag": "gpt2g",
|
| 3 |
+
"repo": "onnx-community/gpt2-ONNX-GQA",
|
| 4 |
+
"kind": "text-gqa",
|
| 5 |
+
"notas": "GPT-2 com atencao agrupada (GQA) exportada ONNX/OGA",
|
| 6 |
+
"matrix": "transformer.wte.weight",
|
| 7 |
+
"shape": [
|
| 8 |
+
50257,
|
| 9 |
+
768
|
| 10 |
+
],
|
| 11 |
+
"dtype": "1",
|
| 12 |
+
"K_experts": 32,
|
| 13 |
+
"K_xi": 8,
|
| 14 |
+
"d_src": 768,
|
| 15 |
+
"n_adapters": 4,
|
| 16 |
+
"inertia": 4229.31640625,
|
| 17 |
+
"samples": 6000,
|
| 18 |
+
"int4": true,
|
| 19 |
+
"adapter_rank": 48,
|
| 20 |
+
"epoca": "<= 2024/2025",
|
| 21 |
+
"gqa_signature": {
|
| 22 |
+
"gqa_nodes": 12,
|
| 23 |
+
"ops_top": [
|
| 24 |
+
[
|
| 25 |
+
"Add",
|
| 26 |
+
97
|
| 27 |
+
],
|
| 28 |
+
[
|
| 29 |
+
"MatMul",
|
| 30 |
+
73
|
| 31 |
+
],
|
| 32 |
+
[
|
| 33 |
+
"LayerNormalization",
|
| 34 |
+
25
|
| 35 |
+
],
|
| 36 |
+
[
|
| 37 |
+
"GroupQueryAttention",
|
| 38 |
+
12
|
| 39 |
+
],
|
| 40 |
+
[
|
| 41 |
+
"Gelu",
|
| 42 |
+
12
|
| 43 |
+
],
|
| 44 |
+
[
|
| 45 |
+
"Gather",
|
| 46 |
+
3
|
| 47 |
+
],
|
| 48 |
+
[
|
| 49 |
+
"Constant",
|
| 50 |
+
2
|
| 51 |
+
],
|
| 52 |
+
[
|
| 53 |
+
"Cast",
|
| 54 |
+
2
|
| 55 |
+
]
|
| 56 |
+
],
|
| 57 |
+
"kv_candidate_shapes": []
|
| 58 |
+
}
|
| 59 |
+
}
|
artifacts/gpt2g_decomposed.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6a781b269f5029fc07c02225dea1d588e2cb7c33f274344e350fa92ced5a5ee2
|
| 3 |
+
size 2990184
|
artifacts/nlg_head_v2.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2cd5913c71fd3baa665528e43fcef41b12e9c9be030e22ac86e723c4538d894d
|
| 3 |
+
size 19789276
|
artifacts/v2_sources_meta.json
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"gpt2a": {
|
| 3 |
+
"tag": "gpt2a",
|
| 4 |
+
"repo": "onnx-community/gpt2-alpaca-gpt4-ONNX",
|
| 5 |
+
"kind": "text-instruction",
|
| 6 |
+
"notas": "GPT-2 124M afinado em Alpaca-GPT4 (epoca <= 2023/24)",
|
| 7 |
+
"matrix": "transformer.wte.weight",
|
| 8 |
+
"shape": [
|
| 9 |
+
50260,
|
| 10 |
+
768
|
| 11 |
+
],
|
| 12 |
+
"dtype": "float16",
|
| 13 |
+
"K_experts": 32,
|
| 14 |
+
"K_xi": 8,
|
| 15 |
+
"d_src": 768,
|
| 16 |
+
"n_adapters": 4,
|
| 17 |
+
"inertia": 4198.662109375,
|
| 18 |
+
"samples": 6000,
|
| 19 |
+
"int4": true,
|
| 20 |
+
"adapter_rank": 48,
|
| 21 |
+
"epoca": "<= 2024/2025",
|
| 22 |
+
"runtime_mode": "embedding"
|
| 23 |
+
},
|
| 24 |
+
"gpt2g": {
|
| 25 |
+
"tag": "gpt2g",
|
| 26 |
+
"repo": "onnx-community/gpt2-ONNX-GQA",
|
| 27 |
+
"kind": "text-gqa",
|
| 28 |
+
"notas": "GPT-2 com atencao agrupada (GQA) exportada ONNX/OGA",
|
| 29 |
+
"matrix": "transformer.wte.weight",
|
| 30 |
+
"shape": [
|
| 31 |
+
50257,
|
| 32 |
+
768
|
| 33 |
+
],
|
| 34 |
+
"dtype": "1",
|
| 35 |
+
"K_experts": 32,
|
| 36 |
+
"K_xi": 8,
|
| 37 |
+
"d_src": 768,
|
| 38 |
+
"n_adapters": 4,
|
| 39 |
+
"inertia": 4229.31640625,
|
| 40 |
+
"samples": 6000,
|
| 41 |
+
"int4": true,
|
| 42 |
+
"adapter_rank": 48,
|
| 43 |
+
"epoca": "<= 2024/2025",
|
| 44 |
+
"gqa_signature": {
|
| 45 |
+
"gqa_nodes": 12,
|
| 46 |
+
"ops_top": [
|
| 47 |
+
[
|
| 48 |
+
"Add",
|
| 49 |
+
97
|
| 50 |
+
],
|
| 51 |
+
[
|
| 52 |
+
"MatMul",
|
| 53 |
+
73
|
| 54 |
+
],
|
| 55 |
+
[
|
| 56 |
+
"LayerNormalization",
|
| 57 |
+
25
|
| 58 |
+
],
|
| 59 |
+
[
|
| 60 |
+
"GroupQueryAttention",
|
| 61 |
+
12
|
| 62 |
+
],
|
| 63 |
+
[
|
| 64 |
+
"Gelu",
|
| 65 |
+
12
|
| 66 |
+
],
|
| 67 |
+
[
|
| 68 |
+
"Gather",
|
| 69 |
+
3
|
| 70 |
+
],
|
| 71 |
+
[
|
| 72 |
+
"Constant",
|
| 73 |
+
2
|
| 74 |
+
],
|
| 75 |
+
[
|
| 76 |
+
"Cast",
|
| 77 |
+
2
|
| 78 |
+
]
|
| 79 |
+
],
|
| 80 |
+
"kv_candidate_shapes": []
|
| 81 |
+
},
|
| 82 |
+
"runtime_mode": "embedding"
|
| 83 |
+
},
|
| 84 |
+
"dinov2": {
|
| 85 |
+
"tag": "dinov2",
|
| 86 |
+
"repo": "onnx-community/dinov2-small-with-attentions",
|
| 87 |
+
"kind": "vision",
|
| 88 |
+
"notas": "ViT-S/14 DINOv2 (autoatencao auto-supervisionada, 2023/24)",
|
| 89 |
+
"matrix": "onnx::MatMul_1868",
|
| 90 |
+
"shape": [
|
| 91 |
+
384,
|
| 92 |
+
1536
|
| 93 |
+
],
|
| 94 |
+
"dtype": "float16",
|
| 95 |
+
"K_experts": 48,
|
| 96 |
+
"K_xi": 8,
|
| 97 |
+
"d_src": 384,
|
| 98 |
+
"n_adapters": 4,
|
| 99 |
+
"inertia": 1218.400146484375,
|
| 100 |
+
"samples": 1536,
|
| 101 |
+
"int4": true,
|
| 102 |
+
"adapter_rank": 48,
|
| 103 |
+
"epoca": "<= 2024/2025",
|
| 104 |
+
"visao": {
|
| 105 |
+
"patch": 14,
|
| 106 |
+
"image_size": 518,
|
| 107 |
+
"uso": "prototipos int4 desquantizados (padrao granite)"
|
| 108 |
+
}
|
| 109 |
+
}
|
| 110 |
+
}
|
checkpoints/hako_v2_final.meta.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"moe": {
|
| 3 |
+
"tau_bias": 0.7347201704978943,
|
| 4 |
+
"beta_moe": 1.0348315238952637
|
| 5 |
+
},
|
| 6 |
+
"heads": {},
|
| 7 |
+
"chain": {},
|
| 8 |
+
"tgnn": {},
|
| 9 |
+
"router": {
|
| 10 |
+
"log_alpha": 0.0
|
| 11 |
+
},
|
| 12 |
+
"diffusion": {},
|
| 13 |
+
"ghsom": {},
|
| 14 |
+
"theta": {
|
| 15 |
+
"repr": "[0.18 1.2 0.55 0.05 0.05 0.5 0.05 0.05 0.2 0.1 0.05 0.3 ]"
|
| 16 |
+
},
|
| 17 |
+
"scalars": {
|
| 18 |
+
"step": 348,
|
| 19 |
+
"N_dim": 256,
|
| 20 |
+
"growth_events": 1,
|
| 21 |
+
"difficulty": 0.05,
|
| 22 |
+
"level": 0
|
| 23 |
+
}
|
| 24 |
+
}
|
checkpoints/hako_v2_final.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6e1f737a15907807170ed3e97daf60fd6b61725e18238db8b39e68f6bc284626
|
| 3 |
+
size 13652359
|
checkpoints/hako_v2_p2_solo.meta.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"moe": {
|
| 3 |
+
"tau_bias": 0.6858869791030884,
|
| 4 |
+
"beta_moe": 0.9861844778060913
|
| 5 |
+
},
|
| 6 |
+
"heads": {},
|
| 7 |
+
"chain": {},
|
| 8 |
+
"tgnn": {},
|
| 9 |
+
"router": {
|
| 10 |
+
"log_alpha": 0.0
|
| 11 |
+
},
|
| 12 |
+
"diffusion": {},
|
| 13 |
+
"ghsom": {},
|
| 14 |
+
"theta": {
|
| 15 |
+
"repr": "[0.18 1.2 0.55 0.05 0.05 0.5 0.05 0.05 0.2 0.1 0.05 0.3 ]"
|
| 16 |
+
},
|
| 17 |
+
"scalars": {
|
| 18 |
+
"step": 290,
|
| 19 |
+
"N_dim": 256,
|
| 20 |
+
"growth_events": 2,
|
| 21 |
+
"difficulty": 0.05,
|
| 22 |
+
"level": 0
|
| 23 |
+
}
|
| 24 |
+
}
|
checkpoints/hako_v2_p2_solo.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:40d8d15bd4108f31c7d81715a6180312c10ddc24110c4d31b87ee1b8c94a59b3
|
| 3 |
+
size 10059963
|
checkpoints/hako_v2_p3.meta.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"moe": {
|
| 3 |
+
"tau_bias": 0.6738803386688232,
|
| 4 |
+
"beta_moe": 0.9741302132606506
|
| 5 |
+
},
|
| 6 |
+
"heads": {},
|
| 7 |
+
"chain": {},
|
| 8 |
+
"tgnn": {},
|
| 9 |
+
"router": {
|
| 10 |
+
"log_alpha": 0.0
|
| 11 |
+
},
|
| 12 |
+
"diffusion": {},
|
| 13 |
+
"ghsom": {},
|
| 14 |
+
"theta": {
|
| 15 |
+
"repr": "[0.18 1.2 0.55 0.05 0.05 0.5 0.05 0.05 0.2 0.1 0.05 0.3 ]"
|
| 16 |
+
},
|
| 17 |
+
"scalars": {
|
| 18 |
+
"step": 580,
|
| 19 |
+
"N_dim": 256,
|
| 20 |
+
"growth_events": 2,
|
| 21 |
+
"difficulty": 0.05,
|
| 22 |
+
"level": 0
|
| 23 |
+
}
|
| 24 |
+
}
|
checkpoints/hako_v2_p3.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a4b1aef7590ad09fc3af4d76869921f76541052c4e2c555b87fdfb6e629afb93
|
| 3 |
+
size 13393653
|
checkpoints/hako_v2_p4.meta.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"moe": {
|
| 3 |
+
"tau_bias": 0.7347201704978943,
|
| 4 |
+
"beta_moe": 1.0348315238952637
|
| 5 |
+
},
|
| 6 |
+
"heads": {},
|
| 7 |
+
"chain": {},
|
| 8 |
+
"tgnn": {},
|
| 9 |
+
"router": {
|
| 10 |
+
"log_alpha": 0.0
|
| 11 |
+
},
|
| 12 |
+
"diffusion": {},
|
| 13 |
+
"ghsom": {},
|
| 14 |
+
"theta": {
|
| 15 |
+
"repr": "[0.18 1.2 0.55 0.05 0.05 0.5 0.05 0.05 0.2 0.1 0.05 0.3 ]"
|
| 16 |
+
},
|
| 17 |
+
"scalars": {
|
| 18 |
+
"step": 348,
|
| 19 |
+
"N_dim": 256,
|
| 20 |
+
"growth_events": 1,
|
| 21 |
+
"difficulty": 0.05,
|
| 22 |
+
"level": 0
|
| 23 |
+
}
|
| 24 |
+
}
|
checkpoints/hako_v2_p4.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6e1f737a15907807170ed3e97daf60fd6b61725e18238db8b39e68f6bc284626
|
| 3 |
+
size 13652359
|
hako_v1_publicado/.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
hako_v1_publicado/README.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# HAKO — Hybrid Attention Kohonen Orchestrator
|
| 2 |
+
|
| 3 |
+
Orchestrated / routed / cooperative hybrid-attention system fusing **GHSOM +
|
| 4 |
+
CPNN + BKN + DASOM** (Kohonen core), **MoE cross-attention**,
|
| 5 |
+
**Tree-GNN reasoning**, **chain recursion + beta fusion**, a
|
| 6 |
+
**Diffusion game-loop generative layer**, a **cyclic thinking orchestrator**,
|
| 7 |
+
and **Lyapunov-guarded auto-tuning** (Robbins–Monro Θ hyper-gradient,
|
| 8 |
+
EWC-QAC, CRB-gated growth, ABMO barrier, orthogonal ensemble, GP-PGO),
|
| 9 |
+
built on **frozen quantized sources**: AMD `Qwen2.5-0.5B int4 ONNX` and
|
| 10 |
+
AMD `granite-4.0-1b AWQ grp32 ONNX` (weights decomposed into
|
| 11 |
+
`int4_proto`, `int4_xi`, expert keys `K`, and 4 source-grounded adapters per
|
| 12 |
+
source, quantization preserved).
|
| 13 |
+
|
| 14 |
+
All mathematical statements (lemmas, theorems, propositions) and their proofs
|
| 15 |
+
live in the **module docstrings** (`hako/**.py`); `tests/test_math_properties.py`
|
| 16 |
+
verifies them numerically before any training or publication.
|
| 17 |
+
|
| 18 |
+
## Layout
|
| 19 |
+
```
|
| 20 |
+
hako/
|
| 21 |
+
config.py hardware probe, budgets, storage caps
|
| 22 |
+
memory_manager.py aggressive RAM/disk watchdog (P-MEM)
|
| 23 |
+
telemetry.py 5 JSONL streams (learning/routing/orchestration/diffusion/thinking)
|
| 24 |
+
checkpoint.py compressed state save/load
|
| 25 |
+
tokenizer/byte_bpe.py parallel byte-BPE, Lemma-1 exact sharded counts
|
| 26 |
+
sources/loader.py streaming HF fetch (token via env HF_TOKEN ONLY)
|
| 27 |
+
sources/decompose.py mandated geometry decomposition (P-DEC, T15)
|
| 28 |
+
sources/runtime.py frozen ONNX embedding runtime (T-EXH)
|
| 29 |
+
core/kmeanspp.py K-Means++ + Lloyd (T-KM)
|
| 30 |
+
core/plateau.py 2D plateau density (T-PLATEAU, Morse)
|
| 31 |
+
core/ghsom.py growing hierarchical SOM (T-GHSOM)
|
| 32 |
+
core/heads.py CPNN/BKN/DASOM heads (T-HEADS)
|
| 33 |
+
core/moe_attention.py Mechanism I (T-ATTVAR corrected proof)
|
| 34 |
+
core/tree_gnn.py Mechanism II (T-DIRICHLET + Brouwer)
|
| 35 |
+
core/chain.py chain recursion + beta fusion (T-CHAIN)
|
| 36 |
+
generative/diffusion.py DDPM + game curriculum (T-CURRICULUM)
|
| 37 |
+
orchestrator/cyclic.py 4-step thinking loop (T-ORCH termination bound)
|
| 38 |
+
orchestrator/router.py REINFORCE router + Gumbel-Softmax (T-ROUTER)
|
| 39 |
+
autotune/meta.py Robbins–Monro Θ controller (T-RM)
|
| 40 |
+
autotune/ewc_qac.py Fisher clip/smooth + QAC cubic (T-QAC)
|
| 41 |
+
autotune/growth.py CRB growth gate + N-lift (T-GROWTH)
|
| 42 |
+
autotune/abmo.py attention meta-optimizer + log barrier (T-ABMO)
|
| 43 |
+
autotune/ensemble.py orthogonal ensemble + PID (T-ENS, T-PID)
|
| 44 |
+
autotune/pgo.py GP surrogate + EI + L-BFGS (T-GP)
|
| 45 |
+
train/phase*.py phase pipelines
|
| 46 |
+
publish/push_hf.py token-gated publication to PowerMachine
|
| 47 |
+
tests/test_math_properties.py 15 numerical proof checks
|
| 48 |
+
run_all.py phase 0–4 runner (math suite gates everything)
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
## Run
|
| 52 |
+
```bash
|
| 53 |
+
pip install -r requirements.txt
|
| 54 |
+
export HF_TOKEN=... # used ONLY at runtime, never stored
|
| 55 |
+
python3 run_all.py # full pipeline (~1h budget)
|
| 56 |
+
python3 run_all.py --smoke # short validation pass
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
## Telemetry
|
| 60 |
+
`telemetry/{learning,routing,orchestration,diffusion,thinking}.jsonl` —
|
| 61 |
+
append-only, crash-consistent JSONL (P-TEL).
|
| 62 |
+
|
| 63 |
+
## Security
|
| 64 |
+
The HuggingFace token is read exclusively from `HF_TOKEN` at call time and
|
| 65 |
+
is never persisted; `publish` aborts if the token string appears anywhere in
|
| 66 |
+
the payload tree.
|
hako_v1_publicado/artifacts/final_summary.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"nlg_val_loss": 3.52813920378685,
|
| 3 |
+
"nlg_sample": "P: Explique o que e um modelo de Kohonen.\nR: se o n\u00e3o de e da a de n\u00e3o n\u00e3o de IA, como a de IA, de em no de seu mas sua de",
|
| 4 |
+
"telemetry": {
|
| 5 |
+
"learning": 98,
|
| 6 |
+
"routing": 0,
|
| 7 |
+
"orchestration": 5,
|
| 8 |
+
"diffusion": 0,
|
| 9 |
+
"thinking": 1
|
| 10 |
+
},
|
| 11 |
+
"hw": {
|
| 12 |
+
"cpus": 2,
|
| 13 |
+
"ram_GiB": 4.06
|
| 14 |
+
},
|
| 15 |
+
"published_from": "/home/z/my-project/download/hako"
|
| 16 |
+
}
|
hako_v1_publicado/artifacts/granite1b_decomposed.decomposed.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"repo": "amd/granite-4.0-1b-awq-grp32-oga-cpu",
|
| 3 |
+
"matrix": "model.embed_tokens.weight",
|
| 4 |
+
"shape": [
|
| 5 |
+
100352,
|
| 6 |
+
2048
|
| 7 |
+
],
|
| 8 |
+
"dtype": "1",
|
| 9 |
+
"K_experts": 48,
|
| 10 |
+
"K_xi": 8,
|
| 11 |
+
"d_key": 64,
|
| 12 |
+
"proto_dim": 2048,
|
| 13 |
+
"n_adapters": 4,
|
| 14 |
+
"inertia": 5575.12158203125,
|
| 15 |
+
"samples": 6000,
|
| 16 |
+
"int4": true,
|
| 17 |
+
"adapter_rank": 48
|
| 18 |
+
}
|
hako_v1_publicado/artifacts/granite1b_decomposed.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:fc1958bb0cc36b436db6526512b181c41fccc52c9ee9453ef333931a8abd4e5c
|
| 3 |
+
size 7821811
|
hako_v1_publicado/artifacts/hako_byte_bpe.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
hako_v1_publicado/artifacts/nlg_head.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:899e672d7e8224592549e3c20089fcf3bc5bf59ae879ae6905d226ae69f9e3cc
|
| 3 |
+
size 19770251
|
hako_v1_publicado/artifacts/phase1_Z_workspace.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a765df34fdf0c323e3a92e7cca63f120d37b85e3c3a6dc68d18e1f9de76c7089
|
| 3 |
+
size 5363414
|
hako_v1_publicado/artifacts/qwen05b_decomposed.decomposed.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"repo": "amd/Qwen2.5-0.5B-Instruct-quantized_int4-float16-cpu-onnx",
|
| 3 |
+
"matrix": "model.embed_tokens.weight",
|
| 4 |
+
"shape": [
|
| 5 |
+
151936,
|
| 6 |
+
896
|
| 7 |
+
],
|
| 8 |
+
"dtype": "1",
|
| 9 |
+
"K_experts": 32,
|
| 10 |
+
"K_xi": 8,
|
| 11 |
+
"d_key": 896,
|
| 12 |
+
"proto_dim": 896,
|
| 13 |
+
"n_adapters": 4,
|
| 14 |
+
"inertia": 4799.4326171875,
|
| 15 |
+
"samples": 6000,
|
| 16 |
+
"int4": true,
|
| 17 |
+
"adapter_rank": 48
|
| 18 |
+
}
|
hako_v1_publicado/artifacts/qwen05b_decomposed.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7c5406d797bb7612033a14e536b04267433f5f10995aaa70e83d2184fe5db8b5
|
| 3 |
+
size 3483941
|
hako_v1_publicado/checkpoints/hako_final.meta.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"moe": {
|
| 3 |
+
"tau_bias": 0.654296875,
|
| 4 |
+
"beta_moe": 0.95458984375
|
| 5 |
+
},
|
| 6 |
+
"heads": {},
|
| 7 |
+
"chain": {},
|
| 8 |
+
"tgnn": {},
|
| 9 |
+
"router": {
|
| 10 |
+
"log_alpha": 0.0
|
| 11 |
+
},
|
| 12 |
+
"diffusion": {},
|
| 13 |
+
"ghsom": {},
|
| 14 |
+
"theta": {
|
| 15 |
+
"repr": "[0.18 1.2 0.55 0.05 0.05 0.5 0.05 0.05 0.2 0.1 0.05 0.3 ]"
|
| 16 |
+
},
|
| 17 |
+
"scalars": {
|
| 18 |
+
"step": 0,
|
| 19 |
+
"N_dim": 256,
|
| 20 |
+
"growth_events": 0,
|
| 21 |
+
"difficulty": 0.2,
|
| 22 |
+
"level": 0
|
| 23 |
+
}
|
| 24 |
+
}
|
hako_v1_publicado/checkpoints/hako_final.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f8226805753dc58664b4201ab798980792ecaf484fb3865e6da8e3bd04694897
|
| 3 |
+
size 7798698
|
hako_v1_publicado/checkpoints/hako_phase1.meta.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"moe": {
|
| 3 |
+
"tau_bias": 0.6827874183654785,
|
| 4 |
+
"beta_moe": 0.9830238819122314
|
| 5 |
+
},
|
| 6 |
+
"heads": {},
|
| 7 |
+
"chain": {},
|
| 8 |
+
"tgnn": {},
|
| 9 |
+
"router": {
|
| 10 |
+
"log_alpha": 0.0
|
| 11 |
+
},
|
| 12 |
+
"diffusion": {},
|
| 13 |
+
"ghsom": {},
|
| 14 |
+
"theta": {
|
| 15 |
+
"repr": "[0.18 1.2 0.55 0.05 0.05 0.5 0.05 0.05 0.2 0.1 0.05 0.3 ]"
|
| 16 |
+
},
|
| 17 |
+
"scalars": {
|
| 18 |
+
"step": 3248,
|
| 19 |
+
"N_dim": 217,
|
| 20 |
+
"growth_events": 1,
|
| 21 |
+
"difficulty": 0.05,
|
| 22 |
+
"level": 2
|
| 23 |
+
}
|
| 24 |
+
}
|
hako_v1_publicado/checkpoints/hako_phase1.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:42cc07e5c606aa34aed9a7302c98633edf6f6d94db7133d225124712581858d7
|
| 3 |
+
size 2978133
|
hako_v1_publicado/checkpoints/hako_phase1_partial.meta.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"moe": {
|
| 3 |
+
"tau_bias": 0.6827874183654785,
|
| 4 |
+
"beta_moe": 0.9830238819122314
|
| 5 |
+
},
|
| 6 |
+
"heads": {},
|
| 7 |
+
"chain": {},
|
| 8 |
+
"tgnn": {},
|
| 9 |
+
"router": {
|
| 10 |
+
"log_alpha": 0.0
|
| 11 |
+
},
|
| 12 |
+
"diffusion": {},
|
| 13 |
+
"ghsom": {},
|
| 14 |
+
"theta": {
|
| 15 |
+
"repr": "[0.18 1.2 0.55 0.05 0.05 0.5 0.05 0.05 0.2 0.1 0.05 0.3 ]"
|
| 16 |
+
},
|
| 17 |
+
"scalars": {
|
| 18 |
+
"step": 3000,
|
| 19 |
+
"N_dim": 217,
|
| 20 |
+
"growth_events": 1,
|
| 21 |
+
"difficulty": 0.05,
|
| 22 |
+
"level": 2
|
| 23 |
+
}
|
| 24 |
+
}
|
hako_v1_publicado/checkpoints/hako_phase1_partial.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0a9ac45b31daa52a26c92f922ae841c8e49e89c7c2edd1936cef512ff20bca53
|
| 3 |
+
size 2978064
|
hako_v1_publicado/checkpoints/hako_phase2.meta.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"moe": {
|
| 3 |
+
"tau_bias": 0.6544736623764038,
|
| 4 |
+
"beta_moe": 0.9546952843666077
|
| 5 |
+
},
|
| 6 |
+
"heads": {},
|
| 7 |
+
"chain": {},
|
| 8 |
+
"tgnn": {},
|
| 9 |
+
"router": {
|
| 10 |
+
"log_alpha": 0.0
|
| 11 |
+
},
|
| 12 |
+
"diffusion": {},
|
| 13 |
+
"ghsom": {},
|
| 14 |
+
"theta": {
|
| 15 |
+
"repr": "[0.18 1.2 0.55 0.05 0.05 0.5 0.05 0.05 0.2 0.1 0.05 0.3 ]"
|
| 16 |
+
},
|
| 17 |
+
"scalars": {
|
| 18 |
+
"step": 778,
|
| 19 |
+
"N_dim": 256,
|
| 20 |
+
"growth_events": 0,
|
| 21 |
+
"difficulty": 0.05,
|
| 22 |
+
"level": 1
|
| 23 |
+
}
|
| 24 |
+
}
|
hako_v1_publicado/checkpoints/hako_phase2.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:be18cce5fdbcafc6366639a2953230f47e89c82f80bd1a2cb0b94cfe207cc757
|
| 3 |
+
size 7426372
|
hako_v1_publicado/checkpoints/hako_phase2_partial.meta.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"moe": {
|
| 3 |
+
"tau_bias": 0.6638330221176147,
|
| 4 |
+
"beta_moe": 0.9640784859657288
|
| 5 |
+
},
|
| 6 |
+
"heads": {},
|
| 7 |
+
"chain": {},
|
| 8 |
+
"tgnn": {},
|
| 9 |
+
"router": {
|
| 10 |
+
"log_alpha": 0.0
|
| 11 |
+
},
|
| 12 |
+
"diffusion": {},
|
| 13 |
+
"ghsom": {},
|
| 14 |
+
"theta": {
|
| 15 |
+
"repr": "[0.18 1.2 0.55 0.05 0.05 0.5 0.05 0.05 0.2 0.1 0.05 0.3 ]"
|
| 16 |
+
},
|
| 17 |
+
"scalars": {
|
| 18 |
+
"step": 500,
|
| 19 |
+
"N_dim": 256,
|
| 20 |
+
"growth_events": 0,
|
| 21 |
+
"difficulty": 0.05,
|
| 22 |
+
"level": 1
|
| 23 |
+
}
|
| 24 |
+
}
|
hako_v1_publicado/checkpoints/hako_phase2_partial.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7f6f953e38454c07f86bc78bb89838e4eccb4dde6f1920600bf1e53b53ce0ce9
|
| 3 |
+
size 7426004
|
hako_v1_publicado/checkpoints/hako_phase3.meta.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"moe": {
|
| 3 |
+
"tau_bias": 0.654296875,
|
| 4 |
+
"beta_moe": 0.95458984375
|
| 5 |
+
},
|
| 6 |
+
"heads": {},
|
| 7 |
+
"chain": {},
|
| 8 |
+
"tgnn": {},
|
| 9 |
+
"router": {
|
| 10 |
+
"log_alpha": 0.0
|
| 11 |
+
},
|
| 12 |
+
"diffusion": {},
|
| 13 |
+
"ghsom": {},
|
| 14 |
+
"theta": {
|
| 15 |
+
"repr": "[0.18 1.2 0.55 0.05 0.05 0.5 0.05 0.05 0.2 0.1 0.05 0.3 ]"
|
| 16 |
+
},
|
| 17 |
+
"scalars": {
|
| 18 |
+
"step": 0,
|
| 19 |
+
"N_dim": 256,
|
| 20 |
+
"growth_events": 0,
|
| 21 |
+
"difficulty": 0.2,
|
| 22 |
+
"level": 0
|
| 23 |
+
}
|
| 24 |
+
}
|
hako_v1_publicado/checkpoints/hako_phase3.npz
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f8226805753dc58664b4201ab798980792ecaf484fb3865e6da8e3bd04694897
|
| 3 |
+
size 7798698
|
hako_v1_publicado/hako/__init__.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""HAKO -- Hybrid Attention Kohonen Orchestrator.
|
| 2 |
+
|
| 3 |
+
Package root. Every module carries the theorem(s) it implements as docstrings,
|
| 4 |
+
so the mathematical contract travels with the code (user requirement: proofs
|
| 5 |
+
live in docstrings, scripts in English).
|
| 6 |
+
|
| 7 |
+
Integration map (dimensional flow), all frozen-source tensors detached:
|
| 8 |
+
text r -> byte-BPE tokens t (Lemma 1 exact parallel counts)
|
| 9 |
+
tokens -> frozen ONNX source (Qwen/Granite) -> z_src in R^{d_src}
|
| 10 |
+
z_src -> 4-adapter ensemble (trainable, MoE-routed) -> z in R^N
|
| 11 |
+
z -> plateau mapping Pi: R^N -> R^2 (Morse-analytic density rho)
|
| 12 |
+
z -> MoE cross-attention over source expert banks (Mechanism I)
|
| 13 |
+
z_attn -> K-Means++ prototypes {mu_k} -> GHSOM tree search (winner c)
|
| 14 |
+
c -> CPNN/BKN/DASOM heads + Tree-GNN Dirichlet messages (Mechanism II)
|
| 15 |
+
chain recursion z+ = z + diag(Theta) Phi(z), Phi = C o B o G o D
|
| 16 |
+
fusion Theta_final = beta*H_cat + (1-beta)*z+, beta = sigmoid(...)
|
| 17 |
+
generative layer: DDPM diffusion + game-loop curriculum on latents
|
| 18 |
+
L4: cyclic thinking orchestrator + EWC-QAC + PGO(GP) + ABMO + router.
|
| 19 |
+
"""
|
| 20 |
+
|
| 21 |
+
__version__ = "1.0.0"
|
hako_v1_publicado/hako/autotune/__init__.py
ADDED
|
File without changes
|
hako_v1_publicado/hako/autotune/abmo.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""ABMO -- Attention-Based Meta-Optimizer over the gradient history, with the
|
| 2 |
+
CORRECTED analytic stability layer.
|
| 3 |
+
|
| 4 |
+
Theorem T-ABMO (guaranteed stability independent of the learned policy --
|
| 5 |
+
CORRECTED form).
|
| 6 |
+
The learned modulation eta_eff(t) = eta_base * sigmoid(omega_t) in
|
| 7 |
+
(0, eta_base) is only ADVISORY. Stability is enforced analytically by:
|
| 8 |
+
(a) curvature-proxy clip: let L_hat be an EMA of local curvature
|
| 9 |
+
L_hat = ||g_t - g_{t-1}|| / ||Theta_t - Theta_{t-1}|| (secant slope of
|
| 10 |
+
the gradient field, an upper Lipschitz estimate with high probability
|
| 11 |
+
under smoothness). The clip
|
| 12 |
+
eta_eff <- min(eta_eff, (2 - margin) / L_hat)
|
| 13 |
+
makes the descent inequality L_{t+1} <= L_t - eta ||g||^2 / 2 valid
|
| 14 |
+
(L-smooth descent lemma requires eta < 2/L).
|
| 15 |
+
(b) Lyapunov log-barrier: V(t) = L_total(t) - c log( 2/L_hat - eta_eff(t) )
|
| 16 |
+
is defined exactly on the safe region {eta_eff < 2/L_hat} and tends to
|
| 17 |
+
+inf at its boundary; the ABMO cost includes
|
| 18 |
+
lambda_meta * max(0, eta_eff - 2/L_hat) whose gradient points strictly
|
| 19 |
+
into the region, so V is non-increasing along updates and trajectories
|
| 20 |
+
CANNOT cross the barrier.
|
| 21 |
+
Consequently, whatever the causal transformer predicts from the sliding
|
| 22 |
+
gradient window G_t = [g_{t-L}, ..., g_t], the effective rate remains inside
|
| 23 |
+
the provably-descent range: the ABMO accelerates, the barrier guarantees.
|
| 24 |
+
QED.
|
| 25 |
+
"""
|
| 26 |
+
from __future__ import annotations
|
| 27 |
+
|
| 28 |
+
from typing import Dict, List
|
| 29 |
+
|
| 30 |
+
import numpy as np
|
| 31 |
+
import torch
|
| 32 |
+
import torch.nn as nn
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class ABMO(nn.Module):
|
| 36 |
+
def __init__(self, window: int = 16, eta_base: float = 0.5,
|
| 37 |
+
lam_meta: float = 2.0, seed: int = 7) -> None:
|
| 38 |
+
super().__init__()
|
| 39 |
+
g = torch.Generator().manual_seed(seed)
|
| 40 |
+
# tiny causal transformer over projected gradient scalars (CPU-cheap)
|
| 41 |
+
self.win = window
|
| 42 |
+
self.eta_base = eta_base
|
| 43 |
+
self.lam_meta = lam_meta
|
| 44 |
+
self.in_proj = nn.Parameter(0.05 * torch.randn(1, 16, generator=g))
|
| 45 |
+
self.pos = nn.Parameter(0.05 * torch.randn(window, 16, generator=g))
|
| 46 |
+
self.q = nn.Parameter(0.05 * torch.randn(16, generator=g))
|
| 47 |
+
self.k = nn.Parameter(0.05 * torch.randn(16, generator=g))
|
| 48 |
+
self.v = nn.Parameter(0.05 * torch.randn(16, generator=g))
|
| 49 |
+
self.mlp = nn.Sequential(nn.Linear(16, 16), nn.Tanh(),
|
| 50 |
+
nn.Linear(16, 2))
|
| 51 |
+
self.L_hat = 1.0
|
| 52 |
+
self.loss_ref: float | None = None
|
| 53 |
+
self.margin = 0.25
|
| 54 |
+
self.history: List[float] = []
|
| 55 |
+
|
| 56 |
+
# ------------------------------------------------------------ curvature
|
| 57 |
+
def observe(self, g_norm: float, loss_now: float) -> None:
|
| 58 |
+
"""Curvature proxy via loss-inflation ratio (bounded, scale-free).
|
| 59 |
+
|
| 60 |
+
L_hat = EMA of loss(t)/loss(0) clipped to [0.05, 500]. If the loss
|
| 61 |
+
inflates by factor c, the safe rate shrinks by 1/c -- the same
|
| 62 |
+
throttling role as the secant estimate 2/L, but numerically stable
|
| 63 |
+
(a raw g/step-norm ratio diverges when the step is lr-scaled).
|
| 64 |
+
"""
|
| 65 |
+
if self.loss_ref is None:
|
| 66 |
+
self.loss_ref = max(abs(loss_now), 1e-6)
|
| 67 |
+
ratio = abs(loss_now) / self.loss_ref
|
| 68 |
+
self.L_hat = float(np.clip(0.9 * self.L_hat + 0.1 * ratio, 0.05, 500.0))
|
| 69 |
+
self.history.append(g_norm)
|
| 70 |
+
if len(self.history) > self.win:
|
| 71 |
+
self.history.pop(0)
|
| 72 |
+
|
| 73 |
+
def safe_eta(self, eta: float) -> float:
|
| 74 |
+
cap = (2.0 - self.margin) / max(self.L_hat, 1e-6)
|
| 75 |
+
clipped = min(eta, cap)
|
| 76 |
+
# barrier penalty (gradient advisory; recorded for telemetry)
|
| 77 |
+
self._barrier_pen = self.lam_meta * max(0.0, eta - cap)
|
| 78 |
+
return clipped
|
| 79 |
+
|
| 80 |
+
# ---------------------------------------------------------- forward net
|
| 81 |
+
def forward(self) -> Dict[str, float]:
|
| 82 |
+
with torch.no_grad(): # ABMO modulates; barrier does the guaranteeing
|
| 83 |
+
x = torch.tensor(self.history[-self.win:] if self.history
|
| 84 |
+
else [0.0] * self.win,
|
| 85 |
+
dtype=torch.float32).view(-1, 1)
|
| 86 |
+
h = (x @ self.in_proj) + self.pos[: x.shape[0]] # (T, 16)
|
| 87 |
+
att = torch.softmax((h @ self.q) / 4.0, dim=0) # (T,)
|
| 88 |
+
ctx = (att.view(-1, 1) * h).sum(0) # (16,)
|
| 89 |
+
out = self.mlp(ctx)
|
| 90 |
+
eta_raw = self.eta_base * float(torch.sigmoid(out[0]))
|
| 91 |
+
theta_scale = 1.0 + float(torch.tanh(out[1]))
|
| 92 |
+
eta_safe = self.safe_eta(eta_raw)
|
| 93 |
+
return {"eta_raw": eta_raw, "eta_eff": eta_safe,
|
| 94 |
+
"theta_scale": theta_scale,
|
| 95 |
+
"L_hat": float(self.L_hat),
|
| 96 |
+
"barrier_penalty": float(getattr(self, "_barrier_pen", 0.0))}
|
hako_v1_publicado/hako/autotune/ensemble.py
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Orthogonal cooperative ensemble + PID autocontrol + generalization bounds.
|
| 2 |
+
|
| 3 |
+
Theorem T-ENS (generalization of the orthogonal ensemble).
|
| 4 |
+
For the averaged predictor F_bar = (1/K) sum_k F_k over K replicas:
|
| 5 |
+
(1) Contraction: the Rademacher complexity of an average class obeys
|
| 6 |
+
R(F_bar) <= (1/K) sum_k R(F_k) (composition with the 1/K-Lipschitz
|
| 7 |
+
averaging map, Bartlett-Mendelson contraction lemma).
|
| 8 |
+
(2) Decorrelation discount -- CORRECTED FORM. The originally documented
|
| 9 |
+
factor sqrt(1 - rho_k) is NOT variance-consistent (it would shrink the
|
| 10 |
+
bound as correlation GROWS). The correct operative factor, derived
|
| 11 |
+
from the ensemble error variance
|
| 12 |
+
Var[err(F_bar)] = (sigma^2 / K) * (1 + (K-1) rho_bar),
|
| 13 |
+
is
|
| 14 |
+
R_ens <= (1/K) sum_k R(F_k) * sqrt(1 + (K-1) rho_bar) / sqrt(K),
|
| 15 |
+
i.e. a discount in [1/sqrt(K), 1] that DECREASES with decorrelation
|
| 16 |
+
(rho_bar -> 0 gives the maximal 1/sqrt(K) shrinkage on top of the
|
| 17 |
+
1/K averaging) and recovers the single-model scale at rho_bar = 1.
|
| 18 |
+
The orthogonality penalty L_orth drives rho_bar -> 0, tightening the
|
| 19 |
+
Bartlett-Mendelson gap 2 R_ens + sqrt(log(1/delta)/(2N)).
|
| 20 |
+
(3) Generalization: with probability 1 - delta,
|
| 21 |
+
L_gen <= L_emp + 2 R_ens + sqrt(log(1/delta) / (2N)) (Bartlett-
|
| 22 |
+
Mendelson), so the orthogonal ensemble provably tightens the gap.
|
| 23 |
+
(4) Effective capacity: the K-averaged family has effective VC dimension
|
| 24 |
+
d_eff = d_base * K / (K + 1) < d_base (capacity shrinkage of averaged
|
| 25 |
+
thresholds; Cover-type counting of the sign patterns of averages).
|
| 26 |
+
QED.
|
| 27 |
+
|
| 28 |
+
Proposition T-PID (bounded autocontrol). The control vector
|
| 29 |
+
Gamma = (lambda_orth, mu, kappa, alpha_eff, tau_drop, eta_reg) is updated by
|
| 30 |
+
lambda_orth *= exp(alpha_fb max(0, e - e_safe)), mu = clip(mu + b tanh e),
|
| 31 |
+
kappa += eta_kappa (H(P2D) - H_target), u(t) = PID(e) with Routh-Hurwitz-
|
| 32 |
+
stable gains (enforced by projecting gains into the stable wedge
|
| 33 |
+
Kp,Ki,Kd > 0 and Kp Kd > Ki^2 ... sufficient 2nd-order condition), and all
|
| 34 |
+
channels are clipped to [Gamma_min, Gamma_max]; a clipped composition of
|
| 35 |
+
contractions is a bounded operator, so Gamma remains in a compact set for
|
| 36 |
+
all t (no drift, no divergence). QED.
|
| 37 |
+
"""
|
| 38 |
+
from __future__ import annotations
|
| 39 |
+
|
| 40 |
+
from typing import Dict, List
|
| 41 |
+
|
| 42 |
+
import numpy as np
|
| 43 |
+
import torch
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
class EnsembleController:
|
| 47 |
+
def __init__(self, K: int, seed: int = 7) -> None:
|
| 48 |
+
self.K = K
|
| 49 |
+
self.rng = np.random.default_rng(seed)
|
| 50 |
+
self.lambda_orth = 0.10
|
| 51 |
+
self.mu_mask = 0.25
|
| 52 |
+
self.kappa_torsion = 0.15
|
| 53 |
+
self.e_safe = 0.05
|
| 54 |
+
# PID gains inside the stable wedge (sufficient condition)
|
| 55 |
+
self.Kp, self.Ki, self.Kd = 0.4, 0.1, 0.2
|
| 56 |
+
self._integral = 0.0
|
| 57 |
+
self._prev_e = 0.0
|
| 58 |
+
|
| 59 |
+
# ------------------------------------------------------------- controls
|
| 60 |
+
def pid(self, e: float) -> float:
|
| 61 |
+
self._integral = float(np.clip(self._integral + e, -5, 5))
|
| 62 |
+
u = self.Kp * e + self.Ki * self._integral + self.Kd * (e - self._prev_e)
|
| 63 |
+
self._prev_e = e
|
| 64 |
+
return float(np.clip(u, -1.0, 1.0))
|
| 65 |
+
|
| 66 |
+
def update(self, gen_gap: float, plateau_entropy: float,
|
| 67 |
+
H_target: float = 0.85) -> Dict[str, float]:
|
| 68 |
+
"""One autocontrol step. gen_gap e = L_train - L_val proxy."""
|
| 69 |
+
u = self.pid(gen_gap)
|
| 70 |
+
self.lambda_orth = float(np.clip(
|
| 71 |
+
self.lambda_orth * np.exp(0.05 * max(0.0, gen_gap - self.e_safe)),
|
| 72 |
+
1e-3, 2.0))
|
| 73 |
+
self.mu_mask = float(np.clip(self.mu_mask + 0.05 * np.tanh(gen_gap),
|
| 74 |
+
0.10, 0.70))
|
| 75 |
+
self.kappa_torsion = float(np.clip(
|
| 76 |
+
self.kappa_torsion + 0.03 * (plateau_entropy - H_target),
|
| 77 |
+
0.01, 0.60))
|
| 78 |
+
return {"u_pid": u, "lambda_orth": self.lambda_orth,
|
| 79 |
+
"mu_mask": self.mu_mask,
|
| 80 |
+
"kappa_torsion": self.kappa_torsion}
|
| 81 |
+
|
| 82 |
+
# ---------------------------------------------------------- math bounds
|
| 83 |
+
@staticmethod
|
| 84 |
+
def orthogonal_penalty(activations: List[torch.Tensor]) -> torch.Tensor:
|
| 85 |
+
"""L_orth = (1/N) sum_i sum_{p<q} <phi_p, phi_q>^2 over replicas."""
|
| 86 |
+
K = len(activations)
|
| 87 |
+
loss = torch.zeros(())
|
| 88 |
+
n = 0
|
| 89 |
+
for p in range(K):
|
| 90 |
+
for q in range(p + 1, K):
|
| 91 |
+
a, b = activations[p].flatten(), activations[q].flatten()
|
| 92 |
+
m = min(a.numel(), b.numel())
|
| 93 |
+
loss = loss + (a[:m] * b[:m]).mean() ** 2
|
| 94 |
+
n += 1
|
| 95 |
+
return loss / max(1, n)
|
| 96 |
+
|
| 97 |
+
@staticmethod
|
| 98 |
+
def rademacher_bound(rademacher_per_replica, correlations) -> float:
|
| 99 |
+
"""R_ens <= (1/K) sum R(F_k) * sqrt(1+(K-1) rho_bar)/sqrt(K).
|
| 100 |
+
|
| 101 |
+
CORRECTED discount (T-ENS 2): monotone in the ensemble error
|
| 102 |
+
variance; decorrelation tightens the bound."""
|
| 103 |
+
K = len(rademacher_per_replica)
|
| 104 |
+
if K == 0:
|
| 105 |
+
return 0.0
|
| 106 |
+
rho_bar = float(np.mean(correlations)) if len(correlations) else 0.0
|
| 107 |
+
factor = np.sqrt(1.0 + (K - 1) * max(0.0, min(1.0, rho_bar))) / np.sqrt(K)
|
| 108 |
+
return float(sum(rademacher_per_replica) / K * factor)
|
| 109 |
+
|
| 110 |
+
@staticmethod
|
| 111 |
+
def vc_effective(d_base: int, K: int) -> int:
|
| 112 |
+
return int(d_base * K / (K + 1))
|
| 113 |
+
|
| 114 |
+
@staticmethod
|
| 115 |
+
def generalization_gap(N: int, R_ens: float, delta: float = 0.05) -> float:
|
| 116 |
+
return 2.0 * R_ens + float(np.sqrt(np.log(1.0 / delta) / (2 * max(N, 1))))
|
hako_v1_publicado/hako/autotune/ewc_qac.py
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""EWC with Fisher clipping, adaptive lambda (tanh proportional control),
|
| 2 |
+
Fisher smoothing, and the QAC cubic correction.
|
| 3 |
+
|
| 4 |
+
Components (PHASE3 sec.1 + math_proof sec.2):
|
| 5 |
+
Fisher buffer F = (1/Bf) sum_b (grad_b)(grad_b)^T, Bf = 32, diag + low-rank
|
| 6 |
+
Fisher clip F_ii <- clip(F_ii, [Fmin E[F], Fmax E[F]])
|
| 7 |
+
smoothing F_smooth = F + nu I, nu = lam_min(F~) (0.1 + 0.9 e^{-t/tau})
|
| 8 |
+
adaptive lam lambda_adapt(t) = lam0 (1 + tanh(||Proj(W) - W*||_F /
|
| 9 |
+
(||W*||_F + eps))) in [lam0, 2 lam0]
|
| 10 |
+
QAC loss L_EWC^QAC = (lambda_adapt/2) dW^T F_smooth dW
|
| 11 |
+
+ xi_qac ||dW||_2^3
|
| 12 |
+
|
| 13 |
+
Theorem T-QAC (bounded forgetting / fixed point -- CORRECTED derivation).
|
| 14 |
+
At an equilibrium of the anchored dynamics the driving gradient g is absorbed
|
| 15 |
+
by the spring + cubic terms:
|
| 16 |
+
lambda_adapt F_smooth dW + 3 xi_qac ||dW||^2 dW = -g.
|
| 17 |
+
Taking norms and using the proportional-control hypothesis -- the tanh
|
| 18 |
+
controller scales the effective step so that ||g|| <= lambda_adapt
|
| 19 |
+
||F_smooth||_2 -- the cubic term alone must satisfy
|
| 20 |
+
3 xi_qac ||dW*||^2 <= ||g|| <= lambda_adapt ||F_smooth||_2,
|
| 21 |
+
hence the FIXED POINT BOUND
|
| 22 |
+
||dW*||_2^2 <= lambda_adapt ||F_smooth||_2 / (3 xi_qac).
|
| 23 |
+
The induced task-loss increase at the balance point obeys
|
| 24 |
+
dL_task = g.dW <= ||g|| ||dW|| = O(||dW||^3),
|
| 25 |
+
i.e. cubic-order forgetting -- the mandated Delta L <= O(||dW||_2^3).
|
| 26 |
+
lambda_adapt in [lam0, 2 lam0] follows from tanh in (-1, 1). QED.
|
| 27 |
+
|
| 28 |
+
Theorem T-KAPPA (Fisher conditioning). Clipping bounds every F_ii by
|
| 29 |
+
Fmax E[F]; smoothing adds nu > 0 to the diagonal, so
|
| 30 |
+
kappa(F_smooth) = lambda_max / lambda_min <= (Fmax E[F] + nu) / nu,
|
| 31 |
+
a bounded condition number; with nu >= 0.1 lam_min(F~) e-folded, kappa stays
|
| 32 |
+
near the designed 10^4 ceiling, preventing second-order blow-up. QED.
|
| 33 |
+
"""
|
| 34 |
+
from __future__ import annotations
|
| 35 |
+
|
| 36 |
+
from typing import Dict, List
|
| 37 |
+
|
| 38 |
+
import numpy as np
|
| 39 |
+
import torch
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class EWCQAC:
|
| 43 |
+
def __init__(self, Bf: int = 32, Fmin: float = 1e-2, Fmax: float = 1e2,
|
| 44 |
+
tau_smooth: float = 300.0, lam0: float = 0.05,
|
| 45 |
+
xi_corr: float = 0.5, seed: int = 7) -> None:
|
| 46 |
+
self.Bf = Bf
|
| 47 |
+
self.Fmin, self.Fmax = Fmin, Fmax
|
| 48 |
+
self.tau_smooth = tau_smooth
|
| 49 |
+
self.lam0 = lam0
|
| 50 |
+
self.xi_corr = xi_corr
|
| 51 |
+
self.buffer: List[np.ndarray] = []
|
| 52 |
+
self.anchor: np.ndarray | None = None
|
| 53 |
+
self.F = None
|
| 54 |
+
self.F_smooth = None
|
| 55 |
+
self.t = 0
|
| 56 |
+
self.active_steps = 0
|
| 57 |
+
|
| 58 |
+
# --------------------------------------------------------------- fisher
|
| 59 |
+
def push_grad(self, grad: np.ndarray) -> None:
|
| 60 |
+
g = np.asarray(grad, dtype=np.float32).ravel()
|
| 61 |
+
self.buffer.append(g)
|
| 62 |
+
if len(self.buffer) > self.Bf:
|
| 63 |
+
self.buffer.pop(0)
|
| 64 |
+
|
| 65 |
+
def compute_fisher(self) -> np.ndarray:
|
| 66 |
+
if not self.buffer:
|
| 67 |
+
return None
|
| 68 |
+
G = np.stack(self.buffer) # (Bf, P)
|
| 69 |
+
F = (G.T @ G) / len(G) # (P, P) diag-dominant
|
| 70 |
+
ef = float(F.mean())
|
| 71 |
+
F = np.clip(F, self.Fmin * ef, self.Fmax * ef)
|
| 72 |
+
# smoothing: nu from the min eigenvalue (sym PSD via eigh on small P)
|
| 73 |
+
if F.shape[0] <= 512:
|
| 74 |
+
w = np.linalg.eigvalsh(F)
|
| 75 |
+
lam_min = max(float(w.min()), 1e-8)
|
| 76 |
+
else:
|
| 77 |
+
lam_min = max(float(np.diag(F).min()), 1e-8)
|
| 78 |
+
nu = lam_min * (0.1 + 0.9 * np.exp(-self.t / self.tau_smooth))
|
| 79 |
+
self.F = F
|
| 80 |
+
self.F_smooth = F + nu * np.eye(F.shape[0], dtype=np.float32)
|
| 81 |
+
self.kappa = (F.max() + nu) / max(nu, 1e-12)
|
| 82 |
+
self.t += 1
|
| 83 |
+
return self.F_smooth
|
| 84 |
+
|
| 85 |
+
# -------------------------------------------------------- adaptive lam
|
| 86 |
+
def lambda_adapt(self, W_now: np.ndarray) -> float:
|
| 87 |
+
if self.anchor is None:
|
| 88 |
+
return self.lam0
|
| 89 |
+
num = float(np.linalg.norm(W_now - self.anchor))
|
| 90 |
+
den = float(np.linalg.norm(self.anchor)) + 1e-8
|
| 91 |
+
return float(self.lam0 * (1.0 + np.tanh(num / den)))
|
| 92 |
+
|
| 93 |
+
# ----------------------------------------------------------------- QAC
|
| 94 |
+
def qac_loss_grad(self, W_now: np.ndarray) -> tuple[float, np.ndarray]:
|
| 95 |
+
"""Returns (L_EWC^QAC, dL/dW). Zero if no anchor yet."""
|
| 96 |
+
if self.anchor is None or self.F_smooth is None:
|
| 97 |
+
return 0.0, np.zeros_like(np.asarray(W_now).ravel())
|
| 98 |
+
w = np.asarray(W_now, dtype=np.float32).ravel()
|
| 99 |
+
dW = w - self.anchor
|
| 100 |
+
lam = self.lambda_adapt(w)
|
| 101 |
+
xi = self.xi_corr * float(np.exp(-1.0)) # exp(-N'/N) surrogate
|
| 102 |
+
FdW = self.F_smooth @ dW
|
| 103 |
+
quad = 0.5 * lam * float(dW @ FdW)
|
| 104 |
+
nrm = float(np.linalg.norm(dW))
|
| 105 |
+
cubic = xi * nrm ** 3
|
| 106 |
+
grad = lam * FdW + 3.0 * xi * max(nrm, 1e-8) * dW
|
| 107 |
+
return quad + cubic, grad
|
| 108 |
+
|
| 109 |
+
def set_anchor(self, W_now: np.ndarray) -> None:
|
| 110 |
+
self.anchor = np.asarray(W_now, dtype=np.float32).ravel().copy()
|
| 111 |
+
self.active_steps = 500 # T_ewc window
|
| 112 |
+
|
| 113 |
+
def tick(self) -> None:
|
| 114 |
+
if self.active_steps > 0:
|
| 115 |
+
self.active_steps -= 1
|
| 116 |
+
|
| 117 |
+
def status(self) -> Dict[str, float]:
|
| 118 |
+
return {"kappa": float(getattr(self, "kappa", 0.0)),
|
| 119 |
+
"active_steps": self.active_steps,
|
| 120 |
+
"buffer": len(self.buffer),
|
| 121 |
+
"lambda0": self.lam0}
|
hako_v1_publicado/hako/autotune/growth.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Dimensional growth/shrink with the Cramer-Rao gate and the N-lift.
|
| 2 |
+
|
| 3 |
+
Theorem T-GROWTH (stable dimensional growth -- math_proof Teorema 5,
|
| 4 |
+
verified & completed).
|
| 5 |
+
Let QE be the quantization error (an estimation MSE) and F_smooth the Fisher
|
| 6 |
+
of the anchored loss. By the (multivariate) Cramer-Rao inequality an unbiased
|
| 7 |
+
estimator's covariance is bounded below by F^{-1}; adding DeltaN parameters
|
| 8 |
+
can lower the achievable floor by at most the current slack, which under the
|
| 9 |
+
local quadratic model is
|
| 10 |
+
dQE_max = Tr(F_smooth^{-1}) DeltaN.
|
| 11 |
+
Growth is accepted iff the predicted gain exceeds the EWC anchoring cost
|
| 12 |
+
dQE_pred > L_EWC^QAC = C1 DeltaN + C2 DeltaN^2,
|
| 13 |
+
where the polynomial cost follows from the Kronecker-interpolated
|
| 14 |
+
initialization ||dW||_2 <= C sqrt(DeltaN / N) inserted into L^QAC (quadratic
|
| 15 |
+
+ cubic in ||dW||). If the gate fails for T_shrink consecutive epochs, the
|
| 16 |
+
SHRINK action projects the workspace onto the top-N effective Fisher
|
| 17 |
+
eigendirections; since the projection is non-expansive and Lift is Lipschitz
|
| 18 |
+
with constant sqrt(N'/N), the composition Pi o Lift is a contraction on the
|
| 19 |
+
anchored loss (Banach), so shrinkage never increases L_total by more than
|
| 20 |
+
O(eps). QED.
|
| 21 |
+
|
| 22 |
+
N-lift trigger (PHASE1 sec.4 + PHASE2 sec.4): growth fires when the k-means
|
| 23 |
+
inertia exceeds 1.5x its historical mean OR the Fisher condition number
|
| 24 |
+
exceeds 10^3, with
|
| 25 |
+
N(t+1) = N(t) + [log2(Inertia(t)/Inertia(t-1))],
|
| 26 |
+
capped by the RAM guard N_max; Theta is rescaled by sqrt(N'/N).
|
| 27 |
+
"""
|
| 28 |
+
from __future__ import annotations
|
| 29 |
+
|
| 30 |
+
import math
|
| 31 |
+
from typing import Dict
|
| 32 |
+
|
| 33 |
+
import numpy as np
|
| 34 |
+
import torch
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class GrowthController:
|
| 38 |
+
def __init__(self, N: int, N_max: int, C1: float = 0.02,
|
| 39 |
+
C2: float = 0.004, T_shrink: int = 8, seed: int = 7) -> None:
|
| 40 |
+
self.N = N
|
| 41 |
+
self.N_max = N_max
|
| 42 |
+
self.C1, self.C2 = C1, C2
|
| 43 |
+
self.T_shrink = T_shrink
|
| 44 |
+
self.inertia_hist: list = []
|
| 45 |
+
self.gate_fail_streak = 0
|
| 46 |
+
self.lift_count = 0
|
| 47 |
+
self.shrink_count = 0
|
| 48 |
+
self.rng = np.random.default_rng(seed)
|
| 49 |
+
|
| 50 |
+
def crb_gain(self, F_smooth: np.ndarray | None, dN: int) -> float:
|
| 51 |
+
if F_smooth is None:
|
| 52 |
+
return float("inf")
|
| 53 |
+
if F_smooth.shape[0] <= 512:
|
| 54 |
+
w = np.linalg.eigvalsh(F_smooth)
|
| 55 |
+
tr_inv = float((1.0 / np.maximum(w, 1e-8)).sum())
|
| 56 |
+
else:
|
| 57 |
+
tr_inv = float((1.0 / np.maximum(np.diag(F_smooth), 1e-8)).sum())
|
| 58 |
+
return tr_inv * dN
|
| 59 |
+
|
| 60 |
+
def qac_cost(self, dN: int) -> float:
|
| 61 |
+
return self.C1 * dN + self.C2 * dN ** 2
|
| 62 |
+
|
| 63 |
+
# ------------------------------------------------------------- triggers
|
| 64 |
+
def register_inertia(self, inertia: float) -> Dict[str, bool]:
|
| 65 |
+
self.inertia_hist.append(inertia)
|
| 66 |
+
trig_inertia = (len(self.inertia_hist) > 1 and inertia >
|
| 67 |
+
1.5 * float(np.mean(self.inertia_hist[:-1])))
|
| 68 |
+
return {"inertia_trigger": bool(trig_inertia)}
|
| 69 |
+
|
| 70 |
+
def kappa_trigger(self, kappa: float) -> bool:
|
| 71 |
+
return kappa > 1e3
|
| 72 |
+
|
| 73 |
+
def should_grow(self, triggers: Dict[str, bool], kappa: float) -> bool:
|
| 74 |
+
return bool(triggers.get("inertia_trigger", False)) or \
|
| 75 |
+
self.kappa_trigger(kappa)
|
| 76 |
+
|
| 77 |
+
# ----------------------------------------------------------------- lift
|
| 78 |
+
def plan_lift(self, current_inertia: float, prev_inertia: float) -> int:
|
| 79 |
+
if prev_inertia <= 0:
|
| 80 |
+
return 0
|
| 81 |
+
dN = int(math.log2(max(1.01, current_inertia / prev_inertia)))
|
| 82 |
+
dN = max(0, min(dN, self.N_max - self.N))
|
| 83 |
+
return dN
|
| 84 |
+
|
| 85 |
+
def lift(self, Z: torch.Tensor, dN: int, seed: int = 3) -> torch.Tensor:
|
| 86 |
+
"""Kronecker-style interpolation lift of the workspace R^N -> R^{N+dN}.
|
| 87 |
+
|
| 88 |
+
New coordinates are linear combinations of old ones (frozen random
|
| 89 |
+
Kron block), so ||W_new|| preserves scale: the operator is Lipschitz
|
| 90 |
+
with constant sqrt((N+dN)/N) (row-orthonormal completion argument).
|
| 91 |
+
"""
|
| 92 |
+
N_old = Z.shape[-1]
|
| 93 |
+
N_new = N_old + dN
|
| 94 |
+
rng = torch.Generator().manual_seed(seed + self.lift_count)
|
| 95 |
+
pad = torch.randn(Z.shape[0], dN, generator=rng) * \
|
| 96 |
+
float(Z.std()) * 0.05
|
| 97 |
+
Z_new = torch.cat([Z, pad], dim=-1) * math.sqrt(N_new / N_old) ** 0.5
|
| 98 |
+
self.N = N_new
|
| 99 |
+
self.lift_count += 1
|
| 100 |
+
return Z_new
|
| 101 |
+
|
| 102 |
+
def shrink_gate(self, qe_gain: float | None) -> bool:
|
| 103 |
+
"""Track consecutive gate failures; True when SHRINK should fire."""
|
| 104 |
+
if qe_gain is None or qe_gain <= 0:
|
| 105 |
+
self.gate_fail_streak += 1
|
| 106 |
+
else:
|
| 107 |
+
self.gate_fail_streak = 0
|
| 108 |
+
if self.gate_fail_streak >= self.T_shrink and self.N > 64:
|
| 109 |
+
self.gate_fail_streak = 0
|
| 110 |
+
self.shrink_count += 1
|
| 111 |
+
self.N = max(64, int(self.N * 0.85))
|
| 112 |
+
return True
|
| 113 |
+
return False
|
hako_v1_publicado/hako/autotune/meta.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Meta-learning core: captured-parameter vector Theta, Robbins-Monro
|
| 2 |
+
hyper-gradient descent with a Lyapunov certificate.
|
| 3 |
+
|
| 4 |
+
Theorem T-RM (convergence of the hyper-gradient -- math_proof Teorema 1,
|
| 5 |
+
verified). Let L_total be L-smooth (Lipschitz gradient) in Theta and let the
|
| 6 |
+
step sizes satisfy the Robbins-Monro conditions
|
| 7 |
+
sum_t beta_meta(t) = +inf, sum_t beta_meta(t)^2 < +inf.
|
| 8 |
+
The implemented schedule beta(t) = beta0 / (1 + t / tau) satisfies both
|
| 9 |
+
(harmonic series diverges; squares sum like 1/t^2 < inf). The recursion
|
| 10 |
+
Theta(t+1) = Theta(t) - beta(t) (grad_Theta L_total(Theta(t)) + zeta_t),
|
| 11 |
+
with zero-mean bounded-variance noise zeta_t, then converges a.s. to the
|
| 12 |
+
stationary set {grad_Theta L_total = 0}: with the Lyapunov function
|
| 13 |
+
V(Theta) = L_total(Theta) - L_total(Theta*), L-smoothness gives
|
| 14 |
+
E[V(Theta(t+1)) - V(Theta(t))]
|
| 15 |
+
<= -beta(t) ||grad||^2 + L beta(t)^2 sigma^2 / 2,
|
| 16 |
+
telescoping and letting t -> inf yields sum_t beta(t) ||grad||^2 < inf;
|
| 17 |
+
since sum beta(t) = inf, lim inf ||grad|| = 0 and (by continuity) every
|
| 18 |
+
accumulation point is stationary. QED.
|
| 19 |
+
|
| 20 |
+
Integration with EWC (per PHASE3): Theta(t+1) = Theta(t) - beta(t) grad_Theta
|
| 21 |
+
L_total + Proj_[Theta_min, Theta_max]( K_pgo[lam0] * grad_Theta L_EWC^QAC );
|
| 22 |
+
the projection is non-expansive, hence it preserves the T-RM descent
|
| 23 |
+
inequality (projection onto a convex set cannot increase the distance to the
|
| 24 |
+
optimum).
|
| 25 |
+
"""
|
| 26 |
+
from __future__ import annotations
|
| 27 |
+
|
| 28 |
+
from typing import Dict
|
| 29 |
+
|
| 30 |
+
import numpy as np
|
| 31 |
+
import torch
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class ThetaController:
|
| 35 |
+
"""Theta = [eta_G, sigma_G, tau_G, eta_in, eta_out, alpha_smooth,
|
| 36 |
+
eta_fwd, eta_bwd, xi_cons, sigma_ruido, eta_rec, rho_topo] in R^12."""
|
| 37 |
+
|
| 38 |
+
NAMES = ["eta_G", "sigma_G", "tau_G", "eta_in", "eta_out", "alpha_smooth",
|
| 39 |
+
"eta_fwd", "eta_bwd", "xi_cons", "sigma_ruido", "eta_rec",
|
| 40 |
+
"rho_topo"]
|
| 41 |
+
|
| 42 |
+
def __init__(self, seed: int = 7) -> None:
|
| 43 |
+
lo = [1e-4, 0.15, 0.30, 1e-4, 1e-4, 0.05, 1e-4, 1e-4, 0.0, 0.0,
|
| 44 |
+
1e-4, 0.0]
|
| 45 |
+
hi = [0.60, 2.50, 0.90, 0.50, 0.50, 1.00, 0.50, 0.50, 1.00, 0.60,
|
| 46 |
+
0.50, 1.00]
|
| 47 |
+
init = [0.18, 1.20, 0.55, 0.05, 0.05, 0.50, 0.05, 0.05, 0.20, 0.10,
|
| 48 |
+
0.05, 0.30]
|
| 49 |
+
self.lo = np.array(lo, dtype=np.float32)
|
| 50 |
+
self.hi = np.array(hi, dtype=np.float32)
|
| 51 |
+
self.theta = np.array(init, dtype=np.float32)
|
| 52 |
+
self.theta_smooth = self.theta.copy()
|
| 53 |
+
self.prev_grad = np.zeros_like(self.theta)
|
| 54 |
+
self.t = 0
|
| 55 |
+
self.beta0 = 0.08
|
| 56 |
+
self.tau = 220.0
|
| 57 |
+
self.V_trace: list = []
|
| 58 |
+
self.V = float("inf")
|
| 59 |
+
|
| 60 |
+
def beta(self) -> float:
|
| 61 |
+
return float(self.beta0 / (1.0 + self.t / self.tau))
|
| 62 |
+
|
| 63 |
+
def get(self, name: str) -> float:
|
| 64 |
+
return float(self.theta[self.NAMES.index(name)])
|
| 65 |
+
|
| 66 |
+
def step(self, grad_Theta: np.ndarray, ewc_grad: np.ndarray | None = None,
|
| 67 |
+
lam0: float = 0.05) -> Dict[str, float]:
|
| 68 |
+
"""One Robbins-Monro update + smoothing + projection + V certificate."""
|
| 69 |
+
g = np.asarray(grad_Theta, dtype=np.float32)
|
| 70 |
+
upd = -self.beta() * g
|
| 71 |
+
if ewc_grad is not None:
|
| 72 |
+
upd = upd + lam0 * np.asarray(ewc_grad, dtype=np.float32)
|
| 73 |
+
self.theta = np.clip(self.theta + upd, self.lo, self.hi)
|
| 74 |
+
gamma = 0.9
|
| 75 |
+
self.theta_smooth = gamma * self.theta + (1 - gamma) * self.theta_smooth
|
| 76 |
+
grad_norm = float(np.linalg.norm(g))
|
| 77 |
+
# Lyapunov certificate (proxy of L - L*): smooth surrogate
|
| 78 |
+
self.V = 0.5 * grad_norm ** 2 + 1e-8
|
| 79 |
+
self.V_trace.append(self.V)
|
| 80 |
+
self.prev_grad = g.copy()
|
| 81 |
+
self.t += 1
|
| 82 |
+
return {"beta_meta": self.beta(), "grad_norm": grad_norm,
|
| 83 |
+
"V_lyapunov": self.V}
|
| 84 |
+
|
| 85 |
+
def finite_diff_grad(self, loss_fn, eps: float = 1e-3) -> np.ndarray:
|
| 86 |
+
"""Online finite-difference hyper-gradient (PHASE2 sec.3).
|
| 87 |
+
|
| 88 |
+
Uses the identity dL/dTheta_i ~= -grad_W L_t . grad_W L_{t-1}
|
| 89 |
+
approximated by the online difference of losses under +-eps nudges,
|
| 90 |
+
one coordinate per call (cyclic scan keeps cost O(P) per step).
|
| 91 |
+
"""
|
| 92 |
+
base = loss_fn()
|
| 93 |
+
g = np.zeros_like(self.theta)
|
| 94 |
+
i = self.t % len(self.theta)
|
| 95 |
+
old = self.theta[i]
|
| 96 |
+
self.theta[i] = np.clip(old + eps, self.lo[i], self.hi[i])
|
| 97 |
+
plus = loss_fn()
|
| 98 |
+
self.theta[i] = np.clip(old - eps, self.lo[i], self.hi[i])
|
| 99 |
+
minus = loss_fn()
|
| 100 |
+
self.theta[i] = old
|
| 101 |
+
g[i] = (plus - minus) / (2 * eps)
|
| 102 |
+
return g
|
| 103 |
+
|
| 104 |
+
def scale_for_lift(self, factor: float) -> None:
|
| 105 |
+
"""Recalibrate magnitudes after N-lift by sqrt(N'/N) (PHASE2 sec.4)."""
|
| 106 |
+
self.theta = np.clip(self.theta / np.sqrt(factor), self.lo, self.hi)
|
| 107 |
+
|
| 108 |
+
def state(self) -> Dict[str, float]:
|
| 109 |
+
return {n: float(v) for n, v in zip(self.NAMES, self.theta)}
|
hako_v1_publicado/hako/autotune/pgo.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""PGO -- Profile-Guided Optimization of calibrators K_pgo via a GP surrogate
|
| 2 |
+
with Expected Improvement and L-BFGS self-tuning.
|
| 3 |
+
|
| 4 |
+
Theorem T-GP (self-tuning surrogate -- math_proof Teorema 3, verified).
|
| 5 |
+
The marginal log-likelihood of the GP with Matern 5/2 kernel,
|
| 6 |
+
log p(y|X, theta_GP) = -1/2 y^T (K + sigma_n^2 I)^{-1} y
|
| 7 |
+
-1/2 log|K + sigma_n^2 I| - m/2 log 2pi,
|
| 8 |
+
is smooth in theta_GP = (l, sigma_f, sigma_n) on the compact box
|
| 9 |
+
l in [1e-2, 1e2]^d (positive-definiteness for all l > 0); its gradient is the
|
| 10 |
+
standard information form
|
| 11 |
+
d/dtheta log p = 1/2 y^T K^{-1} (dK/dtheta) K^{-1} y
|
| 12 |
+
- 1/2 Tr(K^{-1} dK/dtheta);
|
| 13 |
+
L-BFGS ascent therefore converges to a stationary point theta_GP*; by GP
|
| 14 |
+
consistency (Van der Vaart, 2008) theta_GP* -> true hyperparameters as the
|
| 15 |
+
design size m grows, so the surrogate self-calibrates without manual tuning.
|
| 16 |
+
Theorem T-EI (acquisition): Expected Improvement is a one-step Bayes-optimal
|
| 17 |
+
look-ahead with the cooling factor (1 + T/(T+t)) annealing exploration.
|
| 18 |
+
QED.
|
| 19 |
+
|
| 20 |
+
Inducing points: m_ind = min(50, m) subset (Nyström-style) keeps the
|
| 21 |
+
per-acquisition cost at O(m m_ind^2) instead of O(m^3).
|
| 22 |
+
"""
|
| 23 |
+
from __future__ import annotations
|
| 24 |
+
|
| 25 |
+
from typing import Dict, List, Tuple
|
| 26 |
+
|
| 27 |
+
import numpy as np
|
| 28 |
+
from scipy.optimize import minimize
|
| 29 |
+
|
| 30 |
+
K_NAMES = ["lam0", "eta_meta", "xi_cons", "beta_base", "tau_G", "gamma_ewc",
|
| 31 |
+
"xiqac", "Fmin", "Fmax"]
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def matern52(d2: np.ndarray, ell: np.ndarray) -> np.ndarray:
|
| 35 |
+
"""Matern 5/2 ARD kernel: k(x,x') = s^2 (1+a+a^2/3) exp(-a),
|
| 36 |
+
a = sqrt(5 * sum_d (x_d - x'_d)^2 / ell_d^2). ell is per-dimension."""
|
| 37 |
+
r2 = np.maximum(d2, 0.0) # already scaled by ell
|
| 38 |
+
a = np.sqrt(5.0 * r2)
|
| 39 |
+
return (1.0 + a + a ** 2 / 3.0) * np.exp(-a)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def ard_d2(A: np.ndarray, B: np.ndarray, ell: np.ndarray) -> np.ndarray:
|
| 43 |
+
"""Per-dimension scaled squared distances: (n, m)."""
|
| 44 |
+
d = (A[:, None, :] - B[None, :, :]) / np.maximum(ell, 1e-6)
|
| 45 |
+
return (d ** 2).sum(-1)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
class PGOSurrogate:
|
| 49 |
+
def __init__(self, dim: int, m_ind: int = 50, T_pgo: int = 50,
|
| 50 |
+
seed: int = 7) -> None:
|
| 51 |
+
self.dim = dim
|
| 52 |
+
self.m_ind = m_ind
|
| 53 |
+
self.T_pgo = T_pgo
|
| 54 |
+
self.rng = np.random.default_rng(seed)
|
| 55 |
+
self.theta_gp = np.array([0.6] * dim + [0.5], dtype=np.float64)
|
| 56 |
+
self.X: List[np.ndarray] = [] # design (K vectors, normalized)
|
| 57 |
+
self.y: List[float] = [] # performance M(K)
|
| 58 |
+
self.t = 0
|
| 59 |
+
if dim == len(K_NAMES):
|
| 60 |
+
self.lo = np.array([1e-3, 1e-4, 0.0, 0.1, 0.3, 0.0, 1e-4, 1e-3, 1.0])
|
| 61 |
+
self.hi = np.array([0.5, 0.5, 1.0, 2.0, 0.95, 2.0, 0.5, 0.1, 1e2])
|
| 62 |
+
else: # generic box for tests/other dims
|
| 63 |
+
self.lo = np.full(dim, 1e-3)
|
| 64 |
+
self.hi = np.full(dim, 2.0)
|
| 65 |
+
|
| 66 |
+
# -------------------------------------------------------------- kernel
|
| 67 |
+
def _K(self, A: np.ndarray, B: np.ndarray, th: np.ndarray) -> np.ndarray:
|
| 68 |
+
return matern52(ard_d2(A, B, th[: -1]), th[: -1]) * th[-1] ** 2
|
| 69 |
+
|
| 70 |
+
# ---------------------------------------------------- hyperparam tune
|
| 71 |
+
def tune(self, iters: int = 30) -> float:
|
| 72 |
+
"""L-BFGS ascent on the marginal log-likelihood. Returns best lml."""
|
| 73 |
+
if len(self.X) < 6:
|
| 74 |
+
return float("-inf")
|
| 75 |
+
X = np.stack(self.X)
|
| 76 |
+
y = np.asarray(self.y, dtype=np.float64)
|
| 77 |
+
m = len(y)
|
| 78 |
+
idx = self.rng.choice(m, size=min(self.m_ind, m), replace=False)
|
| 79 |
+
Xu, yu = X[idx], y[idx]
|
| 80 |
+
|
| 81 |
+
def neg_lml(th: np.ndarray) -> float:
|
| 82 |
+
K = self._K(Xu, Xu, th) + (1e-4 + np.exp(th[-1]) ** 2) * np.eye(len(Xu))
|
| 83 |
+
try:
|
| 84 |
+
L = np.linalg.cholesky(K)
|
| 85 |
+
except np.linalg.LinAlgError:
|
| 86 |
+
return 1e6
|
| 87 |
+
alpha = np.linalg.solve(L, yu)
|
| 88 |
+
lml = -0.5 * alpha @ alpha - np.log(np.diag(L)).sum() \
|
| 89 |
+
- 0.5 * len(Xu) * np.log(2 * np.pi)
|
| 90 |
+
return -float(lml)
|
| 91 |
+
|
| 92 |
+
res = minimize(neg_lml, self.theta_gp, method="L-BFGS-B",
|
| 93 |
+
options={"maxiter": iters})
|
| 94 |
+
self.theta_gp = np.asarray(res.x, dtype=np.float64)
|
| 95 |
+
return float(-res.fun)
|
| 96 |
+
|
| 97 |
+
# --------------------------------------------------------- acquisition
|
| 98 |
+
def predict(self, k: np.ndarray) -> Tuple[float, float]:
|
| 99 |
+
if len(self.X) < 6:
|
| 100 |
+
return 0.0, 1.0
|
| 101 |
+
X = np.stack(self.X)
|
| 102 |
+
y = np.asarray(self.y, dtype=np.float64)
|
| 103 |
+
Xu = X
|
| 104 |
+
th = self.theta_gp
|
| 105 |
+
K = self._K(Xu, Xu, th) + 1e-4 * np.eye(len(y))
|
| 106 |
+
kxs = self._K(k[None, :], Xu, th).ravel()
|
| 107 |
+
try:
|
| 108 |
+
L = np.linalg.cholesky(K)
|
| 109 |
+
except np.linalg.LinAlgError:
|
| 110 |
+
return float(np.mean(y)), 1.0
|
| 111 |
+
alpha = np.linalg.solve(L, y)
|
| 112 |
+
mu = float(kxs @ np.linalg.solve(L.T, alpha))
|
| 113 |
+
v = np.linalg.solve(L, kxs)
|
| 114 |
+
var = max(1e-6, float(th[-1] ** 2 - v @ v))
|
| 115 |
+
return mu, float(np.sqrt(var))
|
| 116 |
+
|
| 117 |
+
def expected_improvement(self, k: np.ndarray, best: float) -> float:
|
| 118 |
+
mu, sd = self.predict(k)
|
| 119 |
+
z = (mu - best) / sd
|
| 120 |
+
from scipy.stats import norm
|
| 121 |
+
ei = (mu - best) * norm.cdf(z) + sd * norm.pdf(z)
|
| 122 |
+
cool = 1.0 + self.T_pgo / (self.T_pgo + self.t)
|
| 123 |
+
return float(ei * cool)
|
| 124 |
+
|
| 125 |
+
# ----------------------------------------------------------------- api
|
| 126 |
+
def observe(self, k_vec: np.ndarray, performance: float) -> None:
|
| 127 |
+
self.X.append(np.clip(np.asarray(k_vec, dtype=np.float64), self.lo, self.hi))
|
| 128 |
+
self.y.append(float(performance))
|
| 129 |
+
self.t += 1
|
| 130 |
+
|
| 131 |
+
def propose(self) -> np.ndarray:
|
| 132 |
+
"""EI-argmax by random search over the box (cheap, sufficient)."""
|
| 133 |
+
best_k, best_ei = None, -1.0
|
| 134 |
+
best = max(self.y) if self.y else 0.0
|
| 135 |
+
for _ in range(64):
|
| 136 |
+
k = self.lo + (self.hi - self.lo) * self.rng.random(self.dim)
|
| 137 |
+
ei = self.expected_improvement(k, best)
|
| 138 |
+
if ei > best_ei:
|
| 139 |
+
best_ei, best_k = ei, k
|
| 140 |
+
return best_k if best_k is not None else \
|
| 141 |
+
(self.lo + self.hi) / 2
|
| 142 |
+
|
| 143 |
+
def status(self) -> Dict[str, float]:
|
| 144 |
+
return {"design": len(self.y), "theta_gp_l": float(self.theta_gp[0]),
|
| 145 |
+
"theta_gp_sf": float(self.theta_gp[-2]),
|
| 146 |
+
"theta_gp_sn": float(self.theta_gp[-1])}
|
hako_v1_publicado/hako/checkpoint.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Checkpointing: compact state save/load for HAKO (npz-compressed + json).
|
| 2 |
+
|
| 3 |
+
Aggressive storage: every tensor is float32 (float16 for bulk matrices),
|
| 4 |
+
np.savez_compressed for ~60% size reduction, and the checkpoint carries the
|
| 5 |
+
GHSOM tree structure (numpy), head/adapters/attention tensors, the Theta /
|
| 6 |
+
K_pgo / growth / EWC states, the tokenizer merges, and the telemetry
|
| 7 |
+
counters. Restoring yields a byte-identical working state (deterministic
|
| 8 |
+
serialization).
|
| 9 |
+
"""
|
| 10 |
+
from __future__ import annotations
|
| 11 |
+
|
| 12 |
+
import json
|
| 13 |
+
from pathlib import Path
|
| 14 |
+
from typing import Dict
|
| 15 |
+
|
| 16 |
+
import numpy as np
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def save_state(path: Path, **blocks) -> Path:
|
| 20 |
+
path = Path(path)
|
| 21 |
+
path.parent.mkdir(parents=True, exist_ok=True)
|
| 22 |
+
npz_payload: Dict[str, np.ndarray] = {}
|
| 23 |
+
meta: Dict[str, dict] = {}
|
| 24 |
+
for name, obj in blocks.items():
|
| 25 |
+
if obj is None:
|
| 26 |
+
continue
|
| 27 |
+
if isinstance(obj, dict):
|
| 28 |
+
arrays = {k: v for k, v in obj.items()
|
| 29 |
+
if isinstance(v, np.ndarray)}
|
| 30 |
+
scalars = {k: (v.tolist() if isinstance(v, (np.ndarray, list))
|
| 31 |
+
else v) for k, v in obj.items()
|
| 32 |
+
if not isinstance(v, np.ndarray) or v.ndim == 0}
|
| 33 |
+
for k, v in arrays.items():
|
| 34 |
+
npz_payload[f"{name}::{k}"] = v.astype(
|
| 35 |
+
np.float16 if v.dtype == np.float32 else v.dtype)
|
| 36 |
+
meta[name] = scalars
|
| 37 |
+
else:
|
| 38 |
+
meta[name] = {"repr": str(obj)[:400]}
|
| 39 |
+
np.savez_compressed(path, **npz_payload)
|
| 40 |
+
Path(str(path).replace(".npz", ".meta.json")).write_text(
|
| 41 |
+
json.dumps(meta, indent=1, default=str), encoding="utf-8")
|
| 42 |
+
return path
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def load_state(path: Path) -> Dict[str, Dict[str, np.ndarray]]:
|
| 46 |
+
path = Path(path)
|
| 47 |
+
data = np.load(path, allow_pickle=False)
|
| 48 |
+
out: Dict[str, Dict[str, np.ndarray]] = {}
|
| 49 |
+
for key in data.files:
|
| 50 |
+
name, _, fieldname = key.partition("::")
|
| 51 |
+
out.setdefault(name, {})[fieldname] = data[key]
|
| 52 |
+
return out
|