Note

# Quantum Kernel Machine Learning¶

The general task of machine learning is to find and study patterns in data. For many datasets, the datapoints are better understood in a higher dimensional feature space, through the use of a kernel function: $$k(\vec{x}_i, \vec{x}_j) = \langle f(\vec{x}_i), f(\vec{x}_j) \rangle$$ where $$k$$ is the kernel function, $$\vec{x}_i, \vec{x}_j$$ are $$n$$ dimensional inputs, $$f$$ is a map from $$n$$-dimension to $$m$$-dimension space and $$\langle a,b \rangle$$ denotes the dot product. When considering finite data, a kernel function can be represented as a matrix: $$K_{ij} = k(\vec{x}_i,\vec{x}_j)$$.

In quantum kernel machine learning, a quantum feature map $$\phi(\vec{x})$$ is used to map a classical feature vector $$\vec{x}$$ to a quantum Hilbert space, $$| \phi(\vec{x})\rangle \langle \phi(\vec{x})|$$, such that $$K_{ij} = \left| \langle \phi^\dagger(\vec{x}_j)| \phi(\vec{x}_i) \rangle \right|^{2}$$. See Supervised learning with quantum enhanced feature spaces for more details.

In this notebook, we use qiskit to calculate a kernel matrix using a quantum feature map, then use this kernel matrix in scikit-learn classification and clustering algorithms.

[1]:

import matplotlib.pyplot as plt
import numpy as np

from sklearn.svm import SVC
from sklearn.cluster import SpectralClustering
from sklearn.metrics import normalized_mutual_info_score

from qiskit import BasicAer
from qiskit.circuit.library import ZZFeatureMap
from qiskit.utils import QuantumInstance, algorithm_globals
from qiskit_machine_learning.algorithms import QSVC
from qiskit_machine_learning.kernels import QuantumKernel

seed = 12345
algorithm_globals.random_seed = seed


## Classification¶

For our classification example, we will use the ad hoc dataset as described in Supervised learning with quantum enhanced feature spaces, and the scikit-learn support vector machine classification (svc) algorithm.

[2]:

adhoc_dimension = 2
training_size=20,
test_size=5,
gap=0.3,
plot_data=False,
one_hot=False,
include_sample_total=True,
)

plt.figure(figsize=(5, 5))
plt.ylim(0, 2 * np.pi)
plt.xlim(0, 2 * np.pi)
plt.imshow(
interpolation="nearest",
origin="lower",
cmap="RdBu",
extent=[0, 2 * np.pi, 0, 2 * np.pi],
)

plt.scatter(
train_features[np.where(train_labels[:] == 0), 0],
train_features[np.where(train_labels[:] == 0), 1],
marker="s",
facecolors="w",
edgecolors="b",
label="A train",
)
plt.scatter(
train_features[np.where(train_labels[:] == 1), 0],
train_features[np.where(train_labels[:] == 1), 1],
marker="o",
facecolors="w",
edgecolors="r",
label="B train",
)
plt.scatter(
test_features[np.where(test_labels[:] == 0), 0],
test_features[np.where(test_labels[:] == 0), 1],
marker="s",
facecolors="b",
edgecolors="w",
label="A test",
)
plt.scatter(
test_features[np.where(test_labels[:] == 1), 0],
test_features[np.where(test_labels[:] == 1), 1],
marker="o",
facecolors="r",
edgecolors="w",
label="B test",
)

plt.show()


With our training and testing datasets ready, we set up the QuantumKernel class to calculate a kernel matrix using the ZZFeatureMap, and the BasicAer qasm_simulator using 1024 shots.

[3]:

adhoc_feature_map = ZZFeatureMap(feature_dimension=adhoc_dimension, reps=2, entanglement="linear")

BasicAer.get_backend("qasm_simulator"), shots=1024, seed_simulator=seed, seed_transpiler=seed
)



The scikit-learn svc algorithm allows us to define a custom kernel in two ways: by providing the kernel as a callable function or by precomputing the kernel matrix. We can do either of these using the QuantumKernel class in qiskit.

