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#
- class ex_fuzzy.evolutionary_fit_regression.BaseFuzzyRulesRegressor(nRules=30, nAnts=4, n_linguistic_variables=3, fuzzy_type=FUZZY_SETS.t1, linguistic_variables=None, consequent_type='crisp', n_output_lvs=3, n_universe_points=101, rule_mode='additive', tolerance=0.0, verbose=False, backend='pymoo')[source]#
Bases:
RegressorMixin,BaseEstimatorScikit-learn-compatible fast Type-1 fuzzy rules regressor.
consequent_typeselects how a rule states its output:crispZero-order Takagi-Sugeno. Each rule carries a number and predictions are the firing-strength-weighted average of those numbers.
fuzzyMamdani. Each rule names an output fuzzy set whose shape is evolved alongside the rules; predictions are the centroid of the clipped and aggregated consequents. Rules read fully linguistically (
THEN output IS Output_2) at some cost in numeric resolution.
rule_modeselects how many rules speak per sample:additivelets every rule contribute, whilesufficientkeeps only the single strongest rule and falls back to the target mean when even that one fires belowtolerance.backend="pymoo"uses the vectorized NumPy objective on the CPU.backend="evox"evolves populations with EvoX and evaluates complete population batches with PyTorch on CUDA when available.- __init__(nRules=30, nAnts=4, n_linguistic_variables=3, fuzzy_type=FUZZY_SETS.t1, linguistic_variables=None, consequent_type='crisp', n_output_lvs=3, n_universe_points=101, rule_mode='additive', tolerance=0.0, verbose=False, backend='pymoo')[source]#
Configure the regressor; optimization is performed in
fit().
- fit(X, y, n_gen=50, pop_size=50, random_state=42)[source]#
Fit scalar consequents and rule antecedents with a genetic algorithm.
- set_fit_request(*, n_gen='$UNCHANGED$', pop_size='$UNCHANGED$', random_state='$UNCHANGED$')#
Configure whether metadata should be requested to be passed to the
fitmethod.Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with
enable_metadata_routing=True(seesklearn.set_config()). Please check the User Guide on how the routing mechanism works.The options for each parameter are:
True: metadata is requested, and passed tofitif provided. The request is ignored if metadata is not provided.False: metadata is not requested and the meta-estimator will not pass it tofit.None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.str: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (
sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.Added in version 1.3.
- Parameters:
n_gen (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
n_genparameter infit.pop_size (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
pop_sizeparameter infit.random_state (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
random_stateparameter infit.
- Returns:
self – The updated object.
- Return type:
object
FitRuleBaseRegression#
- class ex_fuzzy.evolutionary_fit_regression.FitRuleBaseRegression(X, y, nRules, nAnts, linguistic_variables, y_min=None, y_max=None, y_mean=None, consequent_type='crisp', n_output_lvs=3, n_universe_points=101, rule_mode='additive', tolerance=0.0)[source]#
Bases:
ProblemOptimizer-independent problem for fast optimization of a fixed Type-1 partition.
The integer chromosome always starts with
nRules * nAntsfeature indices followed bynRules * nAntsterm indices (-1means don’t care). The consequent genes depend onconsequent_type:crispnRulesscalar consequents encoded into the target range.fuzzynRulesoutput-set indices, then4 * n_output_lvstrapezoid breakpoints. Each set’s four breakpoints are sorted on decoding, so every chromosome yields a valid trapezoid.
RuleBaseT1Regression#
- class ex_fuzzy.evolutionary_fit_regression.RuleBaseT1Regression(antecedents, rule_list, scalar_consequents, y_mean=None, rule_mode='additive', tolerance=0.0, tnorm=<function prod>)[source]#
Bases:
_RegressionRuleBaseType-1 fuzzy rule base with scalar consequents.
Predictions use zero-order Takagi-Sugeno (height) inference. Samples for which no rule fires fall back to the training-target mean.
RuleBaseT1MamdaniRegression#
- class ex_fuzzy.evolutionary_fit_regression.RuleBaseT1MamdaniRegression(antecedents, rule_list, output_sets, y_mean=None, universe=None, n_universe_points=101, rule_mode='additive', tolerance=0.0, tnorm=<function prod>)[source]#
Bases:
_RegressionRuleBaseType-1 fuzzy rule base whose consequents are output fuzzy sets.
Each rule names one output set. Inference clips every consequent by its rule’s firing strength (min), aggregates the clipped sets with max, and defuzzifies the result by taking its centroid over a discretized universe. Samples for which nothing fires fall back to the training-target mean.
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.