initium-deeplearning 0.1.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/.gitignore +5 -0
  2. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/PKG-INFO +59 -1
  3. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/README.md +58 -0
  4. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/pyproject.toml +1 -0
  5. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/__init__.py +1 -1
  6. initium_deeplearning-0.2.1/src/initium/__init__.py +104 -0
  7. initium_deeplearning-0.2.1/src/initium/analysis/__init__.py +1 -0
  8. initium_deeplearning-0.2.1/src/initium/analysis/kl_attribution.py +291 -0
  9. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/config/controller_config.py +7 -0
  10. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/core_training.py +847 -20
  11. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/common/chain_task.py +7 -1
  12. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/common/digit_codec.py +14 -0
  13. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/dataset_registry.py +3 -0
  14. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/graph_traversal/graph_traversal.py +7 -1
  15. initium_deeplearning-0.2.1/src/initium/data/graph_traversal/order_probe.py +219 -0
  16. initium_deeplearning-0.2.1/src/initium/data/graph_traversal/relational_probe.py +123 -0
  17. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/multimodal/multimodal_dataset.py +7 -1
  18. initium_deeplearning-0.2.1/src/initium/data/prepared_dataset.py +56 -0
  19. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/model_loader.py +11 -0
  20. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/run_inference.py +61 -2
  21. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/tasks/audio_task.py +2 -2
  22. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/tasks/graph_traversal_task.py +15 -2
  23. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/tasks/task_registry.py +1 -0
  24. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/tasks/text_task.py +2 -2
  25. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/tasks/video_task.py +2 -2
  26. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/mamba_controller/split_graph_dnc.py +17 -2
  27. initium_deeplearning-0.2.1/src/initium/memory_manipulation/dnc_mechanisms.py +355 -0
  28. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/memory_manipulation/dynamic_memory_resize.py +23 -5
  29. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/memory_manipulation/link_matrix_ablation.py +11 -1
  30. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/memory_manipulation/nvrtc_compat.py +25 -28
  31. initium_deeplearning-0.1.0/src/initium/__init__.py +0 -1
  32. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/LICENSE +0 -0
  33. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/LNN_controller/cfc_backbone_parallel.py +0 -0
  34. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/LNN_controller/cfc_controller.py +0 -0
  35. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/LNN_controller/chained_controller.py +0 -0
  36. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/LNN_controller/hybrid_controller.py +0 -0
  37. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/MoE/README.md +0 -0
  38. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/MoE/moe_layer.py +0 -0
  39. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/config/train_config.py +0 -0
  40. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/__init__.py +0 -0
  41. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/audio/__init__.py +0 -0
  42. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/audio/audio_dataset.py +0 -0
  43. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/base_dataset.py +0 -0
  44. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/common/__init__.py +0 -0
  45. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/common/graph_io.py +0 -0
  46. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/common/real_data.py +0 -0
  47. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/graph_traversal/__init__.py +0 -0
  48. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/multimodal/__init__.py +0 -0
  49. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/text/__init__.py +0 -0
  50. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/text/text_dataset.py +0 -0
  51. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/video/__init__.py +0 -0
  52. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/data/video/video_dataset.py +0 -0
  53. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/__init__.py +0 -0
  54. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/cache/__init__.py +0 -0
  55. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/cache/base_cache.py +0 -0
  56. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/cache/cache_config.py +0 -0
  57. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/cache/cache_registry.py +0 -0
  58. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/cache/cached_engine.py +0 -0
  59. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/cache/keys.py +0 -0
  60. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/cache/prefix_cache.py +0 -0
  61. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/cache/result_cache.py +0 -0
  62. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/cache/state_utils.py +0 -0
  63. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/cache/stores.py +0 -0
  64. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/capabilities.py +0 -0
  65. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/checkpoint_io.py +0 -0
  66. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/engine.py +0 -0
  67. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/inference_config.py +0 -0
  68. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/metrics.py +0 -0
  69. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/run_logging.py +0 -0
  70. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/tasks/__init__.py +0 -0
  71. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/tasks/base_task.py +0 -0
  72. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/inference/tasks/multimodal_task.py +0 -0
  73. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/mamba_controller/mamba2_controller.py +0 -0
  74. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/mamba_controller/mamba3_controller.py +0 -0
  75. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/mamba_controller/mamba_backbone_parallel.py +0 -0
  76. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/mamba_controller/mamba_controller.py +0 -0
  77. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/memory_manipulation/dynamic_n_controller.py +0 -0
  78. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/memory_manipulation/stochastic_write_head_v2.py +0 -0
  79. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/src/initium/setup_wheels.py +0 -0
  80. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/README.md +0 -0
  81. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/checkpoint/test_checkpoint_roundtrip.py +0 -0
  82. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/checkpoint/test_resume_training.py +0 -0
  83. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/conftest.py +0 -0
  84. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/gradients/test_controller_cell_backward.py +0 -0
  85. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/gradients/test_kl_gradients.py +0 -0
  86. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/gradients/test_moe_aux_loss_gradients.py +0 -0
  87. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/integration/test_controller_matrix.py +0 -0
  88. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/integration/test_dynamic_n_end_to_end.py +0 -0
  89. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/integration/test_moe_integration.py +0 -0
  90. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/integration/test_resize_x_link_matrix.py +0 -0
  91. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/integration/test_split_graph_dnc.py +0 -0
  92. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/smoke/test_inference_smoke.py +0 -0
  93. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/smoke/test_tiny_training_run.py +0 -0
  94. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/unit/test_capabilities.py +0 -0
  95. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/unit/test_checkpoint_io.py +0 -0
  96. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/unit/test_dynamic_n_controller.py +0 -0
  97. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/unit/test_link_matrix_ablation.py +0 -0
  98. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/unit/test_model_loader.py +0 -0
  99. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/unit/test_moe_layer.py +0 -0
  100. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/unit/test_nvrtc_compat.py +0 -0
  101. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/unit/test_real_data_pipeline.py +0 -0
  102. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/unit/test_resize_memory.py +0 -0
  103. {initium_deeplearning-0.1.0 → initium_deeplearning-0.2.1}/tests/unit/test_stochastic_write_head.py +0 -0