The following code gives the kernel as a callable function:

[4]:

adhoc_svc = SVC(kernel=adhoc_kernel.evaluate)

print(f"Callable kernel classification test score: {adhoc_score}")

Callable kernel classification test score: 1.0


The following code precomputes and plots the training and testing kernel matrices before providing them to the scikit-learn svc algorithm:

[5]:

adhoc_matrix_train = adhoc_kernel.evaluate(x_vec=train_features)

fig, axs = plt.subplots(1, 2, figsize=(10, 5))
axs[0].imshow(
)
plt.show()

print(f"Precomputed kernel classification test score: {adhoc_score}")

Precomputed kernel classification test score: 1.0


qiskit also contains the qsvc class that extends the sklearn svc class, that can be used as follows:

[6]:

qsvc = QSVC(quantum_kernel=adhoc_kernel)
qsvc.fit(train_features, train_labels)
qsvc_score = qsvc.score(test_features, test_labels)

print(f"QSVC classification test score: {qsvc_score}")

QSVC classification test score: 1.0


## Clustering¶

For our clustering example, we will again use the ad hoc dataset as described in Supervised learning with quantum enhanced feature spaces, and the scikit-learn spectral clustering algorithm.

We will regenerate the dataset with a larger gap between the two classes, and as clustering is an unsupervised machine learning task, we don’t need a test sample.

[7]:

adhoc_dimension = 2
training_size=25,
test_size=0,
gap=0.6,
plot_data=False,
one_hot=False,
include_sample_total=True,
)

plt.figure(figsize=(5, 5))
plt.ylim(0, 2 * np.pi)
plt.xlim(0, 2 * np.pi)
plt.imshow(
interpolation="nearest",
origin="lower",
cmap="RdBu",
extent=[0, 2 * np.pi, 0, 2 * np.pi],
)
plt.scatter(
train_features[np.where(train_labels[:] == 0), 0],
train_features[np.where(train_labels[:] == 0), 1],
marker="s",
facecolors="w",
edgecolors="b",
label="A",
)
plt.scatter(
train_features[np.where(train_labels[:] == 1), 0],
train_features[np.where(train_labels[:] == 1), 1],
marker="o",
facecolors="w",
edgecolors="r",
label="B",
)

plt.show()


We again set up the QuantumKernel class to calculate a kernel matrix using the ZZFeatureMap, and the BasicAer qasm_simulator using 1024 shots.

[8]:

adhoc_feature_map = ZZFeatureMap(feature_dimension=adhoc_dimension, reps=2, entanglement="linear")

BasicAer.get_backend("qasm_simulator"), shots=1024, seed_simulator=seed, seed_transpiler=seed
)



The scikit-learn spectral clustering algorithm allows us to define a [custom kernel] in two ways: by providing the kernel as a callable function or by precomputing the kernel matrix. Using the QuantumKernel class in qiskit, we can only use the latter.

The following code precomputes and plots the kernel matrices before providing it to the scikit-learn spectral clustering algorithm, and scoring the labels using normalized mutual information, since we a priori know the class labels.

[9]:

adhoc_matrix = adhoc_kernel.evaluate(x_vec=train_features)

plt.figure(figsize=(5, 5))
plt.show()

cluster_score = normalized_mutual_info_score(cluster_labels, train_labels)

print(f"Clustering score: {cluster_score}")

Clustering score: 0.7287008798015746


scikit-learn has other algorithms that can use a precomputed kernel matrix, here are a few:

[10]:

import qiskit.tools.jupyter

%qiskit_version_table


### Version Information

Qiskit SoftwareVersion
qiskit-terra0.20.1
qiskit-aer0.10.4
qiskit-machine-learning0.4.0
System information
Python version3.8.12
Python compilerGCC 9.3.0
Python builddefault, Oct 18 2021 14:07:50
OSLinux
CPUs2
Memory (Gb)6.783607482910156
Fri Apr 29 17:24:03 2022 UTC