Source code for pyriemann_qiskit.classification.wrappers.quantic_svm

"""Quantum-enhanced SVM classifier."""

import numpy as np
from qiskit_machine_learning.algorithms import QSVC, PegasosQSVC
from scipy.special import softmax
from sklearn.svm import SVC

from ...utils.hyper_params_factory import gen_zz_feature_map
from ...utils.quantum_provider import get_quantum_kernel
from .quantic_classifier_base import QuanticClassifierBase


[docs] class QuanticSVM(QuanticClassifierBase): """Quantum-enhanced SVM classifier This class implements a support-vector machine (SVM) classifier [1]_, called SVC, on a quantum machine [2]_. Note that if `quantum` parameter is set to `False` then a classical SVC will be performed instead. Notes ----- .. versionadded:: 0.0.1 .. versionchanged:: 0.0.2 Qiskit's Pegasos implementation [4]_, [5]_. .. versionchanged:: 0.1.0 Fix: copy estimator not keeping base class parameters. .. versionchanged:: 0.2.0 Add seed parameter SVC and QSVC now compute probability (may impact performance) Predict is now using predict_proba with a softmax, when using QSVC. .. versionchanged:: 0.3.0 Add use_fidelity_state_vector_kernel parameter .. versionchanged:: 0.4.0 Add n_jobs and use_qiskit_symb parameter for SymbFidelityStatevectorKernel .. versionchanged:: 0.6.0 Migrate to Qiskit 2.x: use ``BackendSamplerV2`` via base class. Moved to :mod:`pyriemann_qiskit.classification.wrappers.quantic_svm`. Parameters ---------- gamma : float | None, default=None Used as input for sklearn rbf_kernel which is used internally. See [3]_ for more information about gamma. C : float, default=1.0 Regularization parameter. The strength of the regularization is inversely proportional to C. Must be strictly positive. Note, if pegasos is enabled you may want to consider larger values of C. max_iter: int | None, default=None Number of steps in Pegasos or (Q)SVC. If None, respective default values for Pegasos and SVC are used. The default value for Pegasos is 1000. For (Q)SVC it is -1 (that is not limit). pegasos : boolean, default=False If true, uses Qiskit's PegasosQSVC instead of QSVC. quantum : bool, default=True - If true will run on local or remote backend (depending on q_account_token value), - If false, will perform classical computing instead. q_account_token : string | None, default=None If `quantum` is True and `q_account_token` provided, the classification task will be running on a IBM quantum backend. If `load_account` is provided, the classifier will use the previous token saved with `IBMProvider.save_account()`. verbose : bool, default=True If true, will output all intermediate results and logs. shots : int, default=1024 Number of repetitions of each circuit, for sampling. gen_feature_map : Callable[[int, str], QuantumCircuit | FeatureMap], \ default=Callable[int, ZZFeatureMap] Function generating a feature map to encode data into a quantum state. seed : int | None, default=None Random seed for the simulation use_fidelity_state_vector_kernel: boolean, default=True if True, use a FidelitystatevectorKernel for simulation. use_qiskit_symb: boolean, default=True This flag is used only if qiskit-symb is installed, and pegasos is False. If True and the number of qubits < 9, then qiskit_symb is used. n_jobs: boolean The number of jobs for the qiskit-symb fidelity state vector (if applicable) See Also -------- QuanticClassifierBase SymbFidelityStatevectorKernel References ---------- .. [1] Available from: \ https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html .. [2] V. Havlíček et al., 'Supervised learning with quantum-enhanced feature spaces', Nature, vol. 567, no. 7747, pp. 209–212, Mar. 2019, doi: 10.1038/s41586-019-0980-2. .. [3] Available from: \ https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.rbf_kernel.html .. [4] G. Gentinetta, A. Thomsen, D. Sutter, and S. Woerner, 'The complexity of quantum support vector machines', arXiv, arXiv:2203.00031, Feb. 2022. doi: 10.48550/arXiv.2203.00031 .. [5] S. Shalev-Shwartz, Y. Singer, and A. Cotter, 'Pegasos: Primal Estimated sub-GrAdient SOlver for SVM' """
[docs] def __init__( self, gamma="scale", C=1.0, max_iter=None, pegasos=False, quantum=True, q_account_token=None, verbose=True, shots=1024, gen_feature_map=gen_zz_feature_map(), seed=None, use_fidelity_state_vector_kernel=True, use_qiskit_symb=True, n_jobs=4, ): QuanticClassifierBase.__init__( self, quantum, q_account_token, verbose, shots, gen_feature_map, seed ) self.gamma = gamma self.C = C self.max_iter = max_iter self.pegasos = pegasos self.use_fidelity_state_vector_kernel = use_fidelity_state_vector_kernel self.n_jobs = n_jobs self.use_qiskit_symb = use_qiskit_symb
def _init_algo(self, n_features): self._log("SVM initiating algorithm") if self.quantum: quantum_kernel = get_quantum_kernel( self._feature_map, self.gen_feature_map, self._quantum_instance, self.use_fidelity_state_vector_kernel, self.use_qiskit_symb and not self.pegasos, self.n_jobs, ) if self.pegasos: self._log("[Warning] `gamma` is not supported by PegasosQSVC") num_steps = 1000 if self.max_iter is None else self.max_iter classifier = PegasosQSVC( quantum_kernel=quantum_kernel, C=self.C, num_steps=num_steps ) else: max_iter = -1 if self.max_iter is None else self.max_iter classifier = QSVC( quantum_kernel=quantum_kernel, gamma=self.gamma, C=self.C, max_iter=max_iter, probability=True, ) else: max_iter = -1 if self.max_iter is None else self.max_iter classifier = SVC( gamma=self.gamma, C=self.C, max_iter=max_iter, probability=True ) return classifier def predict(self, X): """Predict class labels for samples in X. Parameters ---------- X : ndarray, shape (n_samples, n_features) Test samples. Returns ------- y_pred : ndarray, shape (n_samples,) Predicted class labels. """ if isinstance(self._classifier, QSVC): probs = softmax(self.predict_proba(X)) labels = [np.argmax(prob) for prob in probs] else: labels = self._predict(X) self._log("Prediction finished.") return self._map_indices_to_classes(labels)