necro-neuron
The Elbàlor Neuron — complex metabolic activation for lifelong learning with phase-space conservation, orthogonal weight freezing, Complex-STDP memory, and Pearl rungs 1–3 causality.
Continual learning with near-zero forgetting and no replay, no EWC, no external regularizers. True inference-time continual learning: the base skeleton stays frozen, the memory layer keeps learning.
Heat does not kill the signal. It redirects it.
Install
pip install necro-neuron
Results
| Benchmark | Forgetting | Final Accuracy |
|---|---|---|
| Cross-dataset MLP (no STDP) | 0.0002 | 0.5183 |
| Cross-dataset CNN | 0.0128 | 0.5868 |
| Cross-dataset MLP + STDP (live) | <0.02 | tracking |
Beats Dense, EWC, SI, and SiLU CNN in both metrics.
Quick start
import torch
import torch.nn.functional as F
from necro import ArchD_MLP, project_gradients_orthogonal
model = ArchD_MLP(input_dim=784, hidden_dims=(256, 256),
output_dim=10, num_tasks=5)
# Per-task optimizer (mandatory — see paper §5.1)
optimizer = torch.optim.SGD(
model.get_task_parameters(task_idx=0),
lr=1e-2, momentum=0.9,
)
x = torch.randn(32, 784)
y = torch.randint(0, 10, (32,))
logits = model(x, task_idx=0)
loss = F.cross_entropy(logits, y)
loss.backward()
# Orthogonal projection (mandatory — see paper §5.3)
project_gradients_orthogonal(model)
optimizer.step()
model.apply_therma_updates()
The three plumbing mechanisms
The neuron alone is not sufficient. Three mechanisms are structurally required:
- Per-task optimizer —
model.get_task_parameters(t)excludes prior tasks' heads entirely. Without this, Task 0 collapses to 0.00%. - Thermal snapshot/restore —
model.snapshot()/model.restore()around eval. Without this, measuring a task rewrites the state its head was trained against. - Orthogonal gradient projection —
project_gradients_orthogonal(model)after backward. Without this, blocked gradients leak back into the weight.
Remove any one and the mechanism fails.
Optimizer
SGD with momentum. Not AdamW. AdamW's variance rescaling destroys the metabolic gradient conservation. See paper §3.5.3.
Causality — Pearl rungs 1, 2, 3
The neuron performs its own interventions. Three complex memory matrices, written from three different activations in every training forward pass:
| Rung | Memory | Question |
|---|---|---|
| 1 | C_obs |
P(j | i) — observational association |
| 2 | C_do |
P(j | do(i)) — interventional effect |
| — | C_struct |
cross-domain invariant edges |
The intervention is performed, not inferred. _intervene_input forces a random subset of input features to a fixed value, runs a second forward, and writes C_do from the intervened activation. The two matrices accumulate different statistics. A control test proves the difference disappears when do_self_intervention=False.
Rung 3 (counterfactual) is exposed via counterfactual_query, which runs Pearl's three-step abduction → action → prediction procedure against the observed context.
An explicit graph is available via build_graph, giving you parents(), children(), do_surgery(), adjacency_matrix(), and top_edges() over the memory.
Inference-time continual learning
Set inference_learning=True. The base weights stay frozen, but the memory layer keeps writing during model.eval():
C_obs,C_do,phase_mem,thermal_magall continue to update- No optimizer, no backward pass, no task labels
- Autonomy gates regulate learning turn-by-turn
Boring-Shit Filter. If activity drops below boredom_threshold (default 0.25), psi = 0 — nothing worth learning this turn.
Brain-Rot Shield. If thermal_mag.max() exceeds overheat_threshold (default 0.95), psi goes negative — anti-Hebbian, actively eroding C to reject noise.
Otherwise psi stays at its trained value and memory grows.
Task bias modes
| Mode | Behavior |
|---|---|
"fixed" |
One bias vector per task. Requires num_tasks. Original behavior. |
"none" |
No task bias. Shared bias only. |
"emergent" |
Single shared bias. Task partitioning emerges from the thermal state — no task index at inference. |
emergent is what enables open-ended continual learning. Call model(x) with no task identity; the layer figures out the subspace from the input itself.
Architectures
| Class | Description |
|---|---|
NecroComplexActivation |
Complex metabolic activation with Wirtinger backward |
NecroComplexLinear |
Base complex linear with thermal state |
PhaseReserveLinear |
Architecture A — local phase reserve |
PhaseMemoryLinear |
Architecture B — global phase memory matrix |
PerNeuronSTDPLinear |
Architecture C — timing-based STDP (v3) |
ArchD_STDP_Linear |
Architecture D — anti-rupture, Complex-STDP, Pearl rungs 1–3 |
ArchD_Conv2d |
Architecture D — spatial (per-channel-per-position) version |
ArchD_MLP |
Full MLP wrapper with per-task heads |
CausalGraph |
Explicit DAG over C_obs / C_do |
Inference-time API
model = ArchD_MLP(
input_dim=784, hidden_dims=(256, 256),
output_dim=10,
num_tasks=None,
task_bias_mode="emergent",
inference_learning=True,
)
model.eval()
for x in user_stream:
out = model(x) # no task_idx needed
model.apply_therma_updates() # memory writes continue
# Counterfactual query (rung 3)
cf = model.fc1.counterfactual_query(
a_observed, y_observed,
intervention_idx=[0, 1],
intervention_value=0.0,
)
# Explicit causal graph
graphs = model.build_graph(threshold=1e-3)
print(graphs["fc1"].summary())
Tests
python -m pytest
96 tests across seven files verify every mechanism in the paper: Wirtinger backward correctness, permeability mask behavior, thermal freeze, graduated defense, LTP/LTD phase interference, observational vs interventional memory separation, rung-3 counterfactual, explicit graph operations, inference-time continual learning, and the three plumbing mechanisms.
Citation
@misc{yaka2026elbalor,
title = {The Elbàlor Neuron: A Metabolic Complex Activation for
Lifelong Learning with Phase-Space Conservation,
Orthogonal Weight Freezing, and Complex-STDP Memory},
author = {Yaka, Eric and {Elbàlor, The Digital Necromancer}},
year = {2026},
doi = {10.5281/zenodo.TBD},
url = {https://github.com/elbalor/necro-neuron}
}
License
MIT.
Metadata
Release files for elbalor-neuron 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| elbalor_neuron-0.1.0.tar.gz | 235.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| elbalor_neuron-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 258.9 kB
Release files / elbalor_neuron-0.1.0.tar.gz
| Download URL | elbalor_neuron-0.1.0.tar.gz |
|---|---|
| Size | 235.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a1e44ba0c5346fd1c32d33938e8a76e60801ce88a33110fab1c797b3c1493494
|
|
BLAKE2b-256 checksum How to use checksums |
3e0daeaf9a09bd43ffcca57eadd494d39840fc10114cc8b2727ee37cf0d9a7aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.4
|
Release files / elbalor_neuron-0.1.0-py3-none-any.whl
| Download URL | elbalor_neuron-0.1.0-py3-none-any.whl |
|---|---|
| Size | 23.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
93d977968eafa43d0be5790c8bfad1a4d7b1ade85114ae948bcca2daa5ec739a
|
|
BLAKE2b-256 checksum How to use checksums |
171e20bc55124dcfc0e235264418c4c8c3afed59cae580f7d9e2d38a72b92bee
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.4
|