From f55a374f6d169bd7513108701874973f58b1a2d3 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Wed, 23 Mar 2022 11:01:02 +0100 Subject: [PATCH 01/14] the 3 files --- .../benchmarks/Leo_base_benchmark.py | 98 ++++++++++++ machine_learning/benchmarks/Leo_benchmark.py | 144 ++++++++++++++++++ .../benchmarks/Leo_fit_benchmark.py | 104 +++++++++++++ 3 files changed, 346 insertions(+) create mode 100644 machine_learning/benchmarks/Leo_base_benchmark.py create mode 100644 machine_learning/benchmarks/Leo_benchmark.py create mode 100644 machine_learning/benchmarks/Leo_fit_benchmark.py diff --git a/machine_learning/benchmarks/Leo_base_benchmark.py b/machine_learning/benchmarks/Leo_base_benchmark.py new file mode 100644 index 00000000..8f64aa6a --- /dev/null +++ b/machine_learning/benchmarks/Leo_base_benchmark.py @@ -0,0 +1,98 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2022. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +"""Base class for QuantumKernel and QuantumKernelTraining based classifier benchmarks.""" +from abc import ABC +from typing import Optional + +from qiskit.algorithms.optimizers import Optimizer +from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap +from qiskit.utils import algorithm_globals +from qiskit_machine_learning.kernels import QuantumKernel +from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer +from qiskit_machine_learning.algorithms import QSVC +from sklearn.pipeline import Pipeline +from sklearn.preprocessing import OneHotEncoder, FunctionTransformer +from qiskit import QuantumCircuit +from qiskit.circuit import ParameterVector +import numpy as np + +from .base_classifier_benchmark import BaseClassifierBenchmark + + +class QKernelBaseClassifierBenchmark(BaseClassifierBenchmark, ABC): + """Base class for quantum kernel benchmarks.""" + + def __init__(self) -> None: + reshaper = FunctionTransformer(lambda x: x.reshape(-1, 1)) + encoder = OneHotEncoder(sparse=False) + super().__init__( + synthetic_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]), + iris_num_classes=2, + iris_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]), + ) + + #I just build 1 function for method, I don't want to differentiate datasets + def _construct_QuantumKernel_classical_classifier(self, + quantum_instance_name: str, + optimizer: Optional[Optimizer] = None, + method = "quantumclassical", #do not modify + num_qubits = 1, ) -> QuantumKernel: + """This method just create the matrix from the quantum kernel. Later will be applied the classical SVC""" + kernelmatrix = self._construct_QuantumKernel(num_qubits, quantum_instance_name, method) + #put here the function calling the quantum kernel matrix (Quantum Kernel) + return kernelmatrix + + def _construct_QuantumKernelTrainer(self, + quantum_instance_name: str, + optimizer: Optional[Optimizer] = None, + loss_function: str = None, + method = "quantum", #do not modify + num_qubits = 1,) -> QuantumKernelTrainer: + """This method returns the QuantumKernelTrainer""" + kernel = self._construct_QuantumKernel(num_qubits, quantum_instance_name, method) + optimizer = optimizer #eg L_BFGS_B(maxiter=20) but we need also learning rate, perturbation etc. + # Instantiate a quantum kernel trainer. + #look up how to put random initial parameters, seems simple just check + qkt = QuantumKernelTrainer(quantum_kernel=kernel, loss=loss_function, optimizer = optimizer, initial_point=[np.pi / 2]) #initial random point + return qkt #use the QuantumKernel to return the classifier method + + def _construct_QuantumKernel( + self, + num_inputs: int, + quantum_instance_name: str, + method: str, + optimizer: Optional[Optimizer] = None + ) -> QuantumKernel: + """Construct a QuantumKernel""" + #here we can consider to add functions to be called for the kind of ansatz + # or the ansatz as input here whatever + #we should also personalize the parameters in the quantum method + if method == "quantumclassical": + feature_map = ZZFeatureMap(num_inputs, reps=2, entanglement="linear") + #quantum kernel, not parametrized + qk = QuantumKernel(feature_map=feature_map, quantum_instance=self.backends[quantum_instance_name]) + return qk + elif method == "quantum": + #super dumb parametrized start + #<<<<<<<<<<<<<<<<< any number of qubits + user_params = ParameterVector("θ", 1) + fm0 = QuantumCircuit(num_inputs) + for i in range(num_inputs): + fm0.ry(user_params[0], i) + fm1 = ZZFeatureMap(num_inputs, reps=2, entanglement="linear") + feature_map = fm0.compose(fm1) + #quantum kernel, parametrized + qk = QuantumKernel(feature_map = feature_map, user_parameters=user_params, quantum_instance=self.backends[quantum_instance_name]) + return qk + else: + return ValueError(f"Unsupported method: {method}") diff --git a/machine_learning/benchmarks/Leo_benchmark.py b/machine_learning/benchmarks/Leo_benchmark.py new file mode 100644 index 00000000..37f8abc9 --- /dev/null +++ b/machine_learning/benchmarks/Leo_benchmark.py @@ -0,0 +1,144 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2021, 2022. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +"""QuantumKernel and QuantumKernelTraining benchmarks.""" +import pickle +from itertools import product +from timeit import timeit +from typing import Optional, Union +from qiskit_machine_learning.kernels import QuantumKernel +from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer +import numpy as np +from qiskit.algorithms.optimizers import COBYLA +#from qiskit_machine_learning.algorithms import NeuralNetworkClassifier +from qiskit_machine_learning.algorithms import QSVC +from sklearn.metrics import precision_score, recall_score, f1_score +from sympy import evaluate + +from .base_classifier_benchmark import DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION +from .Leo_base_benchmark import QKernelBaseClassifierBenchmark + +class QKernelBenchmarks(QKernelBaseClassifierBenchmark): + """Quantum Kernel Classifier (q&svm or qkt) benchmarks.""" + version = 1 + timeout = 1200.0 + params = [ + # Only the synthetic dataset now (I'm following vqc) just data import + [DATASET_SYNTHETIC_CLASSIFICATION], + ["qasm_simulator", "statevector_simulator"], + ["QuantumKernel", "QuantumKernelTraining" ] + ] + param_names = ["dataset", "backend", "technique"] + + def __init__(self) -> None: + super().__init__() + self.train_features: Optional[np.ndarray] = None + self.train_labels: Optional[np.ndarray] = None + self.test_features: Optional[np.ndarray] = None + self.test_labels: Optional[np.ndarray] = None + self.model: Optional[Union[QuantumKernel, QuantumKernelTrainer]] = None #ask here model is declared, and called through setup + + def setup(self, dataset: str, technique: str, quantum_instance_name: str) -> None: + """Set up the benchmark.""" + self.train_features = self.datasets[dataset]["train_features"] + self.train_labels = self.datasets[dataset]["train_labels"] + self.test_features = self.datasets[dataset]["test_features"] + self.test_labels = self.datasets[dataset]["test_labels"] + #here I don't care about dataset, I just put the "num_qubits" in _construct_Q...() + #I need to test but I bet is self.train_feature.shape[1] rofl + n_qubits = self.train_features.shape[1] + if technique == "QuantumKernel": + self.model = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= quantum_instance_name, + num_qubits = n_qubits) #this is just a kernel matrix + elif technique == "QuantumKernelTraining": + self.model = self._construct_QuantumKernelTrainer(quantum_instance_name= quantum_instance_name, + num_qubits = n_qubits) #this is a classifier + else: + raise ValueError(f"Unsupported technique: {technique}") + file_name = f"qk_{technique}_{dataset}_{quantum_instance_name}.pickle" + with open(file_name, "rb") as file: + self.result = pickle.load(file) #model._fit_result <<<<<<<<<<<<<<<<<<<<<<<<<< + ############# + def setup_cache(self) -> None: + """Cache qk&svm or qkt fitted model.""" + for dataset, backend, technique in product(*self.params): + train_features = self.datasets[dataset]["train_features"] + train_labels = self.datasets[dataset]["train_labels"] + #for now I put only 1 optimizer as they do, but this is fishy + n_qubits = train_features.shape[1] + if dataset != DATASET_SYNTHETIC_CLASSIFICATION & dataset != DATASET_IRIS_CLASSIFICATION: + raise ValueError(f"Unsupported dataset: {dataset}") + #create model based on params + #for now I directly create the classifier (so add svc in the quantum kernel method) + if technique == "QuantumKernel": + _kernel = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= backend, + optimizer = COBYLA(maxiter=200), + num_qubits = n_qubits) + model = QSVC(kernel = _kernel.evaluate) + elif technique == "QuantumKernelTraining": + model = self._construct_QuantumKernelTrainer(quantum_instance_name= backend, + optimizer=COBYLA(maxiter=200), + num_qubits = n_qubits ) + else: + ValueError(f"Unsupported technique: {technique}") + result = model.fit(train_features, train_labels) + file_name = f"qk_{technique}_{dataset}_{backend}.pickle" + with open(file_name, "wb") as file: + pickle.dump(result, file) ###### <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< this line is a mistery still + + # pylint: disable=invalid-name + def time_score_vqc_classifier(self, _, __): + """Time scoring VQC on data.""" + self.model.score(self.train_features, self.train_labels) + + def time_predict_vqc_classifier(self, _, __): + """Time predicting with VQC.""" + self.model.predict(self.train_features) + + def track_accuracy_score_vqc_classifier(self, _, __): + """Tracks the overall accuracy of the classification results.""" + return self.model.score(self.test_features, self.test_labels) + + def track_precision_score_vqc_classifier(self, _, __): + """Tracks the precision score.""" + predicts = self.model.predict(self.test_features) + return precision_score(y_true=self.test_labels, y_pred=predicts, average="micro") + + def track_recall_score_vqc_classifier(self, _, __): + """Tracks the recall score for each class of the classification results.""" + predicts = self.model.predict(self.test_features) + return recall_score(y_true=self.test_labels, y_pred=predicts, average="micro") + + def track_f1_score_vqc_classifier(self, _, __): + """Tracks the f1 score for each class of the classification results.""" + predicts = self.model.predict(self.test_features) + return f1_score(y_true=self.test_labels, y_pred=predicts, average="micro") + +if __name__ == "__main__": + bench = QKernelBenchmarks() + bench.setup_cache() + for dataset_name, backend_name, technique_name in product(*QKernelBenchmarks.params): + try: + bench.setup(dataset_name, technique_name, backend_name) + except NotImplementedError: + continue + + for method in ( + "time_score_vqc_classifier", + "time_predict_vqc_classifier", + "track_accuracy_score_vqc_classifier", + "track_precision_score_vqc_classifier", + "track_recall_score_vqc_classifier", + "track_f1_score_vqc_classifier", + ): + elapsed = timeit( + f'bench.{method}("{dataset_name}", "{backend_name}")', number=10, globals=globals() + ) #for now I leave the args but then take them out diff --git a/machine_learning/benchmarks/Leo_fit_benchmark.py b/machine_learning/benchmarks/Leo_fit_benchmark.py new file mode 100644 index 00000000..f11e1a7c --- /dev/null +++ b/machine_learning/benchmarks/Leo_fit_benchmark.py @@ -0,0 +1,104 @@ +# This code is part of Qiskit. +# +# (C) Copyright IBM 2021, 2022. +# +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. +"""Variational Quantum Classifier benchmarks.""" + +from itertools import product +from timeit import timeit +from typing import Optional, Union + +import numpy as np +from qiskit.algorithms.optimizers import COBYLA, L_BFGS_B, NELDER_MEAD +#from qiskit_machine_learning.algorithms import NeuralNetworkClassifier + +from .base_classifier_benchmark import DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION +from qiskit_machine_learning.kernels import QuantumKernel +from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer +from qiskit_machine_learning.algorithms import QSVC + +from .Leo_base_benchmark import QKernelBaseClassifierBenchmark + + +class QKernelFitBenchmarks(QKernelBaseClassifierBenchmark): + """QuantumKernel and QuantumKernelTraining fit benchmarks.""" + + version = 2 + timeout = 1200.0 + params = ( + # Only the synthetic dataset now + [DATASET_SYNTHETIC_CLASSIFICATION], + ["qasm_simulator", "statevector_simulator"], + ["QuantumKernel", "QuantumKernelTraining" ], + ["cobyla", "nelder-mead", "l-bfgs-b"], + ["cross_entropy", "squared_error"], + ) + param_names = ["dataset", "backend name", "technique", "optimizer", "loss function"] + + def __init__(self) -> None: + super().__init__() + + self.optimizers = { + "cobyla": COBYLA(maxiter=100), + "nelder-mead": NELDER_MEAD(maxiter=50), + "l-bfgs-b": L_BFGS_B(maxiter=20), + } + self.train_features: Optional[np.ndarray] = None + self.train_labels: Optional[np.ndarray] = None + self.test_features: Optional[np.ndarray] = None + self.test_labels: Optional[np.ndarray] = None + self.model: Optional[Union[QuantumKernel, QuantumKernelTrainer]] = None + + def setup( + self, dataset: str, technique: str, quantum_instance_name: str, optimizer: str, loss_function: str + ) -> None: + """Set up the benchmark.""" + self.train_features = self.datasets[dataset]["train_features"] + self.train_labels = self.datasets[dataset]["train_labels"] + #new + n_qubits = self.train_features.shape[1] + if technique == "QuantumKernel": + self.model = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= quantum_instance_name, optimizer = optimizer, + num_qubits = n_qubits) #this is just a kernel matrix + elif technique == "QuantumKernelTraining": + self.model = self._construct_QuantumKernelTrainer(quantum_instance_name= quantum_instance_name, optimizer= optimizer, + num_qubits = n_qubits, + ) #this is a classifier + else: + raise ValueError(f"Unsupported technique: {technique}") + + + # pylint: disable=invalid-name + def time_fit_vqc(self, technique, _, __, ___, ____): + """Time fitting VQC to data.""" + if technique == "QuantumKernel": + self.model = QSVC(kernel = self.model.evaluate) + #fit + self.model.fit(self.train_features, self.train_labels) + + +if __name__ == "__main__": + for dataset_name, backend_name, technique, optimizer_name, loss_function_name in product( + *QKernelFitBenchmarks.params + ): + bench = QKernelFitBenchmarks() + try: + bench.setup(dataset_name, technique, backend_name, optimizer_name, loss_function_name) + except NotImplementedError: + continue + for method in ["time_fit_vqc"]: + elapsed = timeit( + f'bench.{method}("{technique}", "{dataset_name}", "{backend_name}", ' + f'"{optimizer_name}", "{loss_function_name}")', + number=10, + globals=globals(), + ) + print(f"{method}:\t{elapsed}") + # take out args in case it works \ No newline at end of file From 47a3ffcec51dac9fa0f86a507de8c899b522fbd8 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Wed, 23 Mar 2022 11:07:23 +0100 Subject: [PATCH 02/14] add benchmarks quantum kernel/QKT --- .../benchmarks/{Leo_base_benchmark.py => qk_base_benchmark.py} | 0 .../benchmarks/{Leo_benchmark.py => qk_benchmark.py} | 2 +- .../benchmarks/{Leo_fit_benchmark.py => qk_fit_benchmark.py} | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename machine_learning/benchmarks/{Leo_base_benchmark.py => qk_base_benchmark.py} (100%) rename machine_learning/benchmarks/{Leo_benchmark.py => qk_benchmark.py} (99%) rename machine_learning/benchmarks/{Leo_fit_benchmark.py => qk_fit_benchmark.py} (98%) diff --git a/machine_learning/benchmarks/Leo_base_benchmark.py b/machine_learning/benchmarks/qk_base_benchmark.py similarity index 100% rename from machine_learning/benchmarks/Leo_base_benchmark.py rename to machine_learning/benchmarks/qk_base_benchmark.py diff --git a/machine_learning/benchmarks/Leo_benchmark.py b/machine_learning/benchmarks/qk_benchmark.py similarity index 99% rename from machine_learning/benchmarks/Leo_benchmark.py rename to machine_learning/benchmarks/qk_benchmark.py index 37f8abc9..34beccab 100644 --- a/machine_learning/benchmarks/Leo_benchmark.py +++ b/machine_learning/benchmarks/qk_benchmark.py @@ -24,7 +24,7 @@ from sympy import evaluate from .base_classifier_benchmark import DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION -from .Leo_base_benchmark import QKernelBaseClassifierBenchmark +from .qk_base_benchmark import QKernelBaseClassifierBenchmark class QKernelBenchmarks(QKernelBaseClassifierBenchmark): """Quantum Kernel Classifier (q&svm or qkt) benchmarks.""" diff --git a/machine_learning/benchmarks/Leo_fit_benchmark.py b/machine_learning/benchmarks/qk_fit_benchmark.py similarity index 98% rename from machine_learning/benchmarks/Leo_fit_benchmark.py rename to machine_learning/benchmarks/qk_fit_benchmark.py index f11e1a7c..ba169442 100644 --- a/machine_learning/benchmarks/Leo_fit_benchmark.py +++ b/machine_learning/benchmarks/qk_fit_benchmark.py @@ -24,7 +24,7 @@ from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer from qiskit_machine_learning.algorithms import QSVC -from .Leo_base_benchmark import QKernelBaseClassifierBenchmark +from .qk_base_benchmark import QKernelBaseClassifierBenchmark class QKernelFitBenchmarks(QKernelBaseClassifierBenchmark): From d50db30333f9b945e5ae088c02eb33f67ed50d18 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Mon, 11 Apr 2022 19:07:42 +0200 Subject: [PATCH 03/14] Maybe fixed errors? --- .../benchmarks/qk_base_benchmark.py | 4 +-- machine_learning/benchmarks/qk_benchmark.py | 24 +++++++-------- .../benchmarks/qk_fit_benchmark.py | 29 ++++++++++++------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/machine_learning/benchmarks/qk_base_benchmark.py b/machine_learning/benchmarks/qk_base_benchmark.py index 8f64aa6a..4fd3c74b 100644 --- a/machine_learning/benchmarks/qk_base_benchmark.py +++ b/machine_learning/benchmarks/qk_base_benchmark.py @@ -15,8 +15,7 @@ from typing import Optional from qiskit.algorithms.optimizers import Optimizer -from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap -from qiskit.utils import algorithm_globals +from qiskit.circuit.library import ZZFeatureMap from qiskit_machine_learning.kernels import QuantumKernel from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer from qiskit_machine_learning.algorithms import QSVC @@ -71,7 +70,6 @@ def _construct_QuantumKernel( num_inputs: int, quantum_instance_name: str, method: str, - optimizer: Optional[Optimizer] = None ) -> QuantumKernel: """Construct a QuantumKernel""" #here we can consider to add functions to be called for the kind of ansatz diff --git a/machine_learning/benchmarks/qk_benchmark.py b/machine_learning/benchmarks/qk_benchmark.py index 34beccab..0028e0d2 100644 --- a/machine_learning/benchmarks/qk_benchmark.py +++ b/machine_learning/benchmarks/qk_benchmark.py @@ -44,7 +44,7 @@ def __init__(self) -> None: self.train_labels: Optional[np.ndarray] = None self.test_features: Optional[np.ndarray] = None self.test_labels: Optional[np.ndarray] = None - self.model: Optional[Union[QuantumKernel, QuantumKernelTrainer]] = None #ask here model is declared, and called through setup + self.model: Optional[Union[QuantumKernel, QuantumKernelTrainer]] = None def setup(self, dataset: str, technique: str, quantum_instance_name: str) -> None: """Set up the benchmark.""" @@ -52,8 +52,6 @@ def setup(self, dataset: str, technique: str, quantum_instance_name: str) -> Non self.train_labels = self.datasets[dataset]["train_labels"] self.test_features = self.datasets[dataset]["test_features"] self.test_labels = self.datasets[dataset]["test_labels"] - #here I don't care about dataset, I just put the "num_qubits" in _construct_Q...() - #I need to test but I bet is self.train_feature.shape[1] rofl n_qubits = self.train_features.shape[1] if technique == "QuantumKernel": self.model = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= quantum_instance_name, @@ -65,8 +63,8 @@ def setup(self, dataset: str, technique: str, quantum_instance_name: str) -> Non raise ValueError(f"Unsupported technique: {technique}") file_name = f"qk_{technique}_{dataset}_{quantum_instance_name}.pickle" with open(file_name, "rb") as file: - self.result = pickle.load(file) #model._fit_result <<<<<<<<<<<<<<<<<<<<<<<<<< - ############# + self.result = pickle.load(file) + def setup_cache(self) -> None: """Cache qk&svm or qkt fitted model.""" for dataset, backend, technique in product(*self.params): @@ -82,7 +80,7 @@ def setup_cache(self) -> None: _kernel = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= backend, optimizer = COBYLA(maxiter=200), num_qubits = n_qubits) - model = QSVC(kernel = _kernel.evaluate) + model = _kernel #QSVC(kernel = _kernel.evaluate) elif technique == "QuantumKernelTraining": model = self._construct_QuantumKernelTrainer(quantum_instance_name= backend, optimizer=COBYLA(maxiter=200), @@ -92,34 +90,34 @@ def setup_cache(self) -> None: result = model.fit(train_features, train_labels) file_name = f"qk_{technique}_{dataset}_{backend}.pickle" with open(file_name, "wb") as file: - pickle.dump(result, file) ###### <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< this line is a mistery still + pickle.dump(result, file) # pylint: disable=invalid-name def time_score_vqc_classifier(self, _, __): """Time scoring VQC on data.""" - self.model.score(self.train_features, self.train_labels) + QSVC(kernel = self.model).score(self.train_features, self.train_labels) def time_predict_vqc_classifier(self, _, __): """Time predicting with VQC.""" - self.model.predict(self.train_features) + QSVC(kernel = self.model).predict(self.train_features) def track_accuracy_score_vqc_classifier(self, _, __): """Tracks the overall accuracy of the classification results.""" - return self.model.score(self.test_features, self.test_labels) + return QSVC(kernel = self.model).score(self.test_features, self.test_labels) def track_precision_score_vqc_classifier(self, _, __): """Tracks the precision score.""" - predicts = self.model.predict(self.test_features) + predicts = QSVC(kernel = self.model).predict(self.test_features) return precision_score(y_true=self.test_labels, y_pred=predicts, average="micro") def track_recall_score_vqc_classifier(self, _, __): """Tracks the recall score for each class of the classification results.""" - predicts = self.model.predict(self.test_features) + predicts = QSVC(kernel = self.model).predict(self.test_features) return recall_score(y_true=self.test_labels, y_pred=predicts, average="micro") def track_f1_score_vqc_classifier(self, _, __): """Tracks the f1 score for each class of the classification results.""" - predicts = self.model.predict(self.test_features) + predicts = QSVC(kernel = self.model).predict(self.test_features) return f1_score(y_true=self.test_labels, y_pred=predicts, average="micro") if __name__ == "__main__": diff --git a/machine_learning/benchmarks/qk_fit_benchmark.py b/machine_learning/benchmarks/qk_fit_benchmark.py index ba169442..ff69c34c 100644 --- a/machine_learning/benchmarks/qk_fit_benchmark.py +++ b/machine_learning/benchmarks/qk_fit_benchmark.py @@ -17,12 +17,15 @@ import numpy as np from qiskit.algorithms.optimizers import COBYLA, L_BFGS_B, NELDER_MEAD +from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer +from qiskit_machine_learning.kernels import QuantumKernel +from qiskit_machine_learning.algorithms import QSVC #from qiskit_machine_learning.algorithms import NeuralNetworkClassifier from .base_classifier_benchmark import DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION -from qiskit_machine_learning.kernels import QuantumKernel -from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer -from qiskit_machine_learning.algorithms import QSVC + + + from .qk_base_benchmark import QKernelBaseClassifierBenchmark @@ -34,7 +37,7 @@ class QKernelFitBenchmarks(QKernelBaseClassifierBenchmark): timeout = 1200.0 params = ( # Only the synthetic dataset now - [DATASET_SYNTHETIC_CLASSIFICATION], + [DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION], ["qasm_simulator", "statevector_simulator"], ["QuantumKernel", "QuantumKernelTraining" ], ["cobyla", "nelder-mead", "l-bfgs-b"], @@ -57,7 +60,12 @@ def __init__(self) -> None: self.model: Optional[Union[QuantumKernel, QuantumKernelTrainer]] = None def setup( - self, dataset: str, technique: str, quantum_instance_name: str, optimizer: str, loss_function: str + self, + dataset: str, + technique: str, + quantum_instance_name: str, + optimizer: str, + loss_function: str ) -> None: """Set up the benchmark.""" self.train_features = self.datasets[dataset]["train_features"] @@ -65,16 +73,18 @@ def setup( #new n_qubits = self.train_features.shape[1] if technique == "QuantumKernel": - self.model = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= quantum_instance_name, optimizer = optimizer, + self.model = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= quantum_instance_name, + optimizer = optimizer, num_qubits = n_qubits) #this is just a kernel matrix elif technique == "QuantumKernelTraining": - self.model = self._construct_QuantumKernelTrainer(quantum_instance_name= quantum_instance_name, optimizer= optimizer, + self.model = self._construct_QuantumKernelTrainer(quantum_instance_name= quantum_instance_name, + optimizer= optimizer, + loss_function = loss_function, num_qubits = n_qubits, ) #this is a classifier else: raise ValueError(f"Unsupported technique: {technique}") - # pylint: disable=invalid-name def time_fit_vqc(self, technique, _, __, ___, ____): """Time fitting VQC to data.""" @@ -83,7 +93,6 @@ def time_fit_vqc(self, technique, _, __, ___, ____): #fit self.model.fit(self.train_features, self.train_labels) - if __name__ == "__main__": for dataset_name, backend_name, technique, optimizer_name, loss_function_name in product( *QKernelFitBenchmarks.params @@ -101,4 +110,4 @@ def time_fit_vqc(self, technique, _, __, ___, ____): globals=globals(), ) print(f"{method}:\t{elapsed}") - # take out args in case it works \ No newline at end of file + # take out args in case it works From bd1a015838b50921d437ec34e27664ecb46e3726 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Wed, 11 May 2022 16:29:20 +0900 Subject: [PATCH 04/14] changes on codes and syntac, bug found maybe is solved, probably not but progress --- .../benchmarks/qk_base_benchmark.py | 38 ++++++++----------- machine_learning/benchmarks/qk_benchmark.py | 25 +++++------- .../benchmarks/qk_fit_benchmark.py | 37 +++++++++--------- 3 files changed, 43 insertions(+), 57 deletions(-) diff --git a/machine_learning/benchmarks/qk_base_benchmark.py b/machine_learning/benchmarks/qk_base_benchmark.py index 4fd3c74b..fcb47221 100644 --- a/machine_learning/benchmarks/qk_base_benchmark.py +++ b/machine_learning/benchmarks/qk_base_benchmark.py @@ -40,30 +40,28 @@ def __init__(self) -> None: iris_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]), ) - #I just build 1 function for method, I don't want to differentiate datasets def _construct_QuantumKernel_classical_classifier(self, quantum_instance_name: str, optimizer: Optional[Optimizer] = None, - method = "quantumclassical", #do not modify + method = "quantumclassical", num_qubits = 1, ) -> QuantumKernel: - """This method just create the matrix from the quantum kernel. Later will be applied the classical SVC""" - kernelmatrix = self._construct_QuantumKernel(num_qubits, quantum_instance_name, method) - #put here the function calling the quantum kernel matrix (Quantum Kernel) + """This method just create the matrix from the quantum kernel""" + kernelmatrix = self._construct_QuantumKernel(num_qubits, + quantum_instance_name, method) return kernelmatrix def _construct_QuantumKernelTrainer(self, quantum_instance_name: str, optimizer: Optional[Optimizer] = None, loss_function: str = None, - method = "quantum", #do not modify + method = "quantum", num_qubits = 1,) -> QuantumKernelTrainer: """This method returns the QuantumKernelTrainer""" kernel = self._construct_QuantumKernel(num_qubits, quantum_instance_name, method) - optimizer = optimizer #eg L_BFGS_B(maxiter=20) but we need also learning rate, perturbation etc. - # Instantiate a quantum kernel trainer. - #look up how to put random initial parameters, seems simple just check - qkt = QuantumKernelTrainer(quantum_kernel=kernel, loss=loss_function, optimizer = optimizer, initial_point=[np.pi / 2]) #initial random point - return qkt #use the QuantumKernel to return the classifier method + optimizer = optimizer + qkt = QuantumKernelTrainer(quantum_kernel=kernel, loss=loss_function, + optimizer = optimizer, initial_point=[np.pi / 2]) + return qkt def _construct_QuantumKernel( self, @@ -72,25 +70,21 @@ def _construct_QuantumKernel( method: str, ) -> QuantumKernel: """Construct a QuantumKernel""" - #here we can consider to add functions to be called for the kind of ansatz - # or the ansatz as input here whatever - #we should also personalize the parameters in the quantum method if method == "quantumclassical": feature_map = ZZFeatureMap(num_inputs, reps=2, entanglement="linear") - #quantum kernel, not parametrized - qk = QuantumKernel(feature_map=feature_map, quantum_instance=self.backends[quantum_instance_name]) - return qk + qkernel = QuantumKernel(feature_map=feature_map, + quantum_instance=self.backends[quantum_instance_name]) + return qkernel elif method == "quantum": - #super dumb parametrized start - #<<<<<<<<<<<<<<<<< any number of qubits user_params = ParameterVector("θ", 1) fm0 = QuantumCircuit(num_inputs) for i in range(num_inputs): fm0.ry(user_params[0], i) fm1 = ZZFeatureMap(num_inputs, reps=2, entanglement="linear") feature_map = fm0.compose(fm1) - #quantum kernel, parametrized - qk = QuantumKernel(feature_map = feature_map, user_parameters=user_params, quantum_instance=self.backends[quantum_instance_name]) - return qk + qkernel = QuantumKernel(feature_map = feature_map, + user_parameters=user_params, + quantum_instance=self.backends[quantum_instance_name]) + return qkernel else: return ValueError(f"Unsupported method: {method}") diff --git a/machine_learning/benchmarks/qk_benchmark.py b/machine_learning/benchmarks/qk_benchmark.py index 0028e0d2..6c710199 100644 --- a/machine_learning/benchmarks/qk_benchmark.py +++ b/machine_learning/benchmarks/qk_benchmark.py @@ -18,7 +18,6 @@ from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer import numpy as np from qiskit.algorithms.optimizers import COBYLA -#from qiskit_machine_learning.algorithms import NeuralNetworkClassifier from qiskit_machine_learning.algorithms import QSVC from sklearn.metrics import precision_score, recall_score, f1_score from sympy import evaluate @@ -31,8 +30,7 @@ class QKernelBenchmarks(QKernelBaseClassifierBenchmark): version = 1 timeout = 1200.0 params = [ - # Only the synthetic dataset now (I'm following vqc) just data import - [DATASET_SYNTHETIC_CLASSIFICATION], + [DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION], ["qasm_simulator", "statevector_simulator"], ["QuantumKernel", "QuantumKernelTraining" ] ] @@ -54,11 +52,11 @@ def setup(self, dataset: str, technique: str, quantum_instance_name: str) -> Non self.test_labels = self.datasets[dataset]["test_labels"] n_qubits = self.train_features.shape[1] if technique == "QuantumKernel": - self.model = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= quantum_instance_name, - num_qubits = n_qubits) #this is just a kernel matrix + self.model = self._construct_QuantumKernel_classical_classifier(quantum_instance_name = quantum_instance_name, + num_qubits = n_qubits) elif technique == "QuantumKernelTraining": self.model = self._construct_QuantumKernelTrainer(quantum_instance_name= quantum_instance_name, - num_qubits = n_qubits) #this is a classifier + num_qubits = n_qubits) else: raise ValueError(f"Unsupported technique: {technique}") file_name = f"qk_{technique}_{dataset}_{quantum_instance_name}.pickle" @@ -70,21 +68,18 @@ def setup_cache(self) -> None: for dataset, backend, technique in product(*self.params): train_features = self.datasets[dataset]["train_features"] train_labels = self.datasets[dataset]["train_labels"] - #for now I put only 1 optimizer as they do, but this is fishy n_qubits = train_features.shape[1] if dataset != DATASET_SYNTHETIC_CLASSIFICATION & dataset != DATASET_IRIS_CLASSIFICATION: raise ValueError(f"Unsupported dataset: {dataset}") - #create model based on params - #for now I directly create the classifier (so add svc in the quantum kernel method) if technique == "QuantumKernel": _kernel = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= backend, - optimizer = COBYLA(maxiter=200), - num_qubits = n_qubits) - model = _kernel #QSVC(kernel = _kernel.evaluate) + optimizer = COBYLA(maxiter=200), + num_qubits = n_qubits) + model = _kernel elif technique == "QuantumKernelTraining": model = self._construct_QuantumKernelTrainer(quantum_instance_name= backend, - optimizer=COBYLA(maxiter=200), - num_qubits = n_qubits ) + optimizer=COBYLA(maxiter=200), + num_qubits = n_qubits ) else: ValueError(f"Unsupported technique: {technique}") result = model.fit(train_features, train_labels) @@ -139,4 +134,4 @@ def track_f1_score_vqc_classifier(self, _, __): ): elapsed = timeit( f'bench.{method}("{dataset_name}", "{backend_name}")', number=10, globals=globals() - ) #for now I leave the args but then take them out + ) diff --git a/machine_learning/benchmarks/qk_fit_benchmark.py b/machine_learning/benchmarks/qk_fit_benchmark.py index ff69c34c..5b53e995 100644 --- a/machine_learning/benchmarks/qk_fit_benchmark.py +++ b/machine_learning/benchmarks/qk_fit_benchmark.py @@ -20,29 +20,24 @@ from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer from qiskit_machine_learning.kernels import QuantumKernel from qiskit_machine_learning.algorithms import QSVC -#from qiskit_machine_learning.algorithms import NeuralNetworkClassifier - -from .base_classifier_benchmark import DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION - +from .base_classifier_benchmark import DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION from .qk_base_benchmark import QKernelBaseClassifierBenchmark - class QKernelFitBenchmarks(QKernelBaseClassifierBenchmark): """QuantumKernel and QuantumKernelTraining fit benchmarks.""" version = 2 timeout = 1200.0 - params = ( - # Only the synthetic dataset now + params = [ [DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION], ["qasm_simulator", "statevector_simulator"], - ["QuantumKernel", "QuantumKernelTraining" ], + ["QuantumKernel", "QuantumKernelTraining" ], ["cobyla", "nelder-mead", "l-bfgs-b"], ["cross_entropy", "squared_error"], - ) + ] param_names = ["dataset", "backend name", "technique", "optimizer", "loss function"] def __init__(self) -> None: @@ -65,7 +60,7 @@ def setup( technique: str, quantum_instance_name: str, optimizer: str, - loss_function: str + loss_function: str, ) -> None: """Set up the benchmark.""" self.train_features = self.datasets[dataset]["train_features"] @@ -73,15 +68,17 @@ def setup( #new n_qubits = self.train_features.shape[1] if technique == "QuantumKernel": - self.model = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= quantum_instance_name, - optimizer = optimizer, - num_qubits = n_qubits) #this is just a kernel matrix + self.model = self._construct_QuantumKernel_classical_classifier( + quantum_instance_name= quantum_instance_name, + optimizer = optimizer, + num_qubits = n_qubits) elif technique == "QuantumKernelTraining": - self.model = self._construct_QuantumKernelTrainer(quantum_instance_name= quantum_instance_name, - optimizer= optimizer, - loss_function = loss_function, - num_qubits = n_qubits, - ) #this is a classifier + self.model = self._construct_QuantumKernelTrainer( + quantum_instance_name= quantum_instance_name, + optimizer= optimizer, + loss_function = loss_function, + num_qubits = n_qubits, + ) else: raise ValueError(f"Unsupported technique: {technique}") @@ -99,7 +96,8 @@ def time_fit_vqc(self, technique, _, __, ___, ____): ): bench = QKernelFitBenchmarks() try: - bench.setup(dataset_name, technique, backend_name, optimizer_name, loss_function_name) + bench.setup(dataset_name, technique, backend_name, + optimizer_name, loss_function_name) except NotImplementedError: continue for method in ["time_fit_vqc"]: @@ -110,4 +108,3 @@ def time_fit_vqc(self, technique, _, __, ___, ____): globals=globals(), ) print(f"{method}:\t{elapsed}") - # take out args in case it works From e8a4dca46f1ccb27937ddc94e1251d7b2eb72910 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Tue, 17 May 2022 13:55:16 +0900 Subject: [PATCH 05/14] running locally --- asv.conf.json | 184 +++++++++++++++++++++++++++++++++++++++ benchmarks/__init__.py | 1 + benchmarks/benchmarks.py | 31 +++++++ 3 files changed, 216 insertions(+) create mode 100644 asv.conf.json create mode 100644 benchmarks/__init__.py create mode 100644 benchmarks/benchmarks.py diff --git a/asv.conf.json b/asv.conf.json new file mode 100644 index 00000000..8ca9d50a --- /dev/null +++ b/asv.conf.json @@ -0,0 +1,184 @@ +{ + // The version of the config file format. Do not change, unless + // you know what you are doing. + "version": 1, + + // The name of the project being benchmarked + "project": "project", + + // The project's homepage + "project_url": "http://project-homepage.org/", + + // The URL or local path of the source code repository for the + // project being benchmarked + "repo": ".", + + // The Python project's subdirectory in your repo. If missing or + // the empty string, the project is assumed to be located at the root + // of the repository. + // "repo_subdir": "", + + // Customizable commands for building, installing, and + // uninstalling the project. See asv.conf.json documentation. + // + // "install_command": ["in-dir={env_dir} python -mpip install {wheel_file}"], + // "uninstall_command": ["return-code=any python -mpip uninstall -y {project}"], + // "build_command": [ + // "python setup.py build", + // "PIP_NO_BUILD_ISOLATION=false python -mpip wheel --no-deps --no-index -w {build_cache_dir} {build_dir}" + // ], + + // List of branches to benchmark. If not provided, defaults to "master" + // (for git) or "default" (for mercurial). + // "branches": ["master"], // for git + // "branches": ["default"], // for mercurial + + // The DVCS being used. If not set, it will be automatically + // determined from "repo" by looking at the protocol in the URL + // (if remote), or by looking for special directories, such as + // ".git" (if local). + // "dvcs": "git", + + // The tool to use to create environments. May be "conda", + // "virtualenv" or other value depending on the plugins in use. + // If missing or the empty string, the tool will be automatically + // determined by looking for tools on the PATH environment + // variable. + "environment_type": "virtualenv", + + // timeout in seconds for installing any dependencies in environment + // defaults to 10 min + //"install_timeout": 600, + + // the base URL to show a commit for the project. + // "show_commit_url": "http://github.com/owner/project/commit/", + + // The Pythons you'd like to test against. If not provided, defaults + // to the current version of Python used to run `asv`. + // "pythons": ["2.7", "3.6"], + + // The list of conda channel names to be searched for benchmark + // dependency packages in the specified order + // "conda_channels": ["conda-forge", "defaults"], + + // A conda environment file that is used for environment creation. + // "conda_environment_file": "environment.yml", + + // The matrix of dependencies to test. Each key of the "req" + // requirements dictionary is the name of a package (in PyPI) and + // the values are version numbers. An empty list or empty string + // indicates to just test against the default (latest) + // version. null indicates that the package is to not be + // installed. If the package to be tested is only available from + // PyPi, and the 'environment_type' is conda, then you can preface + // the package name by 'pip+', and the package will be installed + // via pip (with all the conda available packages installed first, + // followed by the pip installed packages). + // + // The ``@env`` and ``@env_nobuild`` keys contain the matrix of + // environment variables to pass to build and benchmark commands. + // An environment will be created for every combination of the + // cartesian product of the "@env" variables in this matrix. + // Variables in "@env_nobuild" will be passed to every environment + // during the benchmark phase, but will not trigger creation of + // new environments. A value of ``null`` means that the variable + // will not be set for the current combination. + // + // "matrix": { + // "req": { + // "numpy": ["1.6", "1.7"], + // "six": ["", null], // test with and without six installed + // "pip+emcee": [""] // emcee is only available for install with pip. + // }, + // "env": {"ENV_VAR_1": ["val1", "val2"]}, + // "env_nobuild": {"ENV_VAR_2": ["val3", null]}, + // }, + + // Combinations of libraries/python versions can be excluded/included + // from the set to test. Each entry is a dictionary containing additional + // key-value pairs to include/exclude. + // + // An exclude entry excludes entries where all values match. The + // values are regexps that should match the whole string. + // + // An include entry adds an environment. Only the packages listed + // are installed. The 'python' key is required. The exclude rules + // do not apply to includes. + // + // In addition to package names, the following keys are available: + // + // - python + // Python version, as in the *pythons* variable above. + // - environment_type + // Environment type, as above. + // - sys_platform + // Platform, as in sys.platform. Possible values for the common + // cases: 'linux2', 'win32', 'cygwin', 'darwin'. + // - req + // Required packages + // - env + // Environment variables + // - env_nobuild + // Non-build environment variables + // + // "exclude": [ + // {"python": "3.2", "sys_platform": "win32"}, // skip py3.2 on windows + // {"environment_type": "conda", "req": {"six": null}}, // don't run without six on conda + // {"env": {"ENV_VAR_1": "val2"}}, // skip val2 for ENV_VAR_1 + // ], + // + // "include": [ + // // additional env for python2.7 + // {"python": "2.7", "req": {"numpy": "1.8"}, "env_nobuild": {"FOO": "123"}}, + // // additional env if run on windows+conda + // {"platform": "win32", "environment_type": "conda", "python": "2.7", "req": {"libpython": ""}}, + // ], + + // The directory (relative to the current directory) that benchmarks are + // stored in. If not provided, defaults to "benchmarks" + // "benchmark_dir": "benchmarks", + + // The directory (relative to the current directory) to cache the Python + // environments in. If not provided, defaults to "env" + "env_dir": ".asv/env", + + // The directory (relative to the current directory) that raw benchmark + // results are stored in. If not provided, defaults to "results". + "results_dir": ".asv/results", + + // The directory (relative to the current directory) that the html tree + // should be written to. If not provided, defaults to "html". + "html_dir": ".asv/html", + + // The number of characters to retain in the commit hashes. + // "hash_length": 8, + + // `asv` will cache results of the recent builds in each + // environment, making them faster to install next time. This is + // the number of builds to keep, per environment. + // "build_cache_size": 2, + + // The commits after which the regression search in `asv publish` + // should start looking for regressions. Dictionary whose keys are + // regexps matching to benchmark names, and values corresponding to + // the commit (exclusive) after which to start looking for + // regressions. The default is to start from the first commit + // with results. If the commit is `null`, regression detection is + // skipped for the matching benchmark. + // + // "regressions_first_commits": { + // "some_benchmark": "352cdf", // Consider regressions only after this commit + // "another_benchmark": null, // Skip regression detection altogether + // }, + + // The thresholds for relative change in results, after which `asv + // publish` starts reporting regressions. Dictionary of the same + // form as in ``regressions_first_commits``, with values + // indicating the thresholds. If multiple entries match, the + // maximum is taken. If no entry matches, the default is 5%. + // + // "regressions_thresholds": { + // "some_benchmark": 0.01, // Threshold of 1% + // "another_benchmark": 0.5, // Threshold of 50% + // }, +} diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/benchmarks/__init__.py @@ -0,0 +1 @@ + diff --git a/benchmarks/benchmarks.py b/benchmarks/benchmarks.py new file mode 100644 index 00000000..26781439 --- /dev/null +++ b/benchmarks/benchmarks.py @@ -0,0 +1,31 @@ +# Write the benchmarking functions here. +# See "Writing benchmarks" in the asv docs for more information. + + +class TimeSuite: + """ + An example benchmark that times the performance of various kinds + of iterating over dictionaries in Python. + """ + def setup(self): + self.d = {} + for x in range(500): + self.d[x] = None + + def time_keys(self): + for key in self.d.keys(): + pass + + def time_values(self): + for value in self.d.values(): + pass + + def time_range(self): + d = self.d + for key in range(500): + x = d[key] + + +class MemSuite: + def mem_list(self): + return [0] * 256 From 1a5ce775910fe888de45f3a3e7389f8871a93fac Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Tue, 17 May 2022 14:38:46 +0900 Subject: [PATCH 06/14] fixed pylint --- .../benchmarks/qk_base_benchmark.py | 42 +++++++++---------- machine_learning/benchmarks/qk_benchmark.py | 41 +++++++++--------- .../benchmarks/qk_fit_benchmark.py | 39 ++++++++--------- 3 files changed, 55 insertions(+), 67 deletions(-) diff --git a/machine_learning/benchmarks/qk_base_benchmark.py b/machine_learning/benchmarks/qk_base_benchmark.py index fcb47221..2ca2a933 100644 --- a/machine_learning/benchmarks/qk_base_benchmark.py +++ b/machine_learning/benchmarks/qk_base_benchmark.py @@ -18,11 +18,11 @@ from qiskit.circuit.library import ZZFeatureMap from qiskit_machine_learning.kernels import QuantumKernel from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer -from qiskit_machine_learning.algorithms import QSVC -from sklearn.pipeline import Pipeline -from sklearn.preprocessing import OneHotEncoder, FunctionTransformer from qiskit import QuantumCircuit from qiskit.circuit import ParameterVector +from sklearn.pipeline import Pipeline +from sklearn.preprocessing import OneHotEncoder, FunctionTransformer + import numpy as np from .base_classifier_benchmark import BaseClassifierBenchmark @@ -37,33 +37,29 @@ def __init__(self) -> None: super().__init__( synthetic_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]), iris_num_classes=2, - iris_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]), - ) - - def _construct_QuantumKernel_classical_classifier(self, - quantum_instance_name: str, + iris_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]),) + def _construct_quantumkernel_classical_classifier(self, + quantum_instance_name:str, optimizer: Optional[Optimizer] = None, - method = "quantumclassical", + method = "quantumclassical", num_qubits = 1, ) -> QuantumKernel: """This method just create the matrix from the quantum kernel""" - kernelmatrix = self._construct_QuantumKernel(num_qubits, + kernelmatrix = self._construct_quantumkernel(num_qubits, quantum_instance_name, method) return kernelmatrix - - def _construct_QuantumKernelTrainer(self, + def _construct_quantumkerneltrainer(self, quantum_instance_name: str, - optimizer: Optional[Optimizer] = None, + optimizer: Optional[Optimizer] = None, loss_function: str = None, - method = "quantum", + method = "quantum", num_qubits = 1,) -> QuantumKernelTrainer: - """This method returns the QuantumKernelTrainer""" - kernel = self._construct_QuantumKernel(num_qubits, quantum_instance_name, method) + """This method returns the quantumkerneltrainer""" + kernel = self._construct_quantumkernel(num_qubits, quantum_instance_name, method) optimizer = optimizer - qkt = QuantumKernelTrainer(quantum_kernel=kernel, loss=loss_function, + qkt = QuantumKernelTrainer(quantum_kernel=kernel, loss=loss_function, optimizer = optimizer, initial_point=[np.pi / 2]) - return qkt - - def _construct_QuantumKernel( + return qkt + def _construct_quantumkernel( self, num_inputs: int, quantum_instance_name: str, @@ -72,8 +68,8 @@ def _construct_QuantumKernel( """Construct a QuantumKernel""" if method == "quantumclassical": feature_map = ZZFeatureMap(num_inputs, reps=2, entanglement="linear") - qkernel = QuantumKernel(feature_map=feature_map, - quantum_instance=self.backends[quantum_instance_name]) + qkernel = QuantumKernel(feature_map=feature_map, + quantum_instance=self.backends[quantum_instance_name]) return qkernel elif method == "quantum": user_params = ParameterVector("θ", 1) @@ -83,7 +79,7 @@ def _construct_QuantumKernel( fm1 = ZZFeatureMap(num_inputs, reps=2, entanglement="linear") feature_map = fm0.compose(fm1) qkernel = QuantumKernel(feature_map = feature_map, - user_parameters=user_params, + user_parameters=user_params, quantum_instance=self.backends[quantum_instance_name]) return qkernel else: diff --git a/machine_learning/benchmarks/qk_benchmark.py b/machine_learning/benchmarks/qk_benchmark.py index 6c710199..568e8557 100644 --- a/machine_learning/benchmarks/qk_benchmark.py +++ b/machine_learning/benchmarks/qk_benchmark.py @@ -16,12 +16,11 @@ from typing import Optional, Union from qiskit_machine_learning.kernels import QuantumKernel from qiskit_machine_learning.kernels.algorithms import QuantumKernelTrainer -import numpy as np from qiskit.algorithms.optimizers import COBYLA from qiskit_machine_learning.algorithms import QSVC from sklearn.metrics import precision_score, recall_score, f1_score from sympy import evaluate - +import numpy as np from .base_classifier_benchmark import DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION from .qk_base_benchmark import QKernelBaseClassifierBenchmark @@ -42,8 +41,7 @@ def __init__(self) -> None: self.train_labels: Optional[np.ndarray] = None self.test_features: Optional[np.ndarray] = None self.test_labels: Optional[np.ndarray] = None - self.model: Optional[Union[QuantumKernel, QuantumKernelTrainer]] = None - + self.model: Optional[Union[QuantumKernel, QuantumKernelTrainer]] = None def setup(self, dataset: str, technique: str, quantum_instance_name: str) -> None: """Set up the benchmark.""" self.train_features = self.datasets[dataset]["train_features"] @@ -52,17 +50,18 @@ def setup(self, dataset: str, technique: str, quantum_instance_name: str) -> Non self.test_labels = self.datasets[dataset]["test_labels"] n_qubits = self.train_features.shape[1] if technique == "QuantumKernel": - self.model = self._construct_QuantumKernel_classical_classifier(quantum_instance_name = quantum_instance_name, - num_qubits = n_qubits) + self.model = self._construct_quantumkernel_classical_classifier(quantum_instance_name = + quantum_instance_name, + num_qubits = n_qubits) elif technique == "QuantumKernelTraining": - self.model = self._construct_QuantumKernelTrainer(quantum_instance_name= quantum_instance_name, - num_qubits = n_qubits) + self.model = self._construct_quantumkerneltrainer(quantum_instance_name= + quantum_instance_name, + num_qubits = n_qubits) else: raise ValueError(f"Unsupported technique: {technique}") file_name = f"qk_{technique}_{dataset}_{quantum_instance_name}.pickle" with open(file_name, "rb") as file: - self.result = pickle.load(file) - + self.result = pickle.load(file) def setup_cache(self) -> None: """Cache qk&svm or qkt fitted model.""" for dataset, backend, technique in product(*self.params): @@ -71,22 +70,22 @@ def setup_cache(self) -> None: n_qubits = train_features.shape[1] if dataset != DATASET_SYNTHETIC_CLASSIFICATION & dataset != DATASET_IRIS_CLASSIFICATION: raise ValueError(f"Unsupported dataset: {dataset}") - if technique == "QuantumKernel": - _kernel = self._construct_QuantumKernel_classical_classifier(quantum_instance_name= backend, - optimizer = COBYLA(maxiter=200), + if technique == "QuantumKernel": + _kernel = self._construct_quantumkernel_classical_classifier(quantum_instance_name= + backend, + optimizer = COBYLA(maxiter=200), num_qubits = n_qubits) model = _kernel elif technique == "QuantumKernelTraining": - model = self._construct_QuantumKernelTrainer(quantum_instance_name= backend, - optimizer=COBYLA(maxiter=200), - num_qubits = n_qubits ) + model = self._construct_quantumkerneltrainer(quantum_instance_name= backend, + optimizer=COBYLA(maxiter=200), + num_qubits = n_qubits) else: - ValueError(f"Unsupported technique: {technique}") + ValueError(f"Unsupported technique: {technique}") result = model.fit(train_features, train_labels) file_name = f"qk_{technique}_{dataset}_{backend}.pickle" with open(file_name, "wb") as file: - pickle.dump(result, file) - + pickle.dump(result, file) # pylint: disable=invalid-name def time_score_vqc_classifier(self, _, __): """Time scoring VQC on data.""" @@ -114,7 +113,6 @@ def track_f1_score_vqc_classifier(self, _, __): """Tracks the f1 score for each class of the classification results.""" predicts = QSVC(kernel = self.model).predict(self.test_features) return f1_score(y_true=self.test_labels, y_pred=predicts, average="micro") - if __name__ == "__main__": bench = QKernelBenchmarks() bench.setup_cache() @@ -123,7 +121,6 @@ def track_f1_score_vqc_classifier(self, _, __): bench.setup(dataset_name, technique_name, backend_name) except NotImplementedError: continue - for method in ( "time_score_vqc_classifier", "time_predict_vqc_classifier", @@ -134,4 +131,4 @@ def track_f1_score_vqc_classifier(self, _, __): ): elapsed = timeit( f'bench.{method}("{dataset_name}", "{backend_name}")', number=10, globals=globals() - ) + ) \ No newline at end of file diff --git a/machine_learning/benchmarks/qk_fit_benchmark.py b/machine_learning/benchmarks/qk_fit_benchmark.py index 5b53e995..34e8cedd 100644 --- a/machine_learning/benchmarks/qk_fit_benchmark.py +++ b/machine_learning/benchmarks/qk_fit_benchmark.py @@ -28,7 +28,6 @@ class QKernelFitBenchmarks(QKernelBaseClassifierBenchmark): """QuantumKernel and QuantumKernelTraining fit benchmarks.""" - version = 2 timeout = 1200.0 params = [ @@ -39,10 +38,8 @@ class QKernelFitBenchmarks(QKernelBaseClassifierBenchmark): ["cross_entropy", "squared_error"], ] param_names = ["dataset", "backend name", "technique", "optimizer", "loss function"] - def __init__(self) -> None: super().__init__() - self.optimizers = { "cobyla": COBYLA(maxiter=100), "nelder-mead": NELDER_MEAD(maxiter=50), @@ -55,9 +52,9 @@ def __init__(self) -> None: self.model: Optional[Union[QuantumKernel, QuantumKernelTrainer]] = None def setup( - self, - dataset: str, - technique: str, + self, + dataset: str, + tech: str, quantum_instance_name: str, optimizer: str, loss_function: str, @@ -67,36 +64,34 @@ def setup( self.train_labels = self.datasets[dataset]["train_labels"] #new n_qubits = self.train_features.shape[1] - if technique == "QuantumKernel": - self.model = self._construct_QuantumKernel_classical_classifier( - quantum_instance_name= quantum_instance_name, + if tech == "QuantumKernel": + self.model = self._construct_quantumkernel_classical_classifier( + quantum_instance_name= quantum_instance_name, optimizer = optimizer, - num_qubits = n_qubits) - elif technique == "QuantumKernelTraining": - self.model = self._construct_QuantumKernelTrainer( - quantum_instance_name= quantum_instance_name, - optimizer= optimizer, + num_qubits = n_qubits) + elif tech == "QuantumKernelTraining": + self.model = self._construct_quantumkerneltrainer( + quantum_instance_name= quantum_instance_name, + optimizer= optimizer, loss_function = loss_function, - num_qubits = n_qubits, - ) + num_qubits = n_qubits, + ) else: - raise ValueError(f"Unsupported technique: {technique}") - + raise ValueError(f"Unsupported technique: {tech}") # pylint: disable=invalid-name - def time_fit_vqc(self, technique, _, __, ___, ____): + def time_fit_vqc(self, tech, _, __, ___, ____): """Time fitting VQC to data.""" - if technique == "QuantumKernel": + if tech == "QuantumKernel": self.model = QSVC(kernel = self.model.evaluate) #fit self.model.fit(self.train_features, self.train_labels) - if __name__ == "__main__": for dataset_name, backend_name, technique, optimizer_name, loss_function_name in product( *QKernelFitBenchmarks.params ): bench = QKernelFitBenchmarks() try: - bench.setup(dataset_name, technique, backend_name, + bench.setup(dataset_name, technique, backend_name, optimizer_name, loss_function_name) except NotImplementedError: continue From d36397cae5fa4ff8557cadc4100e75d2bbf7f630 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Wed, 18 May 2022 13:46:56 +0900 Subject: [PATCH 07/14] fixed typos --- machine_learning/benchmarks/qk_base_benchmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machine_learning/benchmarks/qk_base_benchmark.py b/machine_learning/benchmarks/qk_base_benchmark.py index 2ca2a933..631f4642 100644 --- a/machine_learning/benchmarks/qk_base_benchmark.py +++ b/machine_learning/benchmarks/qk_base_benchmark.py @@ -38,7 +38,7 @@ def __init__(self) -> None: synthetic_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]), iris_num_classes=2, iris_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]),) - def _construct_quantumkernel_classical_classifier(self, + def _construct_quantumkernel_classical_classifier(self, quantum_instance_name:str, optimizer: Optional[Optimizer] = None, method = "quantumclassical", From 80ebca773ecba969314734cffc97d0e1696f4413 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Wed, 18 May 2022 13:50:37 +0900 Subject: [PATCH 08/14] fix typos --- machine_learning/benchmarks/qk_benchmark.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/machine_learning/benchmarks/qk_benchmark.py b/machine_learning/benchmarks/qk_benchmark.py index 568e8557..dedc1218 100644 --- a/machine_learning/benchmarks/qk_benchmark.py +++ b/machine_learning/benchmarks/qk_benchmark.py @@ -72,9 +72,7 @@ def setup_cache(self) -> None: raise ValueError(f"Unsupported dataset: {dataset}") if technique == "QuantumKernel": _kernel = self._construct_quantumkernel_classical_classifier(quantum_instance_name= - backend, - optimizer = COBYLA(maxiter=200), - num_qubits = n_qubits) + backend, num_qubits = n_qubits) model = _kernel elif technique == "QuantumKernelTraining": model = self._construct_quantumkerneltrainer(quantum_instance_name= backend, @@ -131,4 +129,4 @@ def track_f1_score_vqc_classifier(self, _, __): ): elapsed = timeit( f'bench.{method}("{dataset_name}", "{backend_name}")', number=10, globals=globals() - ) \ No newline at end of file + ) From f350849635ccc097066c69d487f8247cdc4ec66d Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Wed, 18 May 2022 13:52:14 +0900 Subject: [PATCH 09/14] typos --- machine_learning/benchmarks/qk_base_benchmark.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/machine_learning/benchmarks/qk_base_benchmark.py b/machine_learning/benchmarks/qk_base_benchmark.py index 631f4642..1cf876b6 100644 --- a/machine_learning/benchmarks/qk_base_benchmark.py +++ b/machine_learning/benchmarks/qk_base_benchmark.py @@ -40,7 +40,6 @@ def __init__(self) -> None: iris_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]),) def _construct_quantumkernel_classical_classifier(self, quantum_instance_name:str, - optimizer: Optional[Optimizer] = None, method = "quantumclassical", num_qubits = 1, ) -> QuantumKernel: """This method just create the matrix from the quantum kernel""" @@ -55,7 +54,6 @@ def _construct_quantumkerneltrainer(self, num_qubits = 1,) -> QuantumKernelTrainer: """This method returns the quantumkerneltrainer""" kernel = self._construct_quantumkernel(num_qubits, quantum_instance_name, method) - optimizer = optimizer qkt = QuantumKernelTrainer(quantum_kernel=kernel, loss=loss_function, optimizer = optimizer, initial_point=[np.pi / 2]) return qkt From eb17e590a350d74b514cf7488bf759123eb56e93 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Wed, 18 May 2022 13:52:53 +0900 Subject: [PATCH 10/14] typos --- machine_learning/benchmarks/qk_base_benchmark.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/machine_learning/benchmarks/qk_base_benchmark.py b/machine_learning/benchmarks/qk_base_benchmark.py index 1cf876b6..3dfa36a5 100644 --- a/machine_learning/benchmarks/qk_base_benchmark.py +++ b/machine_learning/benchmarks/qk_base_benchmark.py @@ -38,7 +38,7 @@ def __init__(self) -> None: synthetic_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]), iris_num_classes=2, iris_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]),) - def _construct_quantumkernel_classical_classifier(self, + def _construct_quantumkernel_classical_classifier(self, quantum_instance_name:str, method = "quantumclassical", num_qubits = 1, ) -> QuantumKernel: From 8eb11d4f2f94a8ec54063919a696c40dcce690f7 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Wed, 18 May 2022 14:02:11 +0900 Subject: [PATCH 11/14] fixed some errors --- .../benchmarks/qk_base_benchmark.py | 48 ++++++++++++------- machine_learning/benchmarks/qk_benchmark.py | 46 +++++++++++------- .../benchmarks/qk_fit_benchmark.py | 33 +++++++------ 3 files changed, 78 insertions(+), 49 deletions(-) diff --git a/machine_learning/benchmarks/qk_base_benchmark.py b/machine_learning/benchmarks/qk_base_benchmark.py index 3dfa36a5..c5f86731 100644 --- a/machine_learning/benchmarks/qk_base_benchmark.py +++ b/machine_learning/benchmarks/qk_base_benchmark.py @@ -37,26 +37,37 @@ def __init__(self) -> None: super().__init__( synthetic_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]), iris_num_classes=2, - iris_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]),) - def _construct_quantumkernel_classical_classifier(self, - quantum_instance_name:str, - method = "quantumclassical", - num_qubits = 1, ) -> QuantumKernel: + iris_label_encoder=Pipeline([("reshape", reshaper), ("one hot", encoder)]), + ) + + def _construct_quantumkernel_classical_classifier( + self, + quantum_instance_name: str, + method="quantumclassical", + num_qubits=1, + ) -> QuantumKernel: """This method just create the matrix from the quantum kernel""" - kernelmatrix = self._construct_quantumkernel(num_qubits, - quantum_instance_name, method) + kernelmatrix = self._construct_quantumkernel(num_qubits, quantum_instance_name, method) return kernelmatrix - def _construct_quantumkerneltrainer(self, + + def _construct_quantumkerneltrainer( + self, quantum_instance_name: str, optimizer: Optional[Optimizer] = None, loss_function: str = None, - method = "quantum", - num_qubits = 1,) -> QuantumKernelTrainer: + method="quantum", + num_qubits=1, + ) -> QuantumKernelTrainer: """This method returns the quantumkerneltrainer""" kernel = self._construct_quantumkernel(num_qubits, quantum_instance_name, method) - qkt = QuantumKernelTrainer(quantum_kernel=kernel, loss=loss_function, - optimizer = optimizer, initial_point=[np.pi / 2]) + qkt = QuantumKernelTrainer( + quantum_kernel=kernel, + loss=loss_function, + optimizer=optimizer, + initial_point=[np.pi / 2], + ) return qkt + def _construct_quantumkernel( self, num_inputs: int, @@ -66,8 +77,9 @@ def _construct_quantumkernel( """Construct a QuantumKernel""" if method == "quantumclassical": feature_map = ZZFeatureMap(num_inputs, reps=2, entanglement="linear") - qkernel = QuantumKernel(feature_map=feature_map, - quantum_instance=self.backends[quantum_instance_name]) + qkernel = QuantumKernel( + feature_map=feature_map, quantum_instance=self.backends[quantum_instance_name] + ) return qkernel elif method == "quantum": user_params = ParameterVector("θ", 1) @@ -76,9 +88,11 @@ def _construct_quantumkernel( fm0.ry(user_params[0], i) fm1 = ZZFeatureMap(num_inputs, reps=2, entanglement="linear") feature_map = fm0.compose(fm1) - qkernel = QuantumKernel(feature_map = feature_map, - user_parameters=user_params, - quantum_instance=self.backends[quantum_instance_name]) + qkernel = QuantumKernel( + feature_map=feature_map, + user_parameters=user_params, + quantum_instance=self.backends[quantum_instance_name], + ) return qkernel else: return ValueError(f"Unsupported method: {method}") diff --git a/machine_learning/benchmarks/qk_benchmark.py b/machine_learning/benchmarks/qk_benchmark.py index dedc1218..6e5e3cd9 100644 --- a/machine_learning/benchmarks/qk_benchmark.py +++ b/machine_learning/benchmarks/qk_benchmark.py @@ -24,14 +24,16 @@ from .base_classifier_benchmark import DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION from .qk_base_benchmark import QKernelBaseClassifierBenchmark + class QKernelBenchmarks(QKernelBaseClassifierBenchmark): """Quantum Kernel Classifier (q&svm or qkt) benchmarks.""" + version = 1 timeout = 1200.0 params = [ [DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION], ["qasm_simulator", "statevector_simulator"], - ["QuantumKernel", "QuantumKernelTraining" ] + ["QuantumKernel", "QuantumKernelTraining"], ] param_names = ["dataset", "backend", "technique"] @@ -42,6 +44,7 @@ def __init__(self) -> None: self.test_features: Optional[np.ndarray] = None self.test_labels: Optional[np.ndarray] = None self.model: Optional[Union[QuantumKernel, QuantumKernelTrainer]] = None + def setup(self, dataset: str, technique: str, quantum_instance_name: str) -> None: """Set up the benchmark.""" self.train_features = self.datasets[dataset]["train_features"] @@ -50,18 +53,19 @@ def setup(self, dataset: str, technique: str, quantum_instance_name: str) -> Non self.test_labels = self.datasets[dataset]["test_labels"] n_qubits = self.train_features.shape[1] if technique == "QuantumKernel": - self.model = self._construct_quantumkernel_classical_classifier(quantum_instance_name = - quantum_instance_name, - num_qubits = n_qubits) + self.model = self._construct_quantumkernel_classical_classifier( + quantum_instance_name=quantum_instance_name, num_qubits=n_qubits + ) elif technique == "QuantumKernelTraining": - self.model = self._construct_quantumkerneltrainer(quantum_instance_name= - quantum_instance_name, - num_qubits = n_qubits) + self.model = self._construct_quantumkerneltrainer( + quantum_instance_name=quantum_instance_name, num_qubits=n_qubits + ) else: raise ValueError(f"Unsupported technique: {technique}") file_name = f"qk_{technique}_{dataset}_{quantum_instance_name}.pickle" with open(file_name, "rb") as file: self.result = pickle.load(file) + def setup_cache(self) -> None: """Cache qk&svm or qkt fitted model.""" for dataset, backend, technique in product(*self.params): @@ -71,46 +75,52 @@ def setup_cache(self) -> None: if dataset != DATASET_SYNTHETIC_CLASSIFICATION & dataset != DATASET_IRIS_CLASSIFICATION: raise ValueError(f"Unsupported dataset: {dataset}") if technique == "QuantumKernel": - _kernel = self._construct_quantumkernel_classical_classifier(quantum_instance_name= - backend, num_qubits = n_qubits) + _kernel = self._construct_quantumkernel_classical_classifier( + quantum_instance_name=backend, num_qubits=n_qubits + ) model = _kernel elif technique == "QuantumKernelTraining": - model = self._construct_quantumkerneltrainer(quantum_instance_name= backend, - optimizer=COBYLA(maxiter=200), - num_qubits = n_qubits) + model = self._construct_quantumkerneltrainer( + quantum_instance_name=backend, + optimizer=COBYLA(maxiter=200), + num_qubits=n_qubits, + ) else: ValueError(f"Unsupported technique: {technique}") result = model.fit(train_features, train_labels) file_name = f"qk_{technique}_{dataset}_{backend}.pickle" with open(file_name, "wb") as file: pickle.dump(result, file) + # pylint: disable=invalid-name def time_score_vqc_classifier(self, _, __): """Time scoring VQC on data.""" - QSVC(kernel = self.model).score(self.train_features, self.train_labels) + QSVC(kernel=self.model).score(self.train_features, self.train_labels) def time_predict_vqc_classifier(self, _, __): """Time predicting with VQC.""" - QSVC(kernel = self.model).predict(self.train_features) + QSVC(kernel=self.model).predict(self.train_features) def track_accuracy_score_vqc_classifier(self, _, __): """Tracks the overall accuracy of the classification results.""" - return QSVC(kernel = self.model).score(self.test_features, self.test_labels) + return QSVC(kernel=self.model).score(self.test_features, self.test_labels) def track_precision_score_vqc_classifier(self, _, __): """Tracks the precision score.""" - predicts = QSVC(kernel = self.model).predict(self.test_features) + predicts = QSVC(kernel=self.model).predict(self.test_features) return precision_score(y_true=self.test_labels, y_pred=predicts, average="micro") def track_recall_score_vqc_classifier(self, _, __): """Tracks the recall score for each class of the classification results.""" - predicts = QSVC(kernel = self.model).predict(self.test_features) + predicts = QSVC(kernel=self.model).predict(self.test_features) return recall_score(y_true=self.test_labels, y_pred=predicts, average="micro") def track_f1_score_vqc_classifier(self, _, __): """Tracks the f1 score for each class of the classification results.""" - predicts = QSVC(kernel = self.model).predict(self.test_features) + predicts = QSVC(kernel=self.model).predict(self.test_features) return f1_score(y_true=self.test_labels, y_pred=predicts, average="micro") + + if __name__ == "__main__": bench = QKernelBenchmarks() bench.setup_cache() diff --git a/machine_learning/benchmarks/qk_fit_benchmark.py b/machine_learning/benchmarks/qk_fit_benchmark.py index 34e8cedd..6ecb6916 100644 --- a/machine_learning/benchmarks/qk_fit_benchmark.py +++ b/machine_learning/benchmarks/qk_fit_benchmark.py @@ -26,18 +26,21 @@ from .qk_base_benchmark import QKernelBaseClassifierBenchmark + class QKernelFitBenchmarks(QKernelBaseClassifierBenchmark): """QuantumKernel and QuantumKernelTraining fit benchmarks.""" + version = 2 timeout = 1200.0 params = [ [DATASET_SYNTHETIC_CLASSIFICATION, DATASET_IRIS_CLASSIFICATION], ["qasm_simulator", "statevector_simulator"], - ["QuantumKernel", "QuantumKernelTraining" ], + ["QuantumKernel", "QuantumKernelTraining"], ["cobyla", "nelder-mead", "l-bfgs-b"], ["cross_entropy", "squared_error"], ] param_names = ["dataset", "backend name", "technique", "optimizer", "loss function"] + def __init__(self) -> None: super().__init__() self.optimizers = { @@ -62,37 +65,39 @@ def setup( """Set up the benchmark.""" self.train_features = self.datasets[dataset]["train_features"] self.train_labels = self.datasets[dataset]["train_labels"] - #new + # new n_qubits = self.train_features.shape[1] if tech == "QuantumKernel": self.model = self._construct_quantumkernel_classical_classifier( - quantum_instance_name= quantum_instance_name, - optimizer = optimizer, - num_qubits = n_qubits) + quantum_instance_name=quantum_instance_name, + num_qubits=n_qubits, + ) elif tech == "QuantumKernelTraining": self.model = self._construct_quantumkerneltrainer( - quantum_instance_name= quantum_instance_name, - optimizer= optimizer, - loss_function = loss_function, - num_qubits = n_qubits, - ) + quantum_instance_name=quantum_instance_name, + optimizer=optimizer, + loss_function=loss_function, + num_qubits=n_qubits, + ) else: raise ValueError(f"Unsupported technique: {tech}") + # pylint: disable=invalid-name def time_fit_vqc(self, tech, _, __, ___, ____): """Time fitting VQC to data.""" if tech == "QuantumKernel": - self.model = QSVC(kernel = self.model.evaluate) - #fit + self.model = QSVC(kernel=self.model.evaluate) + # fit self.model.fit(self.train_features, self.train_labels) + + if __name__ == "__main__": for dataset_name, backend_name, technique, optimizer_name, loss_function_name in product( *QKernelFitBenchmarks.params ): bench = QKernelFitBenchmarks() try: - bench.setup(dataset_name, technique, backend_name, - optimizer_name, loss_function_name) + bench.setup(dataset_name, technique, backend_name, optimizer_name, loss_function_name) except NotImplementedError: continue for method in ["time_fit_vqc"]: From 0c66dbc58ecd59eb2a84d5aeafb98bf0dbfdb584 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Thu, 2 Jun 2022 10:04:54 +0900 Subject: [PATCH 12/14] adjusted benchmarks, still 2 errors --- machine_learning/benchmarks/qk_benchmark.py | 28 ++++++++++++--------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/machine_learning/benchmarks/qk_benchmark.py b/machine_learning/benchmarks/qk_benchmark.py index 6e5e3cd9..f34e6e7e 100644 --- a/machine_learning/benchmarks/qk_benchmark.py +++ b/machine_learning/benchmarks/qk_benchmark.py @@ -75,15 +75,19 @@ def setup_cache(self) -> None: if dataset != DATASET_SYNTHETIC_CLASSIFICATION & dataset != DATASET_IRIS_CLASSIFICATION: raise ValueError(f"Unsupported dataset: {dataset}") if technique == "QuantumKernel": - _kernel = self._construct_quantumkernel_classical_classifier( - quantum_instance_name=backend, num_qubits=n_qubits + _kernel = QSVC( + self._construct_quantumkernel_classical_classifier( + quantum_instance_name=backend, num_qubits=n_qubits + ) ) model = _kernel elif technique == "QuantumKernelTraining": - model = self._construct_quantumkerneltrainer( - quantum_instance_name=backend, - optimizer=COBYLA(maxiter=200), - num_qubits=n_qubits, + model = QSVC( + self._construct_quantumkerneltrainer( + quantum_instance_name=backend, + optimizer=COBYLA(maxiter=200), + num_qubits=n_qubits, + ) ) else: ValueError(f"Unsupported technique: {technique}") @@ -95,29 +99,29 @@ def setup_cache(self) -> None: # pylint: disable=invalid-name def time_score_vqc_classifier(self, _, __): """Time scoring VQC on data.""" - QSVC(kernel=self.model).score(self.train_features, self.train_labels) + self.model.score(self.train_features, self.train_labels) def time_predict_vqc_classifier(self, _, __): """Time predicting with VQC.""" - QSVC(kernel=self.model).predict(self.train_features) + self.model.predict(self.train_features) def track_accuracy_score_vqc_classifier(self, _, __): """Tracks the overall accuracy of the classification results.""" - return QSVC(kernel=self.model).score(self.test_features, self.test_labels) + return self.model.score(self.test_features, self.test_labels) def track_precision_score_vqc_classifier(self, _, __): """Tracks the precision score.""" - predicts = QSVC(kernel=self.model).predict(self.test_features) + predicts = self.model.predict(self.test_features) return precision_score(y_true=self.test_labels, y_pred=predicts, average="micro") def track_recall_score_vqc_classifier(self, _, __): """Tracks the recall score for each class of the classification results.""" - predicts = QSVC(kernel=self.model).predict(self.test_features) + predicts = self.model.predict(self.test_features) return recall_score(y_true=self.test_labels, y_pred=predicts, average="micro") def track_f1_score_vqc_classifier(self, _, __): """Tracks the f1 score for each class of the classification results.""" - predicts = QSVC(kernel=self.model).predict(self.test_features) + predicts = self.model.predict(self.test_features) return f1_score(y_true=self.test_labels, y_pred=predicts, average="micro") From 2415e3387e834b886795119b98a2a57cda1f8402 Mon Sep 17 00:00:00 2001 From: Gruntrexpewrus Date: Fri, 3 Jun 2022 16:08:40 +0900 Subject: [PATCH 13/14] Merge branch 'main' of https://github.com/Gruntrexpewrus/qiskit-app-benchmarks --- machine_learning/benchmarks/qk_benchmark.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/machine_learning/benchmarks/qk_benchmark.py b/machine_learning/benchmarks/qk_benchmark.py index f34e6e7e..cce1761a 100644 --- a/machine_learning/benchmarks/qk_benchmark.py +++ b/machine_learning/benchmarks/qk_benchmark.py @@ -53,12 +53,16 @@ def setup(self, dataset: str, technique: str, quantum_instance_name: str) -> Non self.test_labels = self.datasets[dataset]["test_labels"] n_qubits = self.train_features.shape[1] if technique == "QuantumKernel": - self.model = self._construct_quantumkernel_classical_classifier( - quantum_instance_name=quantum_instance_name, num_qubits=n_qubits + self.model = QSVC( + self._construct_quantumkernel_classical_classifier( + quantum_instance_name=quantum_instance_name, num_qubits=n_qubits + ) ) elif technique == "QuantumKernelTraining": - self.model = self._construct_quantumkerneltrainer( - quantum_instance_name=quantum_instance_name, num_qubits=n_qubits + self.model = QSVC( + self._construct_quantumkerneltrainer( + quantum_instance_name=quantum_instance_name, num_qubits=n_qubits + ) ) else: raise ValueError(f"Unsupported technique: {technique}") From edaf922ee0238bac9d8644c5e9831e4203e82649 Mon Sep 17 00:00:00 2001 From: Atsushi Matsuo Date: Mon, 6 Jun 2022 17:29:59 +0900 Subject: [PATCH 14/14] test --- test | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test diff --git a/test b/test new file mode 100644 index 00000000..e69de29b