Note

Run interactively in jupyter notebook.

# 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)
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')

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)
y_vec=train_features)

fig, axs = plt.subplots(1, 2, figsize=(10, 5))
interpolation='nearest', origin='upper', cmap='Blues')
interpolation='nearest', origin='upper', cmap='Reds')
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)


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)
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')

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 apriori 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.7287008798015754


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
QiskitNone
Terra0.17.0
Aer0.8.0
IgnisNone
AquaNone
IBM Q ProviderNone
System information
Python3.8.8 (default, Feb 19 2021, 19:42:00) [GCC 9.3.0]
OSLinux
CPUs2
Memory (Gb)6.791343688964844
Fri Apr 02 20:40:49 2021 UTC

### This code is a part of Qiskit

obtain a copy of this license in the LICENSE.txt file in the root directory

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.