Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add QuantumKernelTrainer and KernelLoss classes #244

Merged

Conversation

caleb-johnson
Copy link
Contributor

@caleb-johnson caleb-johnson commented Oct 18, 2021

Summary

Closes #227
Variational quantum algorithms generally aim to train some quantum circuit parameters using a classical optimizer. To implement this, parameters of a QuantumCircuit must be bound and re-bound many times during optimization; however, the QuantumCircuit API "forgets" the parameter after it is bound, making consecutive binds of a QuantumCircuit parameter a cumbersome process.

The introduction of a QuantumKernelTrainer (QKT) class simplifies this process by providing a fit_kernel method, which will return some optimized QuantumKernel.feature_map parameter values which can be used to generate an optimized kernel operator.

Changes from this PR:

  • Addition of a qiskit_machine_learning.kernels.algorithms.QuantumKernelTrainer (QKT) class which facilitates optimizing a set of a parameters within a QuantumKernel feature map with regard to a given dataset.

  • Addition of a new qiskit_machine_learning.utils.loss_functions base class, KernelLoss. KernelLoss functions take a set of circuit parameters to optimize, a QuantumKernel object, and a labeled dataset as input and provide a loss value as output.

  • Addition of a new KernelLoss child class, SVCLoss.

Copy link
Collaborator

@adekusar-drl adekusar-drl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank! A couple of questions:

  • Are there any papers to reference in the documentation?
  • Does QKA works for QSVR?

qiskit_machine_learning/algorithms/classifiers/qsvc.py Outdated Show resolved Hide resolved
qiskit_machine_learning/algorithms/classifiers/qsvc.py Outdated Show resolved Hide resolved
qiskit_machine_learning/algorithms/classifiers/qsvc.py Outdated Show resolved Hide resolved
qiskit_machine_learning/algorithms/classifiers/qsvc.py Outdated Show resolved Hide resolved
qiskit_machine_learning/algorithms/classifiers/qsvc.py Outdated Show resolved Hide resolved
test/algorithms/classifiers/test_qsvc.py Outdated Show resolved Hide resolved
Comment on lines 73 to 77
def test_qkt(self):
"""Test QuantumKernelTrainer"""
self.setUp()
with self.subTest("check default fit"):
qkt = QuantumKernelTrainer(optimizer=self.optimizer)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a test where QuantumKernelTrainer is instantiated with all default values?

test/kernels/algorithms/test_qkernel_trainer.py Outdated Show resolved Hide resolved
test/kernels/algorithms/test_qkernel_trainer.py Outdated Show resolved Hide resolved
test/algorithms/classifiers/test_qsvc.py Outdated Show resolved Hide resolved
@adekusar-drl
Copy link
Collaborator

@calebj15 Are there any updates on this PR?

Copy link
Collaborator

@adekusar-drl adekusar-drl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Any plans to add a tutorial on QKT?

super().setUp()
algorithm_globals.random_seed = 10598
self.optimizer = COBYLA(maxiter=25)
self.backend = Aer.get_backend("statevector_simulator")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed, please replace statevector_simulator with aer_simulator_statevector, otherwise there's a deprecation warning.

Suggested change
self.backend = Aer.get_backend("statevector_simulator")
self.backend = Aer.get_backend("aer_simulator_statevector")

Copy link
Collaborator

@adekusar-drl adekusar-drl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I left a few minor comments.

# Class fields
self._quantum_kernel = quantum_kernel
self._initial_point = initial_point
self._optimizer = optimizer if optimizer else SPSA()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be simplified:

Suggested change
self._optimizer = optimizer if optimizer else SPSA()
self._optimizer = optimizer or SPSA()

Comment on lines 126 to 128
self._loss = loss
else:
raise ValueError(f"Unknown loss {loss}!")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if I pass a callable Callable[[Sequence[float]], float], I get an exception.
Could you also add a test with a custom loss to check this scenario?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I believe we decided against this usage, so I just need to update type hint. Thanks

Comment on lines 143 to 146
return self._loss

@loss.setter
def loss(self, loss: KernelLoss) -> None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setter type should be the same as in the constructor.

Comment on lines 69 to 71
def test_qkt(self):
"""Test QuantumKernelTrainer"""
self.setUp()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.setUp() is not required. Please remove.

