Source code for pyriemann_qiskit.ensemble
"""Ensemble methods for quantum classifiers.
This module provides ensemble classification strategies that combine multiple
classifiers to improve prediction accuracy and robustness.
"""
import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin
from .utils import union_of_diff
[docs]
class JudgeClassifier(ClassifierMixin, BaseEstimator):
"""Judge classifier
Several classifiers are trained on the balanced dataset.
When at least one classifier disagrees on the label of a given input
in the training set, the input was noted.
These inputs, a subset of the training data of the balanced dataset,
formed an additional dataset on which a new classifier was subsequently
trained. Adapted from [1]_.
Parameters
----------
judge : ClassifierMixin
Classifier trained on the inputs for which
classifiers `clfs` obtain different predictions.
clfs : list of ClassifierMixin
Classifiers trained on the balanced dataset.
Notes
-----
.. versionadded:: 0.2.0
References
----------
.. [1] M. Grossi et al.,
‘Mixed Quantum–Classical Method for Fraud Detection With Quantum
Feature Selection’,
IEEE Transactions on Quantum Engineering,
doi: 10.1109/TQE.2022.3213474.
"""
[docs]
def __init__(self, judge, clfs):
self.clfs = clfs
self.judge = judge
def fit(self, X, y):
"""Fit all base classifiers and the judge classifier.
Trains all classifiers in `clfs` on the full dataset, then identifies
samples where classifiers disagree and trains the judge classifier on
those samples only.
Parameters
----------
X : ndarray, shape (n_samples, n_features) or (n_samples, n_features, n_times)
Training data. Shape must be consistent across all classifiers.
y : ndarray, shape (n_samples,)
Target labels.
Returns
-------
self : JudgeClassifier
The fitted classifier instance.
"""
self.classes_ = np.unique(y)
ys = [clf.fit(X, y).predict(X) for clf in self.clfs]
mask = union_of_diff(*ys)
if not mask.any():
self.judge.fit(X, y)
else:
self.judge.fit(X[mask], y[mask])
return self
def predict(self, X):
"""Predict class labels for samples in X.
Uses base classifiers for prediction. When classifiers disagree on a
sample, the judge classifier makes the final decision for that sample.
Parameters
----------
X : ndarray, shape (n_samples, n_features) or (n_samples, n_features, n_times)
Test samples. Shape must be consistent across all classifiers.
Returns
-------
y_pred : ndarray, shape (n_samples,)
Predicted class labels.
See Also
--------
union_of_diff : Function to identify samples with disagreement
"""
ys = [clf.predict(X) for clf in self.clfs]
y_pred = ys[0]
mask = union_of_diff(*ys)
if not mask.any():
return y_pred
y_pred[mask] = self.judge.predict(X[mask])
return y_pred
def predict_proba(self, X):
"""Predict class probabilities for samples in X.
Returns averaged probabilities from base classifiers when they agree.
When classifiers disagree, returns probabilities from the judge classifier.
Parameters
----------
X : ndarray, shape (n_samples, n_features) or (n_samples, n_features, n_times)
Test samples. Shape must be consistent across all classifiers.
Returns
-------
proba : ndarray, shape (n_samples, n_classes)
Class probabilities for each sample.
"""
ys = [clf.predict_proba(X) for clf in self.clfs]
predict_proba = sum(ys) / len(ys)
mask = union_of_diff(*ys)
if not mask.any():
return predict_proba
predict_proba[mask] = self.judge.predict_proba(X[mask])
return predict_proba