STANNO — Neural Networks That Train Neural Networks
A modern, open-source Python library implementing the Artificial Neurogenesis Network concept from US Patent 5,852,815 (Thaler, 1998). One network (the trainer) decides how another network (the trainee) should update its weights — no backpropagation needed. Multiple STANNOs can be chained into cascade pipelines, and any trained STANNO can be turned into a data scanner that finds matching rows in large datasets.
Attribution: This is a faithful, open-source implementation of Thaler's patented design with modern extensions (cascading, data scanning, ComfyUI integration). The original patent has expired. All core concepts are credited to the original patent.
⚠️ What STANNO Is (and Isn't)
STANNO is specialized, not a drop-in replacement for PyTorch.
Good for:
- Anomaly detection (reconstruction-based scoring)
- Online/continual learning (one-sample-at-a-time updates)
- Interpretable weight modification (see exactly what changes)
- Multi-stage cascade pipelines (encoder → bottleneck → decoder, end-to-end)
- Semantic data scanning (find rows in a large dataset that match learned distribution)
- ComfyUI creative workflows (style transfer via dream mode)
NOT for:
- General regression (accuracy ~0.4, use PyTorch instead)
- Image generation alone (need Stable Diffusion + nodes)
- High-throughput training (slow NumPy)
For details, see STANNO_IS_NOT.md.
What you can do with this:
Train networks on your data:
from stanno import STANNO
from stanno.config.schema import STANNOConfig
import numpy as np
config = STANNOConfig(layers=[784, 256, 10])
stanno = STANNO(config)
stanno.fit(x_train, y_train, epochs=100)
predictions = stanno.predict(x_test)
Chain into cascade pipelines:
from stanno import STANNO, STANNOConfig, CascadeSTANNO
# Encoder-decoder autoencoder
enc = STANNO(STANNOConfig(layers=[768, 256, 64], learning_rate=0.05))
dec = STANNO(STANNOConfig(layers=[64, 256, 768], learning_rate=0.05))
ae = CascadeSTANNO([enc, dec])
ae.fit(embeddings, embeddings, epochs=200) # end-to-end gradient cascade
# Extract compressed representations
codes = ae.intermediate_output(embeddings, stage=0) # (N, 64)
# Freeze the encoder, continue adapting the decoder
ae.freeze(0)
ae.fit(new_domain_embeddings, new_domain_embeddings, epochs=100)
Scan large datasets for matching rows (DSANNO):
from stanno import STANNO, STANNOConfig, DSANNO
# Train on known-good data
detector = STANNO(STANNOConfig(layers=[64, 128, 64], learning_rate=0.05))
detector.fit(normal_data, normal_data, epochs=200)
scanner = DSANNO(detector, mode="reconstruction")
# Auto-calibrate threshold from training distribution
threshold = scanner.calibrate_threshold(normal_data, percentile=95)
# Find matching rows in a large corpus
result = scanner.scan(large_corpus, threshold=threshold)
matching = large_corpus[result.matched_indices()]
# Or retrieve the top-k best matches
indices, scores, _ = scanner.top_k(large_corpus, k=20)
# Stream huge files without loading all at once
for batch_result in scanner.scan_stream(file_batches, threshold=threshold):
process(batch_result.matched_indices())
Detect when inputs are unusual (anomaly filter):
from stanno.integration.filter import STANNOFilter
# Train on normal data
stanno.fit(normal_data, normal_data, epochs=50)
# Score new input
score, metadata = stanno_filter.score(new_input)
# score ranges [0, 1]: low = normal, high = anomaly
Generate variations via "dream mode":
# Start with a seed input, add noise, generate a sequence
dream_sequence = stanno.dream(
num_steps=64,
input_seed=seed_vector,
noise_sigma=0.1 # controls creativity
)
Use in ComfyUI workflows (9 nodes):
- Load/create STANNO models
- Train on image batches
- Score/filter images
- Inject dream creativity into CLIP conditioning
- Apply dream output as LoRA-style patches
- Route images by style match
- Scan image batches for best matches with auto-calibrated thresholds
- Build multi-stage cascade autoencoders
Why use STANNO?
- Interpretable: You can see exactly what the trainer does to weights. No black-box backprop.
- Flexible: Three trainer types (Fixed, LocalRule, Evolutionary) fit different problems.
- Learnable: The trainer itself can adapt (meta-learning).
- Cascadable: Chain STANNOs into multi-stage pipelines with end-to-end gradient flow across stages.
- Scannable: Turn any trained STANNO into a semantic scanner over large datasets.
- No autodiff: Works with NumPy. No GPU required (but supports PyTorch if you have it).
- ComfyUI ready: Nine custom nodes for image generation workflows.
Install
pip install git+https://github.com/nitroxido/stanno.git
Quick examples
Regression on sin(x)
python -m stanno train --config examples/sin_regression.json
python -m stanno predict --config examples/sin_regression.json --input 0.5
python -m stanno dream --config examples/sin_regression.json
Autoencoder on images
from stanno import STANNO
from stanno.config.schema import STANNOConfig
import numpy as np
# Reshape images to flat vectors (B, H*W*C)
x = images.reshape(images.shape[0], -1).astype('float32')
# Autoencoder: input and output have same size
config = STANNOConfig(layers=[x.shape[1], 256, x.shape[1]])
stanno = STANNO(config)
stanno.fit(x, x, epochs=100, batch_size=32)
# Get reconstruction
x_reconstructed = stanno.predict(x[:10])
Online learning (continual)
from stanno.integration.continual import ContinualSTANNO
cont = ContinualSTANNO(stanno)
for sample, label in data_stream:
loss = cont.observe(sample, label)
if cont.steps % 100 == 0:
test_loss = cont.test_loss(x_test, y_test)
print(f"Step {cont.steps}: train_loss={loss:.4f}, test_loss={test_loss:.4f}")
Anomaly scoring
from stanno.config.schema import FilterConfig
from stanno.integration.filter import STANNOFilter
# Train on normal embeddings
stanno.fit(normal_embeddings, normal_embeddings, epochs=50)
# Create filter
filt = STANNOFilter(stanno, FilterConfig(anomaly_threshold=0.7))
# Score new embedding
score, info = filt.score(new_embedding)
print(f"Anomaly score: {score:.3f} (0=normal, 1=anomaly)")
if info["blocked"]:
print("Blocked: input is too unusual")
How it works
The core idea:
- TraineeNet: A neural network with weights you want to train.
- TrainerNet: Another network that looks at the TraineeNet's internal state (activations, errors, weights) and computes how to update those weights.
- No backprop: The update formula is explicit, not learned via autodiff.
- Cascades: Multiple TraineeNet+TrainerNet pairs can be chained so that gradient signals flow backward across stage boundaries, enabling end-to-end training of multi-stage pipelines.
- Scanning: Any trained STANNO can be used as a similarity function to scan and rank rows in large datasets by how closely they match the learned distribution.
The three trainer types:
| Type | Mechanism | Best for |
|---|---|---|
| Fixed | 4-module design (patent 5852815A), cascade-aware | Baseline, reproducibility, understanding the concept |
| LocalRule | Shared MLP per synapse | Adaptive training, interpretability |
| Evolutionary | Evolve per-layer scales (ES) | Unconventional problems, when autodiff fails |
Technical details
- Backend agnostic: Uses NumPy by default, but can swap in PyTorch.
- Variable architecture: Networks can be any depth (list of layer sizes).
- Configurable feedback: Dream mode can "repeat" outputs, use a learned "linear" projection, or "zero" them.
- Pickle-serializable: Save/load trained models easily.
Benchmark
On sin(x) regression (512 samples, 100 epochs):
Fixed MSE=0.047
LocalRule MSE=0.021 (learnable rules = better fit)
Evolutionary MSE=0.053
For ComfyUI users
The comfyui-stanno custom node package provides nine nodes in the STANNO category:
| Node | What it does |
|---|---|
| STANNOLoad | Create or load a model (JSON config or .pkl file) |
| STANNOTrainImages | Train on image batches |
| STANNOScoreImages | Filter images by reconstruction error |
| STANNODreamCond | Modify CLIP embeddings with dream mode |
| STANNODynamicLoRA | Apply learned style as LoRA patches |
| STANNOCompositeCheck | Route images to whichever of two STANNOs matches best |
| STANNOScan | DSANNO scanner: auto-calibrated threshold + top-k image retrieval |
| STANNOCascadeLoad | Create or load a multi-stage CascadeSTANNO |
| STANNOCascadeTrainImages | Train a cascade end-to-end on an image batch |
Install via ComfyUI-Manager or manually.
Patent & Attribution
STANNO is an open-source implementation of US Patent 5,852,815 (Artificial Neurogenesis Network), filed by Stephen L. Thaler. The patent has expired (US utility patents: 20 years from filing). We fully acknowledge and credit all core architectural concepts to the original patent.
This implementation adds:
- Modern Python/NumPy/PyTorch backend
- CascadeSTANNO (multi-stage gradient cascade)
- DSANNO (data scanning and semantic search)
- Three trainer types (Fixed, LocalRule, Evolutionary)
- ComfyUI integration (9 custom nodes)
- CLI tools for common tasks
See Citation below for how to cite the original patent and this implementation.
Citation
If you use STANNO in research, cite the original patent:
@patent{thaler1998artificial,
title={Artificial neurogenesis network},
author={Thaler, Stephen L},
year={1998},
number={5852815},
institution={United States Patent}
}
And mention this implementation:
@software{stanno2026,
title={STANNO: Self-Training Artificial Neural Network Object},
author={Raides J. Rodríguez},
year={2026},
url={https://github.com/nitroxido/stanno}
}
Questions?
- Bug report: Open an issue on GitHub
- Question: Start a discussion
- Feature request: Describe what you want to build
License
MIT
Core Package
This integration requires the stanno core package.
Install with:
pip install git+https://github.com/nitroxido/stanno.git
``` {data-source-line="259"}