Fuzzy Regression#
The ex_fuzzy.evolutionary_fit_regression module learns interpretable
Type-1 fuzzy rules for continuous targets. During optimization it precomputes
the fixed input-partition memberships and scores candidate rule bases through a
vectorized NumPy inference path with PyMoo, or a batched PyTorch path with the
optional EvoX backend.
Two consequent styles are available, selected with consequent_type:
crisp(default)Zero-order Takagi-Sugeno. Each rule carries a number, and a prediction is the firing-strength-weighted average of those numbers. Best numeric resolution.
fuzzyMamdani. Each rule names an output fuzzy set whose trapezoid is evolved alongside the rules; predictions are the centroid of the clipped and max-aggregated consequents. Rules read fully linguistically, at some cost in resolution.
rule_mode controls how many rules speak per sample. additive (default)
lets every rule contribute. sufficient keeps only each sample’s strongest
rule, and falls back to the training-target mean when even that rule fires at
or below tolerance – giving piecewise-constant, winner-takes-all output.
BaseFuzzyRulesRegressor#
FitRuleBaseRegression#
RuleBaseT1Regression#
RuleBaseT1MamdaniRegression#
Example#
from ex_fuzzy import BaseFuzzyRulesRegressor
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
X, y = make_regression(n_samples=200, n_features=4, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=0
)
regressor = BaseFuzzyRulesRegressor(nRules=20, nAnts=3)
regressor.fit(X_train, y_train, n_gen=50, pop_size=50)
predictions = regressor.predict(X_test)
print(regressor.score(X_test, y_test))
regressor.print_rules()
# Rule 1: IF x0 IS Low AND x2 IS High THEN output = 41.8203
GPU optimization#
Install ex-fuzzy[evox] and select the EvoX backend to evaluate complete
populations on CUDA. If CUDA is unavailable, EvoX runs the same PyTorch path on
the CPU.
regressor = BaseFuzzyRulesRegressor(
nRules=30, nAnts=4, backend="evox", verbose=True
)
regressor.fit(X_train, y_train, n_gen=50, pop_size=100)
print(regressor.optimization_device_)
print(regressor.gpu_accelerated_)
Linguistic consequents#
Switch to Mamdani inference when a rule should name an output label rather than a number:
regressor = BaseFuzzyRulesRegressor(
nRules=20,
nAnts=3,
consequent_type="fuzzy",
n_output_lvs=4, # how many output sets to evolve
n_universe_points=101, # centroid integration grid
)
regressor.fit(X_train, y_train, n_gen=50, pop_size=50)
regressor.print_rules()
# Rule 1: IF x0 IS Low AND x2 IS High THEN output IS Output_3
Every chromosome decodes to a valid trapezoid because each output set’s four breakpoints are sorted before being scaled into the target range.
Winner-takes-all rules#
regressor = BaseFuzzyRulesRegressor(
nRules=20, nAnts=3, rule_mode="sufficient", tolerance=0.05
)
With sufficient only the strongest rule fires per sample, so a crisp-
consequent model becomes piecewise constant: every prediction is one rule’s
consequent, or the target mean where nothing clears the tolerance.
The genetic search optimizes training-set \(R^2\). To estimate
generalization with cross-validation, evaluate the complete estimator through
scikit-learn’s cross_val_score or cross_validate; the estimator must be
refitted independently inside each fold.