@@ -216,3 +216,8 @@ __marimo__/
216
216
 
217
217
  # Streamlit
218
218
  .streamlit/secrets.toml
219
+
220
+ # Experimental documents for context, not to be committed
221
+ documents/*
222
+ dnc-context/*
223
+ tmp/*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: initium-deeplearning
3
- Version: 0.1.0
3
+ Version: 0.2.1
4
4
  Summary: Differentiable Neural Computer research framework with pluggable LSTM/Mamba/CfC controllers, MoE, split-graph and stochastic write heads.
5
5
  Project-URL: Homepage, https://github.com/samueleternity/initium
6
6
  Project-URL: Issues, https://github.com/samueleternity/initium/issues
@@ -47,6 +47,45 @@ The project studies how a neural controller can interact with a differentiable e
47
47
 
48
48
  These are research questions, not all established project claims. In particular, supported dataset interfaces do not imply that every modality has been trained and validated to the same standard as graph traversal.
49
49
 
50
+ ## Launch
51
+
52
+ You can either fork/clone the repository and customize everything you need or you can use pip/pdm/uv for ready to use installation.
53
+
54
+ Guide for pip usage:
55
+
56
+ To install the whole framework: pip install initium-deeplearning
57
+
58
+ For ANY mamba related operation you need: python -m initium.setup_wheels
59
+
60
+ Optionally you can try:
61
+ pip install "initium-deeplearning[text]"
62
+ pip install "initium-deeplearning[video]"
63
+ pip install "initium-deeplearning[real-data]"
64
+
65
+ To see all CLI optionality:
66
+ initium-infer --help
67
+ python initium.core_training --help
68
+
69
+ Example usage:
70
+
71
+ python -m initium.core_training 0.0 --controller lstm
72
+ python -m initium.core_training 0.0 --split-graph --split-graph-variant mamba1 ...
73
+
74
+ Inference runs need a checkpoint first. The built-in tool analyzes it and refuses unsupported task types or dimensions. Dataset preparation-only mode does not need a checkpoint.
75
+
76
+ ### Reusing prepared datasets
77
+
78
+ Training and inference can save the processed dataset state so the raw source is not parsed or tokenized again. `--save DIRECTORY` writes to `DIRECTORY/<type>/<source> [prepared]/dataset.pkl`; `--load-prepared` accepts that prepared folder (or a save root containing exactly one prepared dataset of the requested type). When loading, `--dataset-link` is optional. Use `--prepare-only` with `--save` to prepare and save a dataset without starting a run:
79
+
80
+ ```bash
81
+ python -m initium.core_training 0.0 --dataset-type text --dataset-link ./corpus.txt --save ./prepared --prepare-only
82
+ python -m initium.core_training 0.0 --dataset-type text --load-prepared "./prepared/text/corpus [prepared]"
83
+ initium-infer checkpoint.pt --dataset-type text --load-prepared "./prepared/text/corpus [prepared]"
84
+ initium-infer --dataset-type text --dataset-link ./corpus.txt --save ./prepared --prepare-only
85
+ ```
86
+
87
+ Prepared artifacts retain the resolved train/test pools or graph mappings, including the split used when they were created. They are Python pickle files and should only be loaded from sources you trust.
88
+
50
89
  ## High-level flow
51
90
 
52
91
  ```text
@@ -79,6 +118,25 @@ The training core delegates task construction and task-specific behavior to a da
79
118
 
80
119
  The DNC supplies a memory matrix and differentiable read/write interface. The memory can retain information beyond a controller's immediate hidden state. Content-based addressing, read heads, and temporal-link structures are part of the underlying DNC implementation. The temporal link matrix has quadratic cost in the number of memory cells, which motivates the project's link-matrix ablations and memory-size investigations.
81
120
 
121
+ ### Read/write mechanism roadmap
122
+
123
+ The split-graph memory exposes independent read and write variants while retaining the DNC usage, allocation, write addressing, read modes, and temporal-link machinery:
124
+
125
+ - `--dnc-read-variant cosine` is the DNC baseline. `relational-mlp` replaces cosine similarity with a learned score for each `(query, memory row)` pair. `relational-residual` adds a scaled learned pairwise score to cosine and zero-initializes its final layer, so it starts exactly at the DNC baseline. `--dnc-read-residual-scale` controls that correction's strength (default `1.0`). Track A logs the correction-to-cosine RMS ratio to show whether it contributes meaningfully. Write content addressing remains cosine-based for both learned readers.
126
+ - `--dnc-write-variant learned` is the DNC baseline. `kanerva-closed-form` turns the existing write-value projection into an observation and applies a per-row online isotropic Gaussian posterior update. It does not import the Kanerva Machine's exchangeable episode objective or claim to reproduce its full generative model.
127
+ - The variants compose, so the four baseline / Track A / Track B / combined cells are expressible through the same training and checkpoint pipeline. The closed-form writer uses a deterministic observation projection; the stochastic write head is not installed for that variant.
128
+ - The graph curriculum emits ID, OOD, and OOD-offset metrics as before. Graph runs also write `run_<id>_relational_probe.csv`, with cosine top-1, selected read-head top-1, and held-out-composition accuracy. `data/graph_traversal/order_probe.py` supplies paired prefix-permutation helpers for the Q99 order-sensitivity evaluation.
129
+ - Split-graph graph runs also write `run_<id>_track_a.csv` and `run_<id>_track_b.csv`. Track A records ID/OOD accuracy, relational stress and held-out-composition accuracy, ordinary-input read-score/cosine correlation, and read-content entropy/maximum weight. Track B records the Q99 order-sensitivity gate, ID/OOD posterior variance and write-update diagnostics, and training-window loss, gradient norm, AMP scale, and learning rate. These are experiment logs; no training or evaluation results are checked in.
130
+
131
+ Use the selected split-graph baseline with either supported controller combiner:
132
+
133
+ ```bash
134
+ python -m initium.core_training 0.0 --split-graph --split-graph-variant mamba1 --split-graph-combiner-mode controller --split-graph-combiner-variant cfc
135
+ python -m initium.core_training 0.0 --split-graph --split-graph-variant mamba1 --split-graph-combiner-mode controller --split-graph-combiner-variant mamba+cfc
136
+ ```
137
+
138
+ Add `--dnc-read-variant relational-mlp` to reproduce the original Track A reader, or `--dnc-read-variant relational-residual --dnc-read-residual-scale 1.0` to use the cosine-anchored Track A reader. Lower scales such as `0.5` are available for follow-up comparisons. Use `--dnc-write-variant kanerva-closed-form` for Track B. Add a reader and writer variant together only for the combined cell after each track is characterized. Dense temporal links remain the default. The short-run baseline reproduction gate and the Q99 paired-order evaluation are deliberate user-run experiment steps; no run results are assumed by this repository change.
139
+
82
140
  ### Controllers
83
141
 
84
142
  The training core exposes controller choices through its command-line interface and configuration:
@@ -16,6 +16,45 @@ The project studies how a neural controller can interact with a differentiable e
16
16
 
17
17
  These are research questions, not all established project claims. In particular, supported dataset interfaces do not imply that every modality has been trained and validated to the same standard as graph traversal.
18
18
 
19
+ ## Launch
20
+
21
+ You can either fork/clone the repository and customize everything you need or you can use pip/pdm/uv for ready to use installation.
22
+
23
+ Guide for pip usage:
24
+
25
+ To install the whole framework: pip install initium-deeplearning
26
+
27
+ For ANY mamba related operation you need: python -m initium.setup_wheels
28
+
29
+ Optionally you can try:
30
+ pip install "initium-deeplearning[text]"
31
+ pip install "initium-deeplearning[video]"
32
+ pip install "initium-deeplearning[real-data]"
33
+
34
+ To see all CLI optionality:
35
+ initium-infer --help
36
+ python initium.core_training --help
37
+
38
+ Example usage:
39
+
40
+ python -m initium.core_training 0.0 --controller lstm
41
+ python -m initium.core_training 0.0 --split-graph --split-graph-variant mamba1 ...
42
+
43
+ Inference runs need a checkpoint first. The built-in tool analyzes it and refuses unsupported task types or dimensions. Dataset preparation-only mode does not need a checkpoint.
44
+
45
+ ### Reusing prepared datasets
46
+
47
+ Training and inference can save the processed dataset state so the raw source is not parsed or tokenized again. `--save DIRECTORY` writes to `DIRECTORY/<type>/<source> [prepared]/dataset.pkl`; `--load-prepared` accepts that prepared folder (or a save root containing exactly one prepared dataset of the requested type). When loading, `--dataset-link` is optional. Use `--prepare-only` with `--save` to prepare and save a dataset without starting a run:
48
+
49
+ ```bash
50
+ python -m initium.core_training 0.0 --dataset-type text --dataset-link ./corpus.txt --save ./prepared --prepare-only
51
+ python -m initium.core_training 0.0 --dataset-type text --load-prepared "./prepared/text/corpus [prepared]"
52
+ initium-infer checkpoint.pt --dataset-type text --load-prepared "./prepared/text/corpus [prepared]"
53
+ initium-infer --dataset-type text --dataset-link ./corpus.txt --save ./prepared --prepare-only
54
+ ```
55
+
56
+ Prepared artifacts retain the resolved train/test pools or graph mappings, including the split used when they were created. They are Python pickle files and should only be loaded from sources you trust.
57
+
19
58
  ## High-level flow
20
59
 
21
60
  ```text
@@ -48,6 +87,25 @@ The training core delegates task construction and task-specific behavior to a da
48
87
 
49
88
  The DNC supplies a memory matrix and differentiable read/write interface. The memory can retain information beyond a controller's immediate hidden state. Content-based addressing, read heads, and temporal-link structures are part of the underlying DNC implementation. The temporal link matrix has quadratic cost in the number of memory cells, which motivates the project's link-matrix ablations and memory-size investigations.
50
89
 
90
+ ### Read/write mechanism roadmap
91
+
92
+ The split-graph memory exposes independent read and write variants while retaining the DNC usage, allocation, write addressing, read modes, and temporal-link machinery:
93
+
94
+ - `--dnc-read-variant cosine` is the DNC baseline. `relational-mlp` replaces cosine similarity with a learned score for each `(query, memory row)` pair. `relational-residual` adds a scaled learned pairwise score to cosine and zero-initializes its final layer, so it starts exactly at the DNC baseline. `--dnc-read-residual-scale` controls that correction's strength (default `1.0`). Track A logs the correction-to-cosine RMS ratio to show whether it contributes meaningfully. Write content addressing remains cosine-based for both learned readers.
95
+ - `--dnc-write-variant learned` is the DNC baseline. `kanerva-closed-form` turns the existing write-value projection into an observation and applies a per-row online isotropic Gaussian posterior update. It does not import the Kanerva Machine's exchangeable episode objective or claim to reproduce its full generative model.
96
+ - The variants compose, so the four baseline / Track A / Track B / combined cells are expressible through the same training and checkpoint pipeline. The closed-form writer uses a deterministic observation projection; the stochastic write head is not installed for that variant.
97
+ - The graph curriculum emits ID, OOD, and OOD-offset metrics as before. Graph runs also write `run_<id>_relational_probe.csv`, with cosine top-1, selected read-head top-1, and held-out-composition accuracy. `data/graph_traversal/order_probe.py` supplies paired prefix-permutation helpers for the Q99 order-sensitivity evaluation.
98
+ - Split-graph graph runs also write `run_<id>_track_a.csv` and `run_<id>_track_b.csv`. Track A records ID/OOD accuracy, relational stress and held-out-composition accuracy, ordinary-input read-score/cosine correlation, and read-content entropy/maximum weight. Track B records the Q99 order-sensitivity gate, ID/OOD posterior variance and write-update diagnostics, and training-window loss, gradient norm, AMP scale, and learning rate. These are experiment logs; no training or evaluation results are checked in.
99
+
100
+ Use the selected split-graph baseline with either supported controller combiner:
101
+
102
+ ```bash
103
+ python -m initium.core_training 0.0 --split-graph --split-graph-variant mamba1 --split-graph-combiner-mode controller --split-graph-combiner-variant cfc
104
+ python -m initium.core_training 0.0 --split-graph --split-graph-variant mamba1 --split-graph-combiner-mode controller --split-graph-combiner-variant mamba+cfc
105
+ ```
106
+
107
+ Add `--dnc-read-variant relational-mlp` to reproduce the original Track A reader, or `--dnc-read-variant relational-residual --dnc-read-residual-scale 1.0` to use the cosine-anchored Track A reader. Lower scales such as `0.5` are available for follow-up comparisons. Use `--dnc-write-variant kanerva-closed-form` for Track B. Add a reader and writer variant together only for the combined cell after each track is characterized. Dense temporal links remain the default. The short-run baseline reproduction gate and the Q99 paired-order evaluation are deliberate user-run experiment steps; no run results are assumed by this repository change.
108
+
51
109
  ### Controllers
52
110
 
53
111
  The training core exposes controller choices through its command-line interface and configuration:
@@ -38,6 +38,7 @@ real-data = ["initium-deeplearning[text,video]"]
38
38
  [project.scripts]
39
39
  initium-setup = "initium.setup_wheels:main"
40
40
  initium-infer = "initium.inference.run_inference:main"
41
+ initium-kl-attribution = "initium.analysis.kl_attribution:main"
41
42
 
42
43
  [project.urls]
43
44
  Homepage = "https://github.com/samueleternity/initium"
@@ -1,3 +1,3 @@
1
1
  """initium - modular Differentiable Neural Computer research framework."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.2.1"
@@ -0,0 +1,104 @@
1
+ """Initium's stable architecture API.
2
+
3
+ Import mechanism-layer components from this package, for example::
4
+
5
+ from initium import SplitGraphDNC, MambaDNC, resize_memory
6
+
7
+ Training and inference entry points remain in their existing modules
8
+ (``initium.core_training`` and ``initium.inference``). Dataset encoders,
9
+ ``DigitCodec``, and task/curriculum implementations under ``initium.data``
10
+ are intentionally internal: they describe replaceable representations, not
11
+ the architecture contract. Exports are lazy so importing the package does
12
+ not import a training CLI or optional model dependencies unnecessarily.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from importlib import import_module
18
+ from typing import TYPE_CHECKING, Any
19
+
20
+ __all__ = [
21
+ # DNC architectures
22
+ "SplitGraphDNC",
23
+ "MambaDNC",
24
+ # Controller mechanisms and compositions
25
+ "MambaControllerWrapper",
26
+ "Mamba2ControllerWrapper",
27
+ "Mamba3ControllerWrapper",
28
+ "CfCControllerWrapper",
29
+ "ChainedControllerWrapper",
30
+ "build_hybrid_controller",
31
+ # Routing and stochastic memory writes
32
+ "StochasticWriteHead",
33
+ "SwitchMoE",
34
+ "MoEBlock",
35
+ # Memory and checkpoint mechanics
36
+ "resize_memory",
37
+ "load_checkpoint",
38
+ "describe_checkpoint",
39
+ "load_model",
40
+ "LoadedModel",
41
+ ]
42
+
43
+ _EXPORTS = {
44
+ "SplitGraphDNC": "initium.mamba_controller.split_graph_dnc",
45
+ "MambaDNC": "initium.mamba_controller.mamba_controller",
46
+ "MambaControllerWrapper": "initium.mamba_controller.mamba_controller",
47
+ "Mamba2ControllerWrapper": "initium.mamba_controller.mamba2_controller",
48
+ "Mamba3ControllerWrapper": "initium.mamba_controller.mamba3_controller",
49
+ "CfCControllerWrapper": "initium.LNN_controller.cfc_controller",
50
+ "ChainedControllerWrapper": "initium.LNN_controller.chained_controller",
51
+ "build_hybrid_controller": "initium.LNN_controller.hybrid_controller",
52
+ "StochasticWriteHead": "initium.memory_manipulation.stochastic_write_head_v2",
53
+ "SwitchMoE": "initium.MoE.moe_layer",
54
+ "MoEBlock": "initium.MoE.moe_layer",
55
+ "resize_memory": "initium.memory_manipulation.dynamic_memory_resize",
56
+ "load_checkpoint": "initium.inference.checkpoint_io",
57
+ "describe_checkpoint": "initium.inference.checkpoint_io",
58
+ "load_model": "initium.inference.model_loader",
59
+ "LoadedModel": "initium.inference.model_loader",
60
+ }
61
+
62
+ if TYPE_CHECKING:
63
+ from initium.inference.checkpoint_io import describe_checkpoint as describe_checkpoint
64
+ from initium.inference.checkpoint_io import load_checkpoint as load_checkpoint
65
+ from initium.inference.model_loader import LoadedModel as LoadedModel
66
+ from initium.inference.model_loader import load_model as load_model
67
+ from initium.LNN_controller.cfc_controller import CfCControllerWrapper as CfCControllerWrapper
68
+ from initium.LNN_controller.chained_controller import (
69
+ ChainedControllerWrapper as ChainedControllerWrapper,
70
+ )
71
+ from initium.LNN_controller.hybrid_controller import (
72
+ build_hybrid_controller as build_hybrid_controller,
73
+ )
74
+ from initium.mamba_controller.mamba2_controller import (
75
+ Mamba2ControllerWrapper as Mamba2ControllerWrapper,
76
+ )
77
+ from initium.mamba_controller.mamba3_controller import (
78
+ Mamba3ControllerWrapper as Mamba3ControllerWrapper,
79
+ )
80
+ from initium.mamba_controller.mamba_controller import (
81
+ MambaControllerWrapper as MambaControllerWrapper,
82
+ )
83
+ from initium.mamba_controller.mamba_controller import MambaDNC as MambaDNC
84
+ from initium.mamba_controller.split_graph_dnc import SplitGraphDNC as SplitGraphDNC
85
+ from initium.memory_manipulation.dynamic_memory_resize import resize_memory as resize_memory
86
+ from initium.memory_manipulation.stochastic_write_head_v2 import (
87
+ StochasticWriteHead as StochasticWriteHead,
88
+ )
89
+ from initium.MoE.moe_layer import MoEBlock as MoEBlock
90
+ from initium.MoE.moe_layer import SwitchMoE as SwitchMoE
91
+
92
+
93
+ def __getattr__(name: str) -> Any:
94
+ """Resolve only names explicitly listed in the stable public API."""
95
+ module_name = _EXPORTS.get(name)
96
+ if module_name is None:
97
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
98
+ value = getattr(import_module(module_name), name)
99
+ globals()[name] = value
100
+ return value
101
+
102
+
103
+ def __dir__() -> list[str]:
104
+ return sorted(set(globals()) | set(__all__))
@@ -0,0 +1 @@
1
+ """Analysis helpers for matched Initium experiment runs."""
@@ -0,0 +1,291 @@
1
+ """Matched-pair OGS/KL attribution report generator.
2
+
3
+ Manifest example::
4
+
5
+ {"pairs": [{"seed": 1, "beta0_ogs": "...csv", "beta_ogs": "...csv",
6
+ "beta0_train": "...csv", "beta_train": "...csv"}]}
7
+
8
+ Select the evaluation window before examining outcomes with --step-start and
9
+ --step-end. Each run is averaged over that same inclusive step interval before
10
+ the within-seed beta-minus-zero difference is computed.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import csv
17
+ import json
18
+ import math
19
+ from pathlib import Path
20
+
21
+ METRICS = (
22
+ "ogs",
23
+ "ood_acc",
24
+ "offset_normalized",
25
+ "memory_attributable_ood",
26
+ "ood_perfect_frac",
27
+ )
28
+
29
+
30
+ def _read_window(path, step_start, step_end, columns):
31
+ rows = []
32
+ with open(path, newline="", encoding="utf-8") as f:
33
+ for row in csv.DictReader(f):
34
+ step = int(float(row["step"]))
35
+ if step_start <= step <= step_end:
36
+ rows.append(
37
+ {name: float(row[name]) for name in columns if row.get(name) not in (None, "")}
38
+ )
39
+ if not rows:
40
+ raise ValueError(f"{path}: no rows in preregistered step window {step_start}..{step_end}")
41
+ return {
42
+ name: sum(row[name] for row in rows if name in row) / sum(name in row for row in rows)
43
+ for name in columns
44
+ if any(name in row for row in rows)
45
+ }
46
+
47
+
48
+ def _mean(values):
49
+ return sum(values) / len(values)
50
+
51
+
52
+ def _sd(values):
53
+ return (
54
+ math.sqrt(sum((x - _mean(values)) ** 2 for x in values) / (len(values) - 1))
55
+ if len(values) > 1
56
+ else 0.0
57
+ )
58
+
59
+
60
+ def _betacf(a, b, x):
61
+ qab, qap, qam = a + b, a + 1.0, a - 1.0
62
+ c, d = 1.0, 1.0 - qab * x / qap
63
+ d = 1e-300 if abs(d) < 1e-300 else 1.0 / d
64
+ h = d
65
+ for m in range(1, 201):
66
+ m2 = 2 * m
67
+ aa = m * (b - m) * x / ((qam + m2) * (a + m2))
68
+ d = 1.0 + aa * d
69
+ d = 1e-300 if abs(d) < 1e-300 else d
70
+ c = 1.0 + aa / c
71
+ c = 1e-300 if abs(c) < 1e-300 else c
72
+ d = 1.0 / d
73
+ h *= d * c
74
+ aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2))
75
+ d = 1.0 + aa * d
76
+ d = 1e-300 if abs(d) < 1e-300 else d
77
+ c = 1.0 + aa / c
78
+ c = 1e-300 if abs(c) < 1e-300 else c
79
+ d = 1.0 / d
80
+ delta = d * c
81
+ h *= delta
82
+ if abs(delta - 1.0) < 3e-14:
83
+ break
84
+ return h
85
+
86
+
87
+ def _ibeta(a, b, x):
88
+ if x <= 0:
89
+ return 0.0
90
+ if x >= 1:
91
+ return 1.0
92
+ factor = math.exp(
93
+ math.lgamma(a + b) - math.lgamma(a) - math.lgamma(b) + a * math.log(x) + b * math.log1p(-x)
94
+ )
95
+ if x < (a + 1.0) / (a + b + 2.0):
96
+ return factor * _betacf(a, b, x) / a
97
+ return 1.0 - factor * _betacf(b, a, 1.0 - x) / b
98
+
99
+
100
+ def _t_cdf(t, degrees):
101
+ x = degrees / (degrees + t * t)
102
+ tail = 0.5 * _ibeta(degrees / 2.0, 0.5, x)
103
+ return 1.0 - tail if t >= 0 else tail
104
+
105
+
106
+ def _t_critical(degrees, confidence=0.95):
107
+ target = (1.0 + confidence) / 2.0
108
+ lo, hi = 0.0, 100.0
109
+ for _ in range(100):
110
+ mid = (lo + hi) / 2
111
+ if _t_cdf(mid, degrees) < target:
112
+ lo = mid
113
+ else:
114
+ hi = mid
115
+ return (lo + hi) / 2
116
+
117
+
118
+ def _pearson(xs, ys):
119
+ if len(xs) < 2:
120
+ return float("nan")
121
+ mx, my = _mean(xs), _mean(ys)
122
+ xx = sum((x - mx) ** 2 for x in xs)
123
+ yy = sum((y - my) ** 2 for y in ys)
124
+ if xx == 0 or yy == 0:
125
+ return float("nan")
126
+ return sum((x - mx) * (y - my) for x, y in zip(xs, ys)) / math.sqrt(xx * yy)
127
+
128
+
129
+ def _paired_report(deltas):
130
+ n = len(deltas)
131
+ mean = _mean(deltas)
132
+ sd = _sd(deltas)
133
+ se = sd / math.sqrt(n) if n else float("nan")
134
+ t_value = mean / se if se else (float("inf") if mean else 0.0)
135
+ p_value = 2.0 * (1.0 - _t_cdf(abs(t_value), n - 1)) if n > 1 else float("nan")
136
+ margin = _t_critical(n - 1) * se if n > 1 else float("nan")
137
+ return {
138
+ "n": n,
139
+ "mean_delta": mean,
140
+ "sd_delta": sd,
141
+ "paired_t": t_value,
142
+ "p_two_sided": p_value,
143
+ "ci95": [mean - margin, mean + margin],
144
+ "cohens_dz": mean / sd if sd else float("nan"),
145
+ }
146
+
147
+
148
+ def _training_diagnostics(pair, step_start, step_end):
149
+ result = {}
150
+ for label in ("beta0_train", "beta_train"):
151
+ path = pair.get(label)
152
+ if not path:
153
+ continue
154
+ rows = _read_window(path, step_start, step_end, ("task_loss", "kl_mean", "kl_max"))
155
+ result[label] = rows
156
+ if "beta_train" in result:
157
+ kl_mean = result["beta_train"].get("kl_mean")
158
+ result["kl_collapse_flag"] = kl_mean is not None and abs(kl_mean) < 1e-5
159
+ if "beta0_train" in result and "beta_train" in result:
160
+ a = result["beta0_train"].get("task_loss")
161
+ b = result["beta_train"].get("task_loss")
162
+ result["task_loss_delta_beta_minus_zero"] = (
163
+ b - a if a is not None and b is not None else None
164
+ )
165
+ result["relative_task_loss_increase"] = (
166
+ (b - a) / max(abs(a), 1e-12) if a is not None and b is not None else None
167
+ )
168
+ return result
169
+
170
+
171
+ def build_report(manifest, step_start, step_end):
172
+ if "comparisons" in manifest:
173
+ reports = []
174
+ for comparison in manifest["comparisons"]:
175
+ submanifest = {
176
+ "comparison": comparison.get("label", "unlabeled comparison"),
177
+ "pairs": comparison["pairs"],
178
+ }
179
+ reports.append(
180
+ {
181
+ "task_family": comparison.get("task_family"),
182
+ "architecture": comparison.get("architecture"),
183
+ **build_report(submanifest, step_start, step_end),
184
+ }
185
+ )
186
+ directions = [
187
+ math.copysign(1, item["aggregate"]["ogs"]["mean_delta"])
188
+ for item in reports
189
+ if "ogs" in item.get("aggregate", {}) and item["aggregate"]["ogs"]["mean_delta"] != 0
190
+ ]
191
+ return {
192
+ "preregistered_step_window": [step_start, step_end],
193
+ "comparisons": reports,
194
+ "two_by_two_consistency": {
195
+ "ogs_effect_direction_consistent": len(directions) == len(reports)
196
+ and len(set(directions)) <= 1,
197
+ "criterion": "KL OGS effect sign should agree across the compared architectures and task families.",
198
+ },
199
+ }
200
+ pairs = manifest["pairs"]
201
+ if not pairs:
202
+ raise ValueError("manifest needs at least one matched seed pair")
203
+ columns = list(METRICS)
204
+ rows, diagnostics = [], []
205
+ for pair in pairs:
206
+ if (
207
+ pair.get("beta0_architecture") is not None
208
+ and pair.get("beta_architecture") is not None
209
+ and pair["beta0_architecture"] != pair["beta_architecture"]
210
+ ):
211
+ raise ValueError(f"seed {pair['seed']}: beta pair uses different architectures")
212
+ if (
213
+ pair.get("beta0_step_budget") is not None
214
+ and pair.get("beta_step_budget") is not None
215
+ and pair["beta0_step_budget"] != pair["beta_step_budget"]
216
+ ):
217
+ raise ValueError(f"seed {pair['seed']}: beta pair uses different step budgets")
218
+ anchor = _read_window(pair["beta0_ogs"], step_start, step_end, columns)
219
+ treatment = _read_window(pair["beta_ogs"], step_start, step_end, columns)
220
+ row = {"seed": pair["seed"]}
221
+ for metric in columns:
222
+ if metric in anchor and metric in treatment:
223
+ row[metric] = treatment[metric] - anchor[metric]
224
+ rows.append(row)
225
+ diagnostics.append(_training_diagnostics(pair, step_start, step_end))
226
+ stats = {
227
+ metric: _paired_report([r[metric] for r in rows if metric in r])
228
+ for metric in columns
229
+ if any(metric in r for r in rows)
230
+ }
231
+ anchor_ogs = [
232
+ _read_window(pair["beta0_ogs"], step_start, step_end, ("ogs",))["ogs"] for pair in pairs
233
+ ]
234
+ delta_ogs = [r.get("ogs", float("nan")) for r in rows]
235
+ mean_anchor = _mean(anchor_ogs)
236
+ regression_r = _pearson([v - mean_anchor for v in anchor_ogs], delta_ogs)
237
+ return {
238
+ "comparison": manifest.get("comparison", "beta effect"),
239
+ "preregistered_step_window": [step_start, step_end],
240
+ "pairing": "within-seed beta-minus-zero; same architecture and step window",
241
+ "n_seeds": len(pairs),
242
+ "minimum_n_8_met": len(pairs) >= 8,
243
+ "per_seed_deltas": rows,
244
+ "aggregate": stats,
245
+ "regression_to_mean": {
246
+ "corr_anchor_ogs_offset_vs_beta_delta": regression_r,
247
+ "possible_variance_dampening": math.isfinite(regression_r) and regression_r <= -0.5,
248
+ },
249
+ "training_diagnostics": diagnostics,
250
+ "no_collapse_and_no_cost_redistribution": {
251
+ "all_beta_runs_noncollapsed": all(
252
+ not d.get("kl_collapse_flag", False) for d in diagnostics
253
+ ),
254
+ "task_loss_deltas": [d.get("task_loss_delta_beta_minus_zero") for d in diagnostics],
255
+ "relative_task_loss_increases": [
256
+ d.get("relative_task_loss_increase") for d in diagnostics
257
+ ],
258
+ "possible_cost_redistribution": any(
259
+ d.get("relative_task_loss_increase") is not None
260
+ and d["relative_task_loss_increase"] >= 0.05
261
+ for d in diagnostics
262
+ ),
263
+ "interpretation": "Inspect task_loss and KL together; this report flags near-zero mean KL but does not infer causality.",
264
+ },
265
+ }
266
+
267
+
268
+ def main(argv=None):
269
+ parser = argparse.ArgumentParser(description=__doc__)
270
+ parser.add_argument("manifest", type=Path)
271
+ parser.add_argument(
272
+ "--step-start", type=int, required=True, help="inclusive preregistered lower step bound"
273
+ )
274
+ parser.add_argument(
275
+ "--step-end", type=int, required=True, help="inclusive preregistered upper step bound"
276
+ )
277
+ parser.add_argument("--output", type=Path, default=None)
278
+ args = parser.parse_args(argv)
279
+ if args.step_end < args.step_start:
280
+ parser.error("--step-end must be >= --step-start")
281
+ with args.manifest.open(encoding="utf-8") as f:
282
+ report = build_report(json.load(f), args.step_start, args.step_end)
283
+ rendered = json.dumps(report, indent=2, allow_nan=True)
284
+ if args.output:
285
+ args.output.write_text(rendered + "\n", encoding="utf-8")
286
+ print(rendered)
287
+ return 0
288
+
289
+
290
+ if __name__ == "__main__":
291
+ raise SystemExit(main())
@@ -67,6 +67,13 @@ SPLIT_GRAPH_COMBINER_MODE = "linear" # "linear" (default) | "controller"
67
67
  SPLIT_GRAPH_COMBINER_VARIANT = "mamba1"
68
68
  SPLIT_GRAPH_COMBINER_NUM_BLOCKS = 1
69
69
 
70
+ # DNC memory mechanism variants (only applied by the split-graph assembly).
71
+ DNC_READ_VARIANT = "cosine" # "cosine" | "relational-mlp" | "relational-residual"
72
+ DNC_READ_RESIDUAL_SCALE = 1.0 # Gain applied before tanh for relational-residual.
73
+ DNC_READ_RESIDUAL_MAX_RATIO = 0.5 # Maximum residual magnitude relative to cosine RMS.
74
+ DNC_WRITE_VARIANT = "learned" # "learned" | "kanerva-closed-form"
75
+ DNC_WRITE_OBSERVATION_VARIANCE = 1.0 # fixed isotropic likelihood variance
76
+
70
77
  # ---- Option 1: link-matrix ablation/sparsification at fixed N -----------------
71
78
  LINK_MATRIX_MODE = "dense" # "dense" | "ablated" | "sparse_topk"
72
79
  LINK_MATRIX_TOPK: int | None = None # int, required only for "sparse_topk"