spdal
Single-Pass Discard-After-Learn — hyperellipsoid classifiers for online streaming data.
Each training sample is processed once and then discarded. No full dataset is ever stored. All classifiers implement scikit-learn's partial_fit / predict interface.
Installation
pip install spdal
Development mode:
git clone https://github.com/PeemapatW/single-pass-discard-after-learn
cd single-pass-discard-after-learn
pip install -e ".[dev]"
Quick Start
from sklearn.datasets import make_classification
from spdal import LRHE
X, y = make_classification(n_samples=500, random_state=42)
clf = LRHE()
clf.fit(X[:400], y[:400])
print(clf.predict(X[400:])) # array of class labels
print(len(clf.neuron_list)) # number of learned prototypes
Incremental learning
from spdal import TRACED
import numpy as np
X, y = make_classification(n_samples=500, random_state=42)
classes = np.unique(y)
clf = TRACED()
for i in range(0, 400, 50):
clf.partial_fit(X[i:i+50], y[i:i+50], classes=classes)
print(clf.predict(X[400:]))
Classifiers
| Class | Full name | Year |
|---|---|---|
VEBF |
Versatile Elliptic Basis Function | 2010 |
SCIL |
Streaming Chunk Incremental Learning | 2019 |
LRHE |
Learning with Recoil in Hyperellipsoidal Structure | 2020 |
SHEF |
Scalable Hyper-Ellipsoidal Function | 2020 |
D4 |
Diversion of Data Distribution Direction | 2026 |
TRACED |
Trend-Adaptive Classification with Ellipsoidal Disambiguation | 2026 |
Comparison
| Feature | VEBF | SCIL | LRHE | SHEF | D4 | TRACED |
|---|---|---|---|---|---|---|
| Learning mode | Single | Chunk | Single | Single | Chunk | Chunk |
| Neurons per class | Multiple | Multiple | Multiple | Multiple | One | Multiple |
| Width formula | Init: avg pairwise dist; Update: width + center shift; Merge: sqrt(2π|λ|) | Update: width + center shift; Expand: sqrt(1+η·max_psi)·w; Merge: 1.96 sqrt(|λ|/n) | Init: avg pairwise dist; Update: width + center shift; Merge: sqrt(2π|λ|) | Update: recursive covariance; Width = r·sqrt(λ) | Init: avg pairwise dist; Update: α·sqrt(2πλ) + (1-α)·(width + center shift) | Init: mean NN dist; Update: γ·r·sqrt(λ) + (1-γ)·(width + center shift); Merge: r·sqrt(λ) |
| Creation threshold | Hyperellipsoidal test | Hyperellipsoidal test | Hyperellipsoidal test | Euclidean distance (dynamic threshold) | N/A (always merges) | Euclidean distance (dynamic threshold) |
| Ambiguity resolution | — | — | Shift-and-shrink | Discriminant projection | Coincident: principal-axis subspace | Coincident: principal-axis subspace; Exterior: EMA displacement + expansion |
Parameters
VEBF
from spdal import VEBF
clf = VEBF(theta=0, delta=1)
| Parameter | Default | Description |
|---|---|---|
theta |
0 |
Overlap threshold for neuron merging |
delta |
1 |
Width scaling from pairwise distances for initial width [$\delta > 0$] |
SCIL
from spdal import SCIL
clf = SCIL(N0=3, eta=2, delta=1, theta=0)
| Parameter | Default | Description |
|---|---|---|
N0 |
3 |
Min samples for an active neuron in prediction |
eta |
2 |
Width expansion scaling factor |
delta |
1 |
Width scaling from pairwise distances for initial width [$\delta > 0$] |
theta |
0 |
Overlap threshold for neuron merging |
LRHE
from spdal import LRHE
clf = LRHE(alpha=0.99, theta=0, delta=1)
| Parameter | Default | Description |
|---|---|---|
alpha |
0.99 |
Shrink multiplier during recoil [$\alpha \in [0,1]$]; paper-recommended (gradual shrinking) |
theta |
0 |
Overlap threshold for neuron merging |
delta |
1 |
Width scaling from pairwise distances for initial width [$\delta > 0$] |
SHEF
from spdal import SHEF
clf = SHEF(M=3, r=1.5)
| Parameter | Default | Description |
|---|---|---|
M |
3 |
Min samples before adaptive threshold triggers |
r |
1.5 |
Ellipsoid radius scaling constant [$r > 0$] |
D4
from spdal import D4
clf = D4(width_parameter=1, reduce_dims=0, delta=1, norm=2, threshold=15)
| Parameter | Default | Description |
|---|---|---|
width_parameter |
1 |
Blend: 1 = pure statistical width, 0 = pure expansion-based [$\text{width_parameter} \in [0,1]$] |
reduce_dims |
0 |
Axes to drop in coincident-region disambiguation |
delta |
1 |
Width scaling from pairwise distances for initial width [$\delta > 0$] |
norm |
2 |
Lp norm for distance calculation |
r |
1.5 |
Statistical ellipsoid radius width scaling factor [$r > 0$] |
threshold |
15 |
Angle threshold (degrees) for axis pairing |
D4 maintains one neuron per class. When two nearest neurons belong to different classes, it select their axes using parallel and compactness criteria and assigns the class with the smaller projected distance in that subspace.
Note: Theorem 2 of the D4 paper contains a sign error in the proof. This does not affect the algorithm or experimental results. See technical note for details.
TRACED
from spdal import TRACED
clf = TRACED(
alpha=0.5, beta=0.01, delta=2, width_parameter=1,
reduce_dims=1, N0=3, r=2.507, norm=2,
method='overlap-outside', distance_metric='boundary',threshold=15
)
| Parameter | Default | Description |
|---|---|---|
alpha |
0.5 |
EMA weight for displacement smoothing (0 = disabled) [$\alpha \in [0,1]$] |
beta |
0.01 |
EMA weight for expansion-rate smoothing (0 = disabled) [$\beta \in [0,1]$] |
delta |
2 |
Initial dynamic threshold scaling (mean NN distance × delta) [$\delta > 0$] |
width_parameter |
1 |
Blend: 1 = pure statistical width, 0 = pure expansion-based [$\text{width_parameter} \in [0,1]$] |
reduce_dims |
1 |
Axes to drop in coincident-region disambiguation |
N0 |
3 |
Min samples for an active neuron in prediction and adaptive threshold triggers |
r |
sqrt(2π) |
Statistical ellipsoid radius width scaling factor [$r > 0$] |
norm |
2 |
Lp norm for distance calculation |
method |
'overlap-outside' |
Corrections to apply: 'overlap', 'outside', or both |
distance_metric |
'boundary' |
'boundary' or 'center' |
threshold |
15 |
Angle threshold (degrees) for axis pairing |
TRACED resolves two ambiguous regions:
- Coincident (x inside multiple classes) — principal-axis subspace projection (like D4)
- Exterior (x outside all neurons) — predicts using EMA-smoothed displacement and expansion as a trend model
sklearn Interface
All classifiers are sklearn.base.BaseEstimator subclasses and support:
clf.fit(X, y) # full batch training
clf.partial_fit(X, y, classes=classes) # incremental update
clf.predict(X) # returns array of class labels
clf.classes_ # array of known class labels
clf.neuron_list # list of neuron dicts
Compatible with scikit-learn pipelines and cross-validation tools that support partial_fit.
Neuron Schema
Learned prototypes are stored in clf.neuron_list as a list of dicts:
{
'y': class_label,
'center': np.ndarray, # prototype position
'cov': np.ndarray, # covariance matrix
'eig_component': np.ndarray, # PCA eigenvectors
'width': np.ndarray, # semi-axis lengths
'n': int, # sample count
# SCIL, D4, TRACED only:
'variance': np.ndarray, # eigenvalues
# TRACED only:
'displacement': np.ndarray, # EMA displacement vector
'expansion': np.ndarray, # EMA per-axis expansion rates
}
Development
# Run tests
pytest tests/ -v
# Run a single test class
pytest tests/test_classifiers.py::TestTRACED -v
# Build for PyPI
pip install build && python -m build
References
- VEBF — Jaiyen, S., Lursinsap, C., & Phimoltares, S. (2010). A Very Fast Neural Learning for Classification Using Only New Incoming Datum. IEEE Transactions on Neural Networks, 21(3), 381–392. [paper]
- SCIL — Junsawang, P., Phimoltares, S., & Lursinsap, C. (2019). Streaming chunk incremental learning for class-wise data stream classification with fast learning speed and low structural complexity. PLOS ONE, 14(9), e0220624. [paper]
- LRHE — Jindadoungrut, K., Phimoltares, S., & Lursinsap, C. (2020). Neural Learning With Recoil Behavior in Hyperellipsoidal Structure. IEEE Access, 8, 114643–114655. [paper]
- SHEF — Rungcharassang, P., & Lursinsap, C. (2020). Scalable Hyper-Ellipsoidal Function with Projection Ratio for Local Distributed Streaming Data Classification. IEEE Access, 8, 105460–105474. [paper]
- D4 — Wongsriphisant, P., Plaimas, K., & Lursinsap, C. (2026). Markov-based continuous learning with diversion of data distribution direction for streaming data in limited memory. Expert Systems With Applications, 298, 129818. [paper]
- Technical note (Theorem 2): docs/D4_theorem2_note.md
- TRACED — Wongsriphisant, P., Plaimas, K., & Lursinsap, C. (2026). TRACED: Trend-Adaptive Classification with Ellipsoidal Disambiguation for Resolving Exterior and Coincident Regions in Data Streams. Information Sciences, 743, 123338. [paper]
Citation
If you use this library in your research, please cite the relevant paper(s):
@article{WONGSRIPHISANT2026D4,
title = {Markov-based continuous learning with diversion of data distribution direction for streaming data in limited memory},
journal = {Expert Systems with Applications},
volume = {298},
pages = {129818},
year = {2026},
issn = {0957-4174},
doi = {https://doi.org/10.1016/j.eswa.2025.129818},
url = {https://www.sciencedirect.com/science/article/pii/S0957417425034335},
author = {Peemapat Wongsriphisant and Kitiporn Plaimas and Chidchanok Lursinsap},
}
@article{WONGSRIPHISANT2026TRACED,
title = {TRACED: Trend-adaptive classification with ellipsoidal disambiguation for resolving exterior and coincident regions in data streams},
journal = {Information Sciences},
volume = {743},
pages = {123338},
year = {2026},
issn = {0020-0255},
doi = {https://doi.org/10.1016/j.ins.2026.123338},
url = {https://www.sciencedirect.com/science/article/pii/S0020025526002690},
author = {Peemapat Wongsriphisant and Kitiporn Plaimas and Chidchanok Lursinsap},
}
Notes
- The original monolithic implementation is preserved at
deprecated/spdal.pyfor reference. - Refactoring into the modular
src/spdal/package structure, docstrings, and parameter naming were performed by Claude (Anthropic) and reviewed by the project owner.
Changelog
See CHANGELOG.md. Latest — 0.4.0: VEBF, LRHE, SHEF and TRACED are brought closer to the algorithms as described in their papers, so their results may differ from 0.3.0; LRHE and SCIL gain small numerical safeguards; and D4 no longer takes an r argument. Details and paper references are in the changelog.
Metadata
Release files for spdal 0.4.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 | |
|---|---|---|---|
| spdal-0.4.0.tar.gz | 53.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| spdal-0.4.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 87.5 kB
Release files / spdal-0.4.0.tar.gz
| Download URL | spdal-0.4.0.tar.gz |
|---|---|
| Size | 53.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5410bed9761fa0445df06c3e59786442684fd8c67e6a716c0dcceeef60f4d03b
|
|
BLAKE2b-256 checksum How to use checksums |
260443f3ac0b606b850acb09eaa3accbca9eb33b9c43e45348856209f2c94e66
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.
Transparency logRelease files / spdal-0.4.0-py3-none-any.whl
| Download URL | spdal-0.4.0-py3-none-any.whl |
|---|---|
| Size | 33.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
22b677ccff4cbe9c5408eb4f438cc06189ae223d140a18bdca33646c7cf1d336
|
|
BLAKE2b-256 checksum How to use checksums |
172754c46408d39460e9f6ba8680cebfc2105cf1f27c25ae1f1695bad2ddf1a0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.
Transparency log