Skip to main content

Machine learning with a rate-based specialization of the Neural Engineering Framework (NEF) in PyTorch.

Project description

leenef

Machine learning with a rate-based specialization of the Neural Engineering Framework (NEF) in PyTorch.

Overview

leenef keeps the NEF encoder/decoder split but uses rate neurons and an analytic decoder solve for machine learning:

a = G(g ⊙ (E x) + b)
D = (AᵀA + α_eff I)⁻¹ AᵀY
y = Dᵀa

The practical consequence is that the expensive part of training is not backpropagation through all weights, but accumulation of the sufficient statistics AᵀA and AᵀY. The same primitive supports:

  • single-layer supervised learning with NEFLayer
  • ensembles with NEFEnsemble
  • online / continuous updates via partial_fit, solve_accumulated, and Woodbury-style inverse updates
  • temporal classification with StreamingNEFClassifier
  • multi-layer and recurrent variants for controlled comparisons
  • reinforcement-learning agents built on the same analytic solve

The current supervised-learning, continual-learning, and reinforcement-learning papers are docs/SSUP-I.md, docs/SSUP-II.md, and docs/SSUP-III.md. They are the authoritative source for the repository's present claims, numbers, and caveats.

Paper I abstract:

NEF's regularized least-squares solve over fixed-encoder neural activities — $D = (A^\top A + \alpha_{\mathrm{eff}} I)^{-1} A^\top Y$ — is a compact sufficient-statistics primitive for supervised learning. In a rate-based specialization we call leenef, fixed encoders produce frame-coefficient-like activities and only the decoder is fit. This primitive supports fast static classifiers, ensembles, online Woodbury updates, GPU-friendly accumulate-and-solve, and a streaming temporal classifier. Under multi-seed, code-identity-tagged evaluation, Stream-NEF reaches 98.45 ± 0.02 % on row sMNIST: 0.6 pp below a tuned near-best LSTM while using 2.4× less wall-clock time, and ~5 pp above the completed ESN row panel. Static image classifiers are fast but feature-limited: generic encoders trail tuned MLPs by 1–4 pp, receptive-field encoders reverse the CIFAR-10 MLP gap, and a gradient-free ConvNEF front end reaches 65.89 ± 0.12 % on CIFAR-10. The limits are equally clear: spatial priors matter, purely analytic depth does not buy accuracy on its own, and mean-pooled delay-line features lose long-range order information.

Paper II abstract:

NEF's regularized least-squares solve over fixed-encoder neural activities — $D = (A^\top A + \alpha_{\mathrm{eff}} I)^{-1} A^\top Y$ — is a compact sufficient-statistics primitive for continual learning. Because $A^\top A$ and $A^\top Y$ add over data partitions, sequential partial_fit over a task stream produces the same decoder as joint training over the union of tasks: the forgetting axis has length zero by construction relative to that joint fixed-feature model. Across Split-MNIST, Permuted-MNIST, Split-CIFAR-10, and Split-CIFAR-100, nef_accumulate matches nef_joint to 0.000000 pp over 10 seeds. This removes forgetting from the analytic readout and collapses the class-incremental failure modes of the tested EWC/finetune baselines (Split-MNIST: 97.0 % vs ~20.0 %), while remaining above ER at 86.5 % and exposing the tradeoff directly: the linear head no longer forgets, but absolute accuracy is bounded by the fixed feature map. Capacity scales smoothly with neuron budget per task, a gradient-free ConvNEF front end lifts Split-CIFAR-10 from 49.5 % to 74.7 $\pm$ 0.1 % without breaking the identity, and a streaming-continual panel carries the same exact/joint/Woodbury agreement through 10-task permuted sMNIST while revealing a lower mean-pooled-delay-line ceiling of 58.3 $\pm$ 0.2 % at 16000 neurons.

Paper III abstract:

