Conformal Module#
The ex_fuzzy.conformal module provides conformal prediction utilities for fuzzy classifiers.
Overview#
This module wraps fuzzy classifiers to output prediction sets with coverage guarantees and supports evaluation of empirical coverage.
Classes#
ConformalFuzzyClassifier#
- class ex_fuzzy.conformal.ConformalFuzzyClassifier(clf_or_nRules=None, score_type='membership', **kwargs)[source]#
Bases:
ClassifierMixin,BaseEstimatorConformal prediction wrapper for fuzzy rule-based classifiers.
Can wrap an existing BaseFuzzyRulesClassifier or create one internally using the same parameter signature. Provides prediction sets with statistical coverage guarantees.
- Parameters:
clf_or_nRules (BaseFuzzyRulesClassifier or int, optional) – Either a trained classifier to wrap, or nRules parameter to create new one. If None, uses default nRules=30.
score_type (str, default='membership') – Nonconformity score type: - ‘membership’: 1 - membership degree of true class (default) - ‘association’: 1 - max association degree for rules of true class - ‘entropy’: Entropy of class probability distribution
**kwargs (dict) – Additional parameters passed to BaseFuzzyRulesClassifier if creating new. Common parameters include: nAnts, fuzzy_type, n_linguistic_variables, tolerance, verbose, backend, etc.
- clf#
The underlying fuzzy classifier
- Type:
- score_type#
The type of nonconformity score being used
- Type:
str
- rule_base#
The rule base from the underlying classifier (property)
- Type:
- nclasses_#
Number of classes (property)
- Type:
int
Examples
Wrap an existing trained classifier:
>>> from ex_fuzzy.evolutionary_fit import BaseFuzzyRulesClassifier >>> from ex_fuzzy.conformal import ConformalFuzzyClassifier >>> >>> clf = BaseFuzzyRulesClassifier(nRules=20) >>> clf.fit(X_train, y_train, n_gen=50) >>> >>> conf_clf = ConformalFuzzyClassifier(clf) >>> conf_clf.calibrate(X_cal, y_cal) >>> pred_sets = conf_clf.predict_set(X_test, alpha=0.1)
Create classifier from scratch:
>>> conf_clf = ConformalFuzzyClassifier(nRules=20, nAnts=4) >>> conf_clf.fit(X_train, y_train, X_cal, y_cal, n_gen=50) >>> pred_sets = conf_clf.predict_set(X_test, alpha=0.1)
Get rule-wise explanations:
>>> results = conf_clf.predict_set_with_rules(X_test, alpha=0.1) >>> for r in results: ... print(f"Prediction set: {r['prediction_set']}") ... print(f"Rule contributions: {r['rule_contributions']}")
A conformal wrapper that provides prediction sets and calibration utilities.
- fit(X, y, X_cal=None, y_cal=None, cal_size=0.2, **fit_kwargs)[source]#
Fit the classifier and calibrate for conformal prediction.
If X_cal/y_cal not provided, automatically splits X/y using cal_size.
- Parameters:
X (array-like of shape (n_samples, n_features)) – Training data
y (array-like of shape (n_samples,)) – Training labels
X_cal (array-like of shape (n_cal_samples, n_features), optional) – Calibration data. If None, split from X using cal_size.
y_cal (array-like of shape (n_cal_samples,), optional) – Calibration labels. If None, split from y using cal_size.
cal_size (float, default=0.2) – Fraction of data to use for calibration if X_cal not provided
**fit_kwargs (dict) – Parameters passed to clf.fit() (n_gen, pop_size, etc.)
- Returns:
self – The fitted conformal classifier
- Return type:
Examples
>>> conf_clf = ConformalFuzzyClassifier(nRules=20) >>> # Auto-split for calibration >>> conf_clf.fit(X, y, cal_size=0.2, n_gen=50)
>>> # Or provide explicit calibration set >>> conf_clf.fit(X_train, y_train, X_cal, y_cal, n_gen=50)
- calibrate(X_cal, y_cal)[source]#
Calibrate conformal prediction thresholds using calibration set.
Computes nonconformity scores on the calibration set and stores them for computing p-values during prediction.
- Parameters:
X_cal (array-like of shape (n_cal_samples, n_features)) – Calibration samples
y_cal (array-like of shape (n_cal_samples,)) – Calibration labels
- Returns:
self – The calibrated conformal classifier
- Return type:
- Raises:
ValueError – If the underlying classifier has not been fitted yet
Examples
>>> # After fitting the base classifier separately >>> conf_clf = ConformalFuzzyClassifier(trained_clf) >>> conf_clf.calibrate(X_cal, y_cal)
- predict(X)[source]#
Standard point prediction (delegates to wrapped classifier).
- Parameters:
X (array-like of shape (n_samples, n_features)) – Test samples
- Returns:
predictions – Predicted class labels
- Return type:
ndarray of shape (n_samples,)
- predict_set(X, alpha=0.1)[source]#
Predict conformal sets with coverage guarantee 1-alpha.
Returns prediction sets that, under exchangeability assumptions, contain the true label with probability at least 1-alpha.
- Parameters:
X (array-like of shape (n_samples, n_features)) – Test samples
alpha (float, default=0.1) – Significance level. The coverage guarantee is 1-alpha. For example, alpha=0.1 gives 90% coverage.
- Returns:
prediction_sets – For each sample, a set of class indices in the prediction set. Empty sets indicate high uncertainty for all classes. Sets with multiple classes indicate ambiguous predictions.
- Return type:
list of sets
- Raises:
ValueError – If the classifier is not calibrated
Examples
>>> pred_sets = conf_clf.predict_set(X_test, alpha=0.1) >>> for i, pred_set in enumerate(pred_sets): ... if len(pred_set) == 1: ... print(f"Sample {i}: confident prediction {pred_set}") ... elif len(pred_set) > 1: ... print(f"Sample {i}: ambiguous between {pred_set}") ... else: ... print(f"Sample {i}: high uncertainty (empty set)")
- predict_set_with_rules(X, alpha=0.1)[source]#
Predict conformal sets with rule-level explanations.
Returns prediction sets along with which rules contribute and their individual confidence levels. This provides explainable uncertainty quantification.
- Parameters:
X (array-like of shape (n_samples, n_features)) – Test samples
alpha (float, default=0.1) – Significance level (0.1 = 90% coverage)
- Returns:
results – Each result dict includes keys: ‘prediction_set’ (set of class indices), ‘rule_contributions’ (list of per-rule contribution dicts with ‘rule_index’, ‘class’, ‘firing_strength’, and ‘rule_confidence’), and ‘class_p_values’ (dict mapping class index to p-value).
- Return type:
list of dicts
- Raises:
ValueError – If the classifier is not calibrated
Examples
>>> results = conf_clf.predict_set_with_rules(X_test[:5], alpha=0.1) >>> for i, r in enumerate(results): ... print(f"Sample {i}:") ... print(f" Prediction set: {r['prediction_set']}") ... print(f" P-values: {r['class_p_values']}") ... for contrib in r['rule_contributions'][:3]: ... print(f" Rule {contrib['rule_index']}: " ... f"class={contrib['class']}, " ... f"strength={contrib['firing_strength']:.3f}")
- get_calibration_info()[source]#
Return calibration statistics for inspection.
- Returns:
info – Dictionary containing: - ‘n_calibration_samples’: total calibration samples - ‘samples_per_class’: dict of samples per class - ‘score_type’: the nonconformity score type used - ‘n_rules_calibrated’: number of rules with calibration data
- Return type:
dict
Examples
>>> info = conf_clf.get_calibration_info() >>> print(f"Calibrated with {info['n_calibration_samples']} samples") >>> print(f"Score type: {info['score_type']}")
- print_rules(return_rules=False, bootstrap_results=False)[source]#
Print or return the rules from the underlying classifier.
- set_fit_request(*, X_cal='$UNCHANGED$', cal_size='$UNCHANGED$', y_cal='$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:
X_cal (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
X_calparameter infit.cal_size (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
cal_sizeparameter infit.y_cal (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
y_calparameter infit.
- Returns:
self – The updated object.
- Return type:
object
- set_score_request(*, sample_weight='$UNCHANGED$')#
Configure whether metadata should be requested to be passed to the
scoremethod.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 toscoreif provided. The request is ignored if metadata is not provided.False: metadata is not requested and the meta-estimator will not pass it toscore.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:
sample_weight (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
sample_weightparameter inscore.- Returns:
self – The updated object.
- Return type:
object
evaluate_conformal_coverage#
- ex_fuzzy.conformal.evaluate_conformal_coverage(conf_clf, X_test, y_test, alpha=0.1)[source]#
Evaluate conformal prediction coverage and efficiency.
Computes metrics to assess the quality of conformal predictions, including whether the coverage guarantee is satisfied and how informative the prediction sets are.
- Parameters:
conf_clf (ConformalFuzzyClassifier) – A calibrated conformal classifier
X_test (array-like of shape (n_samples, n_features)) – Test samples
y_test (array-like of shape (n_samples,)) – True labels for test samples
alpha (float, default=0.1) – Significance level used for prediction sets
- Returns:
metrics – Dictionary containing: - ‘coverage’: Empirical coverage (should be >= 1-alpha) - ‘expected_coverage’: The target coverage (1-alpha) - ‘avg_set_size’: Average prediction set size - ‘efficiency’: 1 / avg_set_size (higher is better) - ‘empty_sets’: Proportion of empty prediction sets - ‘singleton_sets’: Proportion of single-class sets - ‘coverage_by_class’: Per-class coverage rates
- Return type:
dict
Examples
>>> metrics = evaluate_conformal_coverage(conf_clf, X_test, y_test, alpha=0.1) >>> print(f"Coverage: {metrics['coverage']:.3f} (expected: {metrics['expected_coverage']:.3f})") >>> print(f"Average set size: {metrics['avg_set_size']:.2f}") >>> print(f"Singleton rate: {metrics['singleton_sets']:.2%}")
>>> # Check coverage guarantee >>> if metrics['coverage'] >= metrics['expected_coverage'] - 0.05: ... print("Coverage guarantee approximately satisfied")
Examples#
from ex_fuzzy.conformal import ConformalFuzzyClassifier, evaluate_conformal_coverage
from sklearn.model_selection import train_test_split
X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.4, random_state=0)
X_cal, X_test, y_cal, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=0)
conf_clf = ConformalFuzzyClassifier(nRules=20, nAnts=4)
conf_clf.fit(X_train, y_train, X_cal, y_cal, n_gen=50, pop_size=50)
pred_sets = conf_clf.predict_set(X_test, alpha=0.1)
metrics = evaluate_conformal_coverage(conf_clf, X_test, y_test, alpha=0.1)