basis
Basis-function models in C11: extreme learning machines (ELM), random vector functional-link models (RVFL), random Fourier features (RFF), and Nyström RBF features. Regression uses a regularized linear readout; classification offers multinomial logistic or one-hot ridge readouts.
The C engine requires only libc/libm. JavaScript uses @wlearn/core for matrix
normalization, errors, WLRN artifacts, metrics and loader registration. Python
uses NumPy plus wlearn for artifacts, errors and registration. No Polygrad,
BLAS, LAPACK or external neural runtime is required.
Requires @wlearn/core 0.3 in JavaScript or wlearn>=0.3,<0.4 in Python.
JavaScript
const { BasisRegressor } = require('@wlearn/basis')
const { load } = require('@wlearn/core')
const X = [[-1, 0], [0, 1], [1, 0], [2, 1]]
const model = await BasisRegressor.create({ method: 'rvfl', nComponents: 64 })
model.fit(X, [-1, 1, 3, 5])
const predictions = model.predict([[0.5, 0]])
const restored = await load(model.save())
Use BasisClassifier for classification, with predictProba(X),
decisionFunction(X) and the classes property. Probabilities and decisions
are flat row-major arrays of rows * classes.length. Predictions retain sorted
original int32 class labels. Dense {data, rows, cols} matrices and rectangular
numeric arrays are accepted; sparse and missing inputs are unsupported.
Construction/loading is asynchronous. fit, prediction, scoring, save and
dispose are synchronous. fit(X, y, {sampleWeight}) accepts nonnegative weights
with positive total and positive weight in every observed class.
dist/basis.js exposes the basis browser global. dist/basis.mjs provides
named ESM exports. Both embed single-threaded WASM and work without special
cross-origin isolation headers. TypeScript declarations implement the shared
wlearn Estimator/Classifier contract.
Python
from wlearn_basis import BasisRegressor
from wlearn import load
model = BasisRegressor(method="rvfl", n_components=64)
model.fit([[-1, 0], [0, 1], [1, 0], [2, 1]], [-1, 1, 3, 5])
predictions = model.predict([[0.5, 0]])
model.save("model.wlrn")
restored = load("model.wlrn")
Python names use snake_case: n_components, max_iter, get_params,
set_params, default_search_space, predict_proba, decision_function,
feature_map, fit_info, classes_, n_features_in_, n_components_.
fit(X, y, sample_weight=None) accepts NumPy arrays or numeric lists.
predict_proba and decision_function return (rows, classes) arrays, including
two columns for binary classification. save(path=None) returns WLRN bytes;
load(bytes_or_path) accepts those bytes or a filesystem path.
Models and parameters
| Parameter (JS / Python) | Default | Meaning |
|---|---|---|
method |
rff |
elm, rvfl, rff, nystrom |
sampling |
gaussian |
gaussian or supervised swim, for ELM/RVFL |
nComponents / n_components |
128 | Requested map width, 1–4096 |
activation |
tanh |
tanh or relu, for ELM/RVFL |
readout |
ridge / logistic |
Regression / classification default |
alpha |
1 | Positive readout regularization |
gamma |
0.1 | Positive RBF inverse length scale, RFF/Nyström |
scale |
1 | Positive weight/bias scale, or SWIM transition scale |
seed |
42 | Integer 0–2³²−1 |
maxIter / max_iter |
300 | Logistic iteration cap |
tol |
1e-6 | Logistic mean-objective gradient infinity-norm threshold |
Scale numeric inputs using training rows only, through preprocessing outside
the model (for wlearn pipelines, use @wlearn/preprocess / wlearn.preprocess).
Map width, regularization and kernel width affect quality. These defaults are
starting points, not selected configurations for every dataset.
- ELM defaults to fixed Gaussian weights scaled by
scale / sqrt(input width), uniform biases in[-scale, scale], then tanh or ReLU. - RVFL appends the original numeric inputs to those ELM features.
- RFF uses
sqrt(2/m) * cos(Wx + b), Gaussian weights of variance2*gammaand uniform phase. It approximatesexp(-gamma * ||x-z||²). - Nyström samples distinct training row indices and whitens their RBF kernel
using a symmetric eigendecomposition. Effective width is
min(nComponents,n); duplicate rows are allowed. Eigenvalues at most1e-12 * max(1, largest)are truncated. Feature coordinates are not uniquely determined across numerical implementations; their kernel and predictions are the meaningful comparison.
SWIM sampling
Set sampling: 'swim' in JS or sampling="swim" in Python with method='elm'
or 'rvfl'. SWIM samples a supervised map once; it uses the same readout and
has the same prediction cost as the corresponding Gaussian map.
The implementation follows Bolager et al., NeurIPS 2023.
Pair mass is proportional to abs(y2-y1) / ||x2-x1||; classification uses
one-hot target distance (one for different classes, zero otherwise), so class
numbers carry no ordering. Positive sample weights define the endpoint measure.
All ordered pairs are considered if they fit within max(4096, 8*nComponents);
otherwise that many pairs are sampled with replacement from the endpoint measure.
The hidden units are resampled from this pool using the supervised masses.
This is a bounded approximation, not exhaustive pair search on large datasets.
For endpoints a,b, hidden weights are s1*(b-a)/||b-a||² and bias is
-dot(weights,a)-s2. Tanh uses (s1,s2)=scale*(log(3),log(3)/2); ReLU uses
(scale,0). At scale one, the two endpoints map to (-.5,.5) for tanh or
(0,1) for ReLU. Pairs within 1e-12 input units are excluded. If all target
differences in the pool vanish, sampling uses endpoint masses alone. If no
usable pair remains, hidden weights are zero, retaining the readout intercept
and RVFL direct inputs. No preprocessing or target data is stored for inference.
SWIM must be fitted inside every CV training fold, after training-only scaling.
Do not construct its map from validation targets. Tune alpha, width,
activation and scale; supervised sampling does not guarantee better predictions.
Ridge minimizes sum(w * residual²) + alpha * ||coefficients||² via incremental
Givens QR. Logistic minimizes sum(w * cross_entropy) + alpha/2 * ||coefficients||²
via L-BFGS. Both leave the intercept unpenalized. Classification ridge fits
one-hot targets and softmaxes its scores; those probabilities are uncalibrated.
fitInfo / fit_info reports iterations and convergence. Ridge reports one
direct solve. A logistic iteration cap or unsuccessful line search retains a
finite fitted model with converged=false; inspect this diagnostic when tuning.
Ridge uses O(q² + qk) workspace, while logistic additionally holds the n×q
feature matrix; Nyström has O(m²) storage and an O(m³) eigensolve. Individual
arrays and the model payload are limited to 256 MiB, not total process memory. WASM memory may grow to
1 GiB. Large input magnitudes may be rejected when feature/readout arithmetic
cannot remain finite.
Lifecycle and composition
BasisTransformer fits only a feature map and emits a host-owned dense matrix.
It shares map construction with the fused estimators and can precede GAM, RF,
XGBoost or another compatible estimator:
const { BasisTransformer } = require('@wlearn/basis')
const { RFModel } = require('@wlearn/rf')
const { Pipeline } = require('@wlearn/core')
const map = await BasisTransformer.create({ method: 'rvfl', sampling: 'swim', nComponents: 64 })
const forest = await RFModel.create({ task: 'regression', nEstimators: 100 })
const pipeline = new Pipeline([['map', map], ['forest', forest]])
pipeline.fit(X, y)
const predictions = pipeline.predict(Xtest)
const bytes = pipeline.save()
Python exposes the same BasisTransformer, with fit_transform, transform,
save(path=None) and load(bytes_or_path). Map parameters exclude readout,
alpha, maxIter and tol; task defaults to 'regression'. Set
task: 'classification' when SWIM should use label equality rather than numerical
target distance. Only SWIM requires y. Weights affect SWIM sampling; other maps
retain seeded sampling. Pipeline forwards weights to steps declaring support and
rejects a weighted fit if the final estimator cannot consume them.
Map persistence uses wlearn.basis.transformer@1 with a BAM1 payload inside
WLRN. There is no readout state. Keep SWIM fitting inside each CV training fold;
AutoML can search a caller-provided estimator factory owning this Pipeline.
Its Tranfi templates continue to cover ordinary tabular preparation.
Materializing a map allocates rows * outputCols * 8 bytes before the next
estimator copies input into its own runtime. Fused ridge avoids this training
matrix through streaming QR. Tree composition is available, but its accuracy and
cost need validation for the intended dataset.
getParams/setParams expose validated parameters. A changed parameter
invalidates fitted state. Invalid parameters and failed refits preserve the
previous fitted model. Returned predictions/features/coefficients are owned
copies. featureMap / feature_map inspects the fitted map; it is not a pipeline
Transformer. coefficients() includes the intercept in its last row.
Call dispose() when replacing models or completing loops, CV and worker jobs.
Each model owns native allocations; disposal is idempotent. Finalizers are a
fallback. Python instances and the singleton WASM module are intended for serial
calls; use separate workers/processes for parallel training.
Both estimator classes expose model-provided search spaces and stable AutoML
class IDs. They compose with existing core Pipeline, VotingEnsemble and AutoML
without model-specific engine code. The SDK re-exports both estimators and the
Transformer. defaultPortfolio() / default_portfolio() supplies four initial
configurations; callers can override these through the model spec's portfolio.
The shared search IR currently supports equality conditions. The default space
therefore searches sampling, activation and scale when method='elm'; RVFL
uses defaults for those fields. To tune SWIM RVFL, supply a space with
method fixed to rvfl and those parameters unconditional.
Gaussian persistence retains wlearn.basis.classifier@1 and wlearn.basis.regressor@1.
SWIM uses the corresponding @2 type IDs and BAS2 payload, with the sampling
flag in header word 52. Old readers reject this version; current readers accept
both. Existing Gaussian bundles and Gaussian RNG sequences are unchanged.
The core WLRN container holds a validated application/vnd.wlearn.basis payload
with BAS1 magic, a 96-byte little-endian header, feature parameters, Nyström
whitening matrix, readout coefficients and original labels. Payload bytes survive
Python/JS round trips exactly; fresh native/WASM training is compared within
numerical tolerance. There is no pickle or alternative public artifact format.
Build and test
Canonical C sources live in src/. js/csrc/ and py/csrc/ are generated
distribution copies, following the RF/GAM layout. Native CMake builds a shared
library; Python wheels compile the same sources into a ctypes-loadable extension.
make test-c JOBS=4
make build-js # Emscripten, Node, esbuild and local core required
make test-js test-types test-browser
make test-py PYTHON=python3 # install Python test extras first
make wheel PYTHON=python3
Use process affinity and numerical thread limits appropriate to the host.
Browser tests reuse the ecosystem Playwright install and Chromium cache.
BASIS_LIB_PATH selects a native development library explicitly. The native
build and wheels have been exercised on Linux x86-64; other native platforms
require their own build checks.
bench/composition.py --output RUN compares fused ridge with a separately fitted
map plus matched sklearn ridge, and raw/map-based RF and XGBoost. It uses four
small IID datasets and three fixed outer splits, without tuning. The shared
repository's bench/basis-composition.mjs RUN WASM_RUN consumes those exact
prepared splits for a separate WASM Pipeline comparison.
bench/benchmark.py compares fixed settings against native linear/logistic,
wlearn RF, XGBoost and LightGBM on six datasets and three held-out splits.
Install its optional reference dependencies first. It writes the protocol before
fitting, hashes implementation inputs and reports metrics, fit/predict times,
bundle sizes and cumulative process RSS. bench/benchmark.js consumes the same
prepared splits for a separate WASM comparison. Timings are single warm-process
measurements, not controlled performance regression gates.
bench/tune.py --output RUN --energy-csv DATA.csv runs the separate small tuning
study: 12 candidates per family, three inner folds and two outer split seeds.
Gaussian/SWIM ELM and RVFL share candidates; RFF/Nyström, ridge/logistic,
XGBoost and LightGBM are tuned too. Six original datasets are retained, with iris
and UCI energy heating load added. The latter is a building simulation dataset:
Tsanas & Xifara (2012), UCI, CC BY 4.0.
Download its CSV separately;
it is not shipped in the package. Protocol, splits, source hashes, trial failures,
warnings, convergence, selected parameters and test predictions are saved.
License
Original implementation: Apache-2.0. No GPL model dependency is included.
The npm package carries Emscripten, musl, compiler-rt and bundled wlearn core
notices under licenses/; browser distributions embed those license texts.
Metadata
Release files for wlearn-basis 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 | Provenance | Actions |
|---|---|---|---|---|
| wlearn_basis-0.1.0.tar.gz | 36.1 kB | Without provenance | Details for wlearn_basis-0.1.0.tar.gz |
Release files / wlearn_basis-0.1.0.tar.gz
| Download URL | wlearn_basis-0.1.0.tar.gz |
|---|---|
| Size | 36.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1bf5daad4e66c6864c0bc7ed056a0e38670cb65c6918720c8ee2e02effa288da
|
|
BLAKE2b-256 checksum How to use checksums |
113499148516e1781eb52d19486810b6796a95de3036871735bf6dfba2314acb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Security for wlearn-basis 0.1.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.