Skip to content

Batch inference, serialization & scikit-learn

Batch (vectorized) inference

Calling a system evaluates one sample. predict(**arrays) evaluates many at once — pass an array per variable and get an array back. Available on every engine: Mamdani, TSK, Tsukamoto, FuzzyClassifier and the interval type-2 engines.

import numpy as np
from fuzzytool import datasets

sys, *_ = datasets.credit_risk()
scores = np.array([520.0, 660.0, 800.0])
dtis   = np.array([42.0, 30.0, 10.0])

sys.predict(score=scores, dti=dtis)   # -> array([10.16, 6.  ,  1.91]), one premium per sample

The result matches calling the system once per sample, but the firing, implication, aggregation and defuzzification steps run vectorized (Mamdani uses a batch centroid/bisector when the defuzzifier has one, and falls back to a per-sample loop otherwise). Samples where no rule fires follow the system's on_no_rule policy — by default the Mamdani midpoint or a TSK NaN.

Memory: chunking large batches

Mamdani inference materializes an (n_samples, resolution) array per output, so a very large batch would otherwise exhaust memory. predict processes the batch in blocks of chunk_size samples (4096 by default):

sys.predict(score=scores, dti=dtis, chunk_size=512)   # tighter memory bound
sys.predict(score=scores, dti=dtis, chunk_size=None)  # off

The results are identical either way, and chunking costs nothing measurable — see Performance.

Saving and loading systems

Serialize any rule-based system to JSON and restore it later: Mamdani, TSK, Tsukamoto, FuzzyClassifier, IT2Mamdani and IT2TSK. Connectives and the defuzzifier must be given by name, every membership function must be registered (the built-ins are), and TSK consequents must be numbers or coefficient mappings rather than callables.

import fuzzytool as fz

fz.save(sys, "credit_risk.json")
restored = fz.load("credit_risk.json")

The file records a format_version; a file written by a newer, incompatible version of fuzzytool is rejected with a clear error rather than silently misread.

fuzzytool.membership.to_dict/from_dict and Variable.to_dict/from_dict expose the building blocks if you need finer control.

scikit-learn compatibility

ANFIS follows the estimator protocol (fit returns self, plus predict, get_params, set_params), so it drops into a Pipeline or GridSearchCV without importing scikit-learn at all:

import fuzzytool as fz

model = fz.ANFIS(n_inputs=2, n_mf=3)
model.get_params()              # every hyperparameter, ready for a clone
clone = fz.ANFIS(**model.get_params())

The scikit-learn integration adds estimators proper — Fuzzifier, WangMendelRegressor, FuzzySystemRegressor, ChiClassifier and FuzzySystemClassifier — which carry the estimator tags scikit-learn 1.6+ expects, so cross_val_score, GridSearchCV and Pipeline all work:

from fuzzytool.integrations.sklearn import ChiClassifier
from sklearn.model_selection import cross_val_score

cross_val_score(ChiClassifier(inputs), X, y, cv=5)