Comment on lines 84 to 86

with self.subTest("check fit with params"):
self.setUp()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.setUp() is not required. Please remove.

@adekusar-drl
Copy link
Collaborator

@calebj15 you have a conflict in .pylintdict

Copy link
Collaborator

@adekusar-drl adekusar-drl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the tutorial!I think we are converging and a few minor things are left in the code and tutorial.

Comment on lines 1 to 3
{
"cells": [
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename tutorial to 08. There are already two new tutorials 06 Torch runtime, 07 PegasosQSVC.

Comment on lines 64 to 68
" x[0]: number of function evaluations\n",
" x[1]: the parameters\n",
" x[2]: the function value\n",
" x[3]: the stepsize\n",
" x[4]: whether the step was accepted\n",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please reformat as a proper docstring. By the way, starting last week, black should applied on the doc folder as well.

"source": [
"### Prepare the Dataset\n",
"\n",
"QKT only provides an advantage over classical counterparts for quantum kernels which are hard to compute classically. Finding quantum kernels which provide an advantage on real world data is a challenge in itself and is outside the scope of this tutorial.\n",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"QKT only provides an advantage over classical counterparts for quantum kernels which are hard to compute classically. Finding quantum kernels which provide an advantage on real world data is a challenge in itself and is outside the scope of this tutorial.\n",
"`QuantumKernelTrainer` only provides an advantage over classical counterparts for quantum kernels which are hard to compute classically. Finding quantum kernels which provide an advantage on real world data is a challenge in itself and is outside the scope of this tutorial.\n",

"\n",
"QKT only provides an advantage over classical counterparts for quantum kernels which are hard to compute classically. Finding quantum kernels which provide an advantage on real world data is a challenge in itself and is outside the scope of this tutorial.\n",
"\n",
"In this guide, we will use Qiskit Machine Learning's `ad_hoc.py` dataset located [here](../../qiskit_machine_learning/datasets/). Quantum kernel training does not provide a classification advantage on this dataset, but we will use it to demonstrate the kernel training process."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"In this guide, we will use Qiskit Machine Learning's `ad_hoc.py` dataset located [here](../../qiskit_machine_learning/datasets/). Quantum kernel training does not provide a classification advantage on this dataset, but we will use it to demonstrate the kernel training process."
"In this guide, we will use Qiskit Machine Learning's `ad_hoc` dataset, see the documentation [here](https://qiskit.org/documentation/machine-learning/stubs/qiskit_machine_learning.datasets.ad_hoc_data.html). Quantum kernel training does not provide a classification advantage on this dataset, but we will use it to demonstrate the kernel training process."

Comment on lines 201 to 202
"\n",
"Additionally, we select SPSA as the optimizer and initialize the trainable parameter to 0.1 with `initial_point`.\n",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the code initial_point set as initial_point=[0.0], while in the text it is mentioned 0.1. Please correct.

Comment on lines 230 to 232
"# To use the quantum-kernel-trainer runtime client, users should replace\n",
"# QuantumKernelTrainer with the\n",
"# qiskit_machine_learning.runtime.QuantumKernelTrainerClient class.\n",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather remove this comment about the runtime. Once runtime is out, the tutorial can be extended.

Comment on lines 263 to 268
"{ 'optimal_parameters': {ParameterVectorElement(θ[0]): -0.0717475136739174},\n",
" 'optimal_point': array([-0.07174751]),\n",
" 'optimal_value': 6.825533666231239,\n",
" 'optimizer_evals': 30,\n",
" 'optimizer_time': None,\n",
" 'quantum_kernel': <qiskit_machine_learning.kernels.quantum_kernel.QuantumKernel object at 0x7fdda0701b50>}\n"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a description of what you get in qka_results?

Comment on lines 325 to 327
"From the callback data, we can plot how the loss evolves during the training process. We see it converges rapidly and reaches 100% test accuracy on this dataset with our choice of inputs.\n",
"\n",
"We can also display the final kernel matrix evaluated on the training data."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please a description of what is shown on the kernel matrix plot in various colors?

Comment on lines 92 to 99
loss: Union[str, Callable[[Sequence[float]], float]] = "svc_loss",
optimizer: Optional[Optimizer] = None,
initial_point: Optional[Sequence[float]] = None,
):
"""
Args:
quantum_kernel: QuantumKernel to be trained
loss (Callable[[Sequence[float]], float] or str):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please update loss type hints to be the same across the code? I guess it should be Union[str, KernelLoss] now.

Copy link
Collaborator

@adekusar-drl adekusar-drl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I hope I left last two comments :)

"source": [
"### Train the Quantum Kernel\n",
"\n",
"To train the quantum kernel on the dataset (samples and labels), we call the `fit_kernel` method of `QuantumKernelTrainer`.\n",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"To train the quantum kernel on the dataset (samples and labels), we call the `fit_kernel` method of `QuantumKernelTrainer`.\n",
"To train the quantum kernel on the dataset (samples and labels), we call the `fit` method of `QuantumKernelTrainer`.\n",

Comment on lines 118 to 122
loss = loss.lower()
if loss == "svc_loss":
self._loss = self._str_to_loss(loss)
else:
raise ValueError(f"Unknown loss {loss}!")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess a string to loss conversion is done in the _str_to_loss, so these checks are unnecessary as you mentioned below.

@adekusar-drl
Copy link
Collaborator

@stefan-woerner Please review as well as you left a change request.

stefan-woerner
stefan-woerner previously approved these changes Dec 14, 2021
Copy link
Contributor

@stefan-woerner stefan-woerner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider renaming user_parameters to kernel_parameters but otherwise I am good.

Copy link
Collaborator

@adekusar-drl adekusar-drl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot!

@adekusar-drl adekusar-drl merged commit aeed2df into qiskit-community:main Dec 14, 2021
oscar-wallis pushed a commit that referenced this pull request Feb 16, 2024
* Add QuantumKernelTrainer class, KernelLoss class, and refactor QSVC to accept QKT as input.

* Refactor to unconfuse mypy

* Add runtime client for QKA

* Remove qka program info from __init__

* Remove vqe language from qka client

* Retract changes to QSVC

* Address peer review comments. Remove kernels.algorithms package. Make QuantumKernel.assign_user_parameters more robust and add user tests to test parameter expression assignment. Test QKT outputs in tests.

* Change SVCAlignment class to SVCLoss and update KernelLoss doc strings.

* Fix equation in SVCLoss docstring

* Docstring improvements

* Add quantum kernel trainer runtime client and unit tests.

* Fix spelling errors

* Fix spelling errors

* Clean up docstring for SVCLoss

* Clean up docstring for SVCLoss

* Fix spelling errors

* Fix equation formatting in docstring

* Fix equation formatting in docstring

* New spelling errors

* New spelling errors

* Fix spelling errors. Add 'runtime' to pylint dict

* Fix mypy errors

* Fix mypy errors

* style error

* style error

* spelling error in docstring

* Fix circular imports due to typing.

* Fix circular imports due to typing.

* Make QuantumKernel class serializable by runtime.

* Update quantum_kernel_trainer.py

* Update quantum_kernel_trainer.py

* Update quantum_kernel_trainer.py

* Make KernelLoss.get_variational_callable a base method

* Make SVCLoss more efficient by only calculating kernel once

* Create kernels.algorithms package for QuantumKernelTrainer. Fix all CI/CD errors

* spelling errors

* Clean up kernel loss docstring

* Create kernels.algorithms package for quantum kernel trainer. Clean up CI/CD errors. Address kernel loss feedback.

* spelling errors

* spelling errors

* spelling errors

* Create separate file for kernel loss classes. Fix spelling errors.

* add runtime to pylint dict

* add vqe to pylint dict

* Address peer feedback

* html errors

* Address peer review comments

* Fix mypy errors

* Add a quantum kernel training tutorial

* Print results of kernel fitting in tutorial

* Rename QKT tutorial. Fix bad assertion in qkt test.

* Make QKT tests deterministic. Add to pylintdict

* Address minor comments in qkt tutorial

* Fix spelling errors in QKT tutorial

* Clean up docstring for qkt

* Fix comment in qkt tutorial. Remove unnecessary type checks from QKT module

* Clean up docstring in QKT

* Fix mypy error in qkt

* Fix mypy errors in qkt

* Fix mypy errors in qkt

Co-authored-by: Manoel Marques <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement a quantum kernel trainer class
8 participants