NEF's regularized least-squares solve over fixed-encoder neural activities, $D = (A^\top A + \alpha_{\mathrm{eff}} I)^{-1} A^\top Y$, can be used as a compact sufficient-statistics primitive for reinforcement learning when the target matrix $Y$ is constructed to match the control problem. In dense control, a non-bootstrapped $100$-step NEF action-value regression (NEF-AVR) configuration reaches $201.3 \pm 9.8$ robust return on LunarLander-v3 over 10 seeds, crossing the informal 200-return reference line under the evaluation protocol used here; the same analytic control path reaches near-perfect CartPole-v1 best evaluation (best_eval $=499.4 \pm 0.6$). A baseline DQN implementation evaluated under the exact same protocol reaches $129.3 \pm 21.7$ on LunarLander-v3. In sparse control, target construction is the result: a full-successor random-direction mechanism breaks the flat MountainCar-v0 floor but does not solve the environment, reaching $-158.8 \pm 1.4$ at 2000 neurons, and a 6000-neuron directional known-goal readout gives a stable Acrobot-v1 signal ($-194.9 \pm 10.4$ robust, $-132.1 \pm 6.1$ best) when successor statistics are retained slowly enough. The boundary rows explain the conditions rather than replacing the headline: one-step bootstrapped TD collapses on LunarLander-v3 ($-123.8 \pm 13.1$), the cheaper directional MountainCar readout stays flat ($-197.0 \pm 1.7$), and widening the full MountainCar successor model to 6000 neurons costs $5.7\times$ more without improving robust return. The paper's claim is therefore not that analytic fixed-feature RL is a universal control algorithm. It is that the same sufficient-statistics object can support successful control when $Y$ is stable, informative, and matched to the task.

Quick start

from leenef.layers import NEFLayer
from leenef.ensemble import NEFEnsemble
from leenef.streaming import StreamingNEFClassifier

# Single layer: fixed encoders, analytic decoder solve
layer = NEFLayer(d_in=784, n_neurons=5000, d_out=10, centers=x_train)
layer.fit(x_train, y_train)
predictions = layer(x_test)

# Incremental / online accumulation
online = NEFLayer(d_in=784, n_neurons=5000, d_out=10, centers=x_train)
for batch_x, batch_y in data_stream:
    online.partial_fit(batch_x, batch_y)
online.solve_accumulated(alpha=1e-3)

# Ensemble of independent feature banks
ens = NEFEnsemble(
    d_in=784,
    n_neurons=3000,
    d_out=10,
    n_members=10,
    encoder_strategy="receptive_field",
    encoder_kwargs={"image_shape": (28, 28)},
    centers=x_train,
)
ens.fit(x_train, y_train)

# Streaming classifier on sequence data
stream = StreamingNEFClassifier(
    d_timestep=1,
    n_neurons=8000,
    d_out=10,
    window_size=10,
    centers=x_train_seq,
)
stream.fit(x_train_seq, y_train)

Setup

Requires Python 3.12+.

From PyPI or a built wheel:

pip install leenef

For development from a checkout:

python3 -m venv venv
source venv/bin/activate
pip install -e '.[dev]'

See docs/usage.md for the usage manual.

Agent skill

The leenef Agent Skill lives in skills/leenef/ with its asset manifest. From a clone, install it as symlinks so edits stay live:

python skills/leenef/install_skill.py --dest ~/.config/agent/skills --link

After pip install leenef, the same installed package provides:

leenef-install-skill --dest ~/.config/agent/skills

Tests

source venv/bin/activate
pytest
pytest -k test_fit_identity -q
ruff check src/leenef/ tests/ benchmarks/
ruff format --check src/leenef/ tests/ benchmarks/

Benchmarks and paper artifacts

The active supervised-learning harness is the sl_clean stack used for Paper I. Example launches:

source venv/bin/activate

PYTHON=$PWD/venv/bin/python SEEDS=0-9 \
    bash benchmarks/sl_clean/sl_hp_driver.sh biases_mnist
PYTHON=$PWD/venv/bin/python SEEDS=0-9 \
    bash benchmarks/sl_clean/sl_hp_driver.sh biases_fashion
PYTHON=$PWD/venv/bin/python SEEDS=0-9 \
    bash benchmarks/sl_clean/sl_hp_driver.sh biases_cifar10

# Follow-up bias-placement panels
PYTHON=$PWD/venv/bin/python SEEDS=0-9 \
    bash benchmarks/sl_clean/sl_hp_driver.sh biases_cifar10_centered
PYTHON=$PWD/venv/bin/python SEEDS=0-9 \
    bash benchmarks/sl_clean/sl_hp_driver.sh biases_mnist_decentered

# Regenerate the Paper-I figures
python3 docs/generate_paper_i_figures.py

# Regenerate the Paper-III figures
python3 docs/generate_paper_iii_figures.py

# Build Paper I / Paper II / Paper III PDFs
bash docs/build_ssup_pdf.sh docs/SSUP-I.md docs/SSUP-I.pdf
bash docs/build_ssup_pdf.sh docs/SSUP-II.md docs/SSUP-II.pdf
bash docs/build_ssup_pdf.sh docs/SSUP-III.md docs/SSUP-III.pdf

All paper-grade result rows carry a code identity, dataset hashes, full config dictionaries, per-seed metrics, and aggregate summaries. The preserved JSON/log artifacts used by Papers I, II, and III live under results/sl_clean/, results/cl_clean/, results/rl_paper/, and results/rl_sparse/.

Components

Path Purpose
src/leenef/layers.py NEFLayer: encode -> activate -> decode; batch, accumulated, and continuous analytic solves
src/leenef/ensemble.py NEFEnsemble: independent NEF layers combined by averaging or voting
src/leenef/networks.py NEFNetwork: multi-layer comparison model with greedy, hybrid, target-prop, end-to-end, hybrid->E2E, and target-prop->E2E training
src/leenef/recurrent.py RecurrentNEFLayer: recurrent decode-then-re-encode sequence model
src/leenef/streaming.py StreamingNEFClassifier: delay-line temporal classifier with batch, Woodbury, and accumulate+solve training
src/leenef/conv.py ConvNEFStage, ConvNEFPipeline, ConvNEFEnsemble: gradient-free convolutional front ends and ensembles
src/leenef/rl.py NEFFeatures, NEFAVRAgent, NEFAVREnsemble: RL agents and ensembles built on analytic value solves
src/leenef/encoders.py Encoder strategies: hypersphere, gaussian, sparse, receptive_field, whitened, class_contrast, local_pca
src/leenef/activations.py Activations: abs, relu, softplus, lif_rate
src/leenef/solvers.py Decoder solvers and normal-equation utilities
benchmarks/sl_clean/ Active reproducible supervised-learning sweep harness for Paper I
benchmarks/cl_clean/ Active reproducible continual-learning sweep harness for Paper II
results/sl_clean/ Preserved multi-seed result rows, summaries, and logs used by Paper I
results/cl_clean/ Preserved multi-seed result rows, summaries, and logs used by Paper II
attic/ Archived pre-restart infrastructure, reports, and notes kept for historical reference

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

leenef-0.1.1.tar.gz (2.6 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

leenef-0.1.1-py3-none-any.whl (3.0 MB view details)

Uploaded Python 3

File details

Details for the file leenef-0.1.1.tar.gz.

File metadata

  • Download URL: leenef-0.1.1.tar.gz
  • Upload date:
  • Size: 2.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for leenef-0.1.1.tar.gz
Algorithm Hash digest
SHA256 54a27cd331704758df9d37ce67ce49ad1a5b60cb4075a9b257279180f14e3c26
MD5 78eca14837a9fb51844a21840a79e041
BLAKE2b-256 ee652ec49cd714889e43f7dbae20aaddddc6fada547945b4e41bfc4255c93cb4

See more details on using hashes here.

Provenance

The following attestation bundles were made for leenef-0.1.1.tar.gz:

Publisher: publish-pypi.yml on nikeke/leenef

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file leenef-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: leenef-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 3.0 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for leenef-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f08a1ee05d6404065ce31863cd5d5531ec3b2450eb879839505f8446ba6918f4
MD5 bac114fbdaae5511adaf60afe66cae22
BLAKE2b-256 7bc3bae98d516582d0965296b72a36c34f2d68ec92e11b15b85c9dd9aa67b0f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for leenef-0.1.1-py3-none-any.whl:

Publisher: publish-pypi.yml on nikeke/leenef

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page