Single-pass and discard-after-learn hyperellipsoid classifiers for online learning
Project description
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.
Corrigendum: Theorem 2 of the D4 paper contains a sign error. See the correction and revised theoretical mechanism: Markdown · PDF
Installation
pip install spdal
Development mode:
git clone https://github.com/your-org/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 (chunk) 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 | Key idea |
|---|---|---|---|
VEBF |
Versatile Elliptic Basis Function | 2010 | Foundation: PCA-axis hyperellipsoids, single-datum online learning |
LRHE |
Learning with Recoil in Hyperellipsoidal Structure | 2020 | Shrink-and-shift recoil to handle noisy boundary data |
SCIL |
Streaming Chunk Incremental Learning | 2019 | Neuron merging with parallel-axis covariance pooling |
SHEF |
Scalable Hyper-Ellipsoidal Function | 2020 | Regularized covariance + Mahalanobis-based prediction |
D4 |
Diversion of Data Distribution Direction | 2026 | Hybrid width formula; principal-axis projection for coincident regions |
TRACED |
Trend-Adaptive Classification with Ellipsoidal Disambiguation | TBD | Adds EMA displacement/expansion tracking for exterior-region prediction |
VEBF
from spdal import VEBF
clf = VEBF(theta=0, delta=1, epsilon=1e-10)
| Parameter | Default | Description |
|---|---|---|
theta |
0 |
Overlap threshold for neuron merging |
delta |
1 |
Width scaling from pairwise distances |
epsilon |
1e-10 |
Numerical floor |
LRHE
from spdal import LRHE
clf = LRHE(alpha=0.5, theta=0, delta=1, epsilon=1e-10)
| Parameter | Default | Description |
|---|---|---|
alpha |
0.5 |
Shrink multiplier during recoil (0–1) |
theta |
0 |
Overlap threshold for merging |
delta |
1 |
Width scaling from pairwise distances |
epsilon |
1e-10 |
Numerical floor |
SCIL
from spdal import SCIL
clf = SCIL(N0=3, eta=2, delta=1, theta=0, epsilon=1e-10)
| Parameter | Default | Description |
|---|---|---|
N0 |
3 |
Min samples for an active neuron |
eta |
2 |
Width expansion scaling factor |
delta |
1 |
Width scaling from pairwise distances |
theta |
0 |
Merge overlap threshold |
epsilon |
1e-10 |
Numerical floor |
SHEF
from spdal import SHEF
clf = SHEF(M=3, r=1.5, epsilon=1e-10)
| Parameter | Default | Description |
|---|---|---|
M |
3 |
Min samples before adaptive threshold triggers |
r |
1.5 |
Ellipsoid radius scaling constant |
epsilon |
1e-10 |
Regularization / numerical floor |
D4
from spdal import D4
clf = D4(width_parameter=1, reduce_dims=0, delta=1, norm=2, r=1.5, threshold=15, epsilon=1e-10)
| Parameter | Default | Description |
|---|---|---|
width_parameter |
1 |
Blend: 1 = pure statistical width, 0 = pure expansion-based |
reduce_dims |
0 |
Principal axes to drop in disambiguation subspace |
delta |
1 |
Width scaling from pairwise distances |
norm |
2 |
Lp norm for projected distance |
r |
1.5 |
Radius scaling factor |
threshold |
15 |
Angle threshold (degrees) for axis pairing |
epsilon |
1e-10 |
Numerical floor |
D4 maintains one neuron per class. When two nearest neurons belong to different classes, it pairs their principal axes by smallest angle and assigns the class with the smaller projected distance in that subspace.
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, epsilon=1e-10,
)
| Parameter | Default | Description |
|---|---|---|
alpha |
0.5 |
EMA weight for displacement smoothing (0 = disabled) |
beta |
0.01 |
EMA weight for expansion-rate smoothing (0 = disabled) |
delta |
2 |
Dynamic threshold scaling (mean NN distance × delta) |
width_parameter |
1 |
Blend: 1 = statistical, 0 = expansion-based |
reduce_dims |
1 |
Axes to drop in coincident-region disambiguation |
N0 |
3 |
Min samples for an active neuron |
r |
sqrt(2π) |
Statistical width scaling |
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 |
epsilon |
1e-10 |
Numerical floor |
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 New Versatile Elliptic Basis Function Neural Network. IEEE Transactions on Neural Networks, 21(3), 381–392.
- LRHE — Jindadoungrut, K., Phimoltares, S., & Lursinsap, C. (2020). Neural Learning With Recoil Behavior in Hyperellipsoidal Structure. IEEE Access, 8, 114643–114655.
- 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.
- SHEF — Rungcharassang, P., & Lursinsap, C. (2020). Scalable Hyper-Ellipsoidal Function with Projection Ratio for Local Distributed Streaming Data Classification. IEEE Access. DOI: 10.1109/ACCESS.2020.2997944.
- 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.
- Corrigendum (Theorem 2): docs/D4_corrigendum.md · PDF
- TRACED — Wongsriphisant, P., Plaimas, K., & Lursinsap, C. TRACED: Trend-Adaptive Classification with Ellipsoidal Disambiguation for Resolving Exterior and Coincident Regions in Data Streams. Preprint submitted to Elsevier.
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spdal-0.1.0.tar.gz.
File metadata
- Download URL: spdal-0.1.0.tar.gz
- Upload date:
- Size: 42.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5af750951125a9d046a3174df2c1a37f854642d8e25d16e94fcf1c1a9434446a
|
|
| MD5 |
4232d367df3e3e7f00ffa9f1e701fc24
|
|
| BLAKE2b-256 |
079111fabdafa603d68c5b63b54d294a748d991c909571f30676e35de973e601
|
Provenance
The following attestation bundles were made for spdal-0.1.0.tar.gz:
Publisher:
publish.yml on PeemapatW/single-pass-discard-after-learn
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spdal-0.1.0.tar.gz -
Subject digest:
5af750951125a9d046a3174df2c1a37f854642d8e25d16e94fcf1c1a9434446a - Sigstore transparency entry: 1101045471
- Sigstore integration time:
-
Permalink:
PeemapatW/single-pass-discard-after-learn@51310189b198b13eba85dfa7f69bc501c3009347 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/PeemapatW
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@51310189b198b13eba85dfa7f69bc501c3009347 -
Trigger Event:
release
-
Statement type:
File details
Details for the file spdal-0.1.0-py3-none-any.whl.
File metadata
- Download URL: spdal-0.1.0-py3-none-any.whl
- Upload date:
- Size: 29.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dfa9e9fdafe7557c81af8ac292325a31ea944b498ad5188cd65069d852be0d6a
|
|
| MD5 |
d70dadcf9cb5bc595b9c82c686b563da
|
|
| BLAKE2b-256 |
bb2b0a02087d1383bc4a78183a6debdda0c6400790fb6e050b97fd7997727c62
|
Provenance
The following attestation bundles were made for spdal-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on PeemapatW/single-pass-discard-after-learn
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
spdal-0.1.0-py3-none-any.whl -
Subject digest:
dfa9e9fdafe7557c81af8ac292325a31ea944b498ad5188cd65069d852be0d6a - Sigstore transparency entry: 1101045476
- Sigstore integration time:
-
Permalink:
PeemapatW/single-pass-discard-after-learn@51310189b198b13eba85dfa7f69bc501c3009347 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/PeemapatW
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@51310189b198b13eba85dfa7f69bc501c3009347 -
Trigger Event:
release
-
Statement type: