French
Langues
English
Bengali
French
Hindi
Italian
Japanese
Korean
Malayalam
Russian
Spanish
Tamil
Turkish
Vietnamese
Shortcuts

Note

Cette page a été générée à partir de docs/tutorials/02_neural_network_classifier_and_regressor.ipynb.

Classification et régression de réseau de neurones

Dans ce tutoriel, nous montrons comment utiliser NeuralNetworkClassifier et NeuralNetworkRegressor. Les deux prennent comme entrée (Quantique) NeuralNetwork et l’exploitent dans un contexte spécifique. Dans les deux cas, nous proposons également pour plus de commodité, une variante préconfigurée : Le Classificateur Variationnel Quantique (VQC) et le Régresseur Variationnel Quantique (VQR). Le didacticiel est structuré comme suit :

  1. Classification <#Classification> __

    • Classification avec OpflowQNN

    • Classification avec CircuitQNN

    • Classifieur Variationnel Quantique (VQC)

  2. Régression <#Regression> __

    • Régression avec OpflowQNN

    • Régresseur Variationnel Quantique (VQR)

[1]:
import numpy as np
import matplotlib.pyplot as plt

from qiskit import Aer, QuantumCircuit
from qiskit.opflow import Z, I, StateFn
from qiskit.utils import QuantumInstance
from qiskit.circuit import Parameter
from qiskit.circuit.library import RealAmplitudes, ZZFeatureMap
from qiskit.algorithms.optimizers import COBYLA, L_BFGS_B

from qiskit_machine_learning.neural_networks import TwoLayerQNN, CircuitQNN
from qiskit_machine_learning.algorithms.classifiers import NeuralNetworkClassifier, VQC
from qiskit_machine_learning.algorithms.regressors import NeuralNetworkRegressor, VQR

from typing import Union

from qiskit_machine_learning.exceptions import QiskitMachineLearningError

from IPython.display import clear_output
[2]:
quantum_instance = QuantumInstance(Aer.get_backend('aer_simulator'), shots=1024)

Classification

Nous préparons un ensemble de données de classification simple pour illustrer les algorithmes suivants.

[3]:
num_inputs = 2
num_samples = 20
X = 2*np.random.rand(num_samples, num_inputs) - 1
y01 = 1*(np.sum(X, axis=1) >= 0)  # in { 0,  1}
y = 2*y01-1                       # in {-1, +1}
y_one_hot = np.zeros((num_samples, 2))
for i in range(num_samples):
    y_one_hot[i, y01[i]] = 1

for x, y_target in zip(X, y):
    if y_target == 1:
        plt.plot(x[0], x[1], 'bo')
    else:
        plt.plot(x[0], x[1], 'go')
plt.plot([-1, 1], [1, -1], '--', color='black')
plt.show()
../_images/tutorials_02_neural_network_classifier_and_regressor_4_0.png

Classification avec OpflowQNN

Premièrement, nous montrons comment OpflowQNN peut être utilisé pour la classification dans un NeuralNetworkClassifier. Dans ce contexte, OpflowQNN est censé renvoyer une sortie unidimensionnelle dans \([ -1, + 1 ]\). Cela ne fonctionne que pour la classification binaire et nous affectons les deux classes à :math:` { -1, + 1}`. Pour plus de commodité, nous utilisons le TwoLayerQNN, qui est un type spécial de OpflowQNN défini via une carte de features et un ansatz.

[4]:
# construct QNN
opflow_qnn = TwoLayerQNN(num_inputs, quantum_instance=quantum_instance)
[5]:
# QNN maps inputs to [-1, +1]
opflow_qnn.forward(X[0, :], np.random.rand(opflow_qnn.num_weights))
[5]:
array([[0.47265625]])

Nous allons ajouter une fonction de rappel appelée callback_graph. Elle sera appelée pour chaque itération de l’optimiseur et recevra deux paramètres : les poids actuels et la valeur de la fonction objectif à ces pondérations. Pour notre fonction, nous ajoutons la valeur de la fonction objectif à un tableau pour que nous puissions tracer la valeur de l’itération par rapport à la fonction objectif et mettre à jour le graphe avec chaque itération. Cependant, vous pouvez faire ce que vous voulez avec une fonction de rappel tant qu’elle obtient les deux paramètres mentionnés.

[6]:
# callback function that draws a live plot when the .fit() method is called
def callback_graph(weights, obj_func_eval):
    clear_output(wait=True)
    objective_func_vals.append(obj_func_eval)
    plt.title("Objective function value against iteration")
    plt.xlabel("Iteration")
    plt.ylabel("Objective function value")
    plt.plot(range(len(objective_func_vals)), objective_func_vals)
    plt.show()
[7]:
# construct neural network classifier
opflow_classifier = NeuralNetworkClassifier(opflow_qnn, optimizer=COBYLA(), callback=callback_graph)
[8]:
# create empty array for callback to store evaluations of the objective function
objective_func_vals = []
plt.rcParams["figure.figsize"] = (12, 6)

# fit classifier to data
opflow_classifier.fit(X, y)

# return to default figsize
plt.rcParams["figure.figsize"] = (6, 4)

# score classifier
opflow_classifier.score(X, y)
../_images/tutorials_02_neural_network_classifier_and_regressor_11_0.png
[8]:
0.5
[9]:
# evaluate data points
y_predict = opflow_classifier.predict(X)

# plot results
# red == wrongly classified
for x, y_target, y_p in zip(X, y, y_predict):
    if y_target == 1:
        plt.plot(x[0], x[1], 'bo')
    else:
        plt.plot(x[0], x[1], 'go')
    if y_target != y_p:
        plt.scatter(x[0], x[1], s=200, facecolors='none', edgecolors='r', linewidths=2)
plt.plot([-1, 1], [1, -1], '--', color='black')
plt.show()
../_images/tutorials_02_neural_network_classifier_and_regressor_12_0.png

Classification avec CircuitQNN

Ensuite, nous montrons comment CircuitQNN peut être utilisé pour la classification à l’intérieur d’un NeuralNetworkClassifier. Dans ce contexte, le CircuitQNN est censé renvoyer le vecteur de probabilité \(d\)-dimensionnel comme sortie, où \(d\) indique le nombre de classes. L’échantillonnage d’un QuantumCircuit donne automatiquement lieu à une distribution de probabilité et il suffit de définir une correspondance entre les chaînes de bits mesurées et les différentes classes. Pour la classification binaire, nous utilisons la correspondance de parité.

[10]:
# construct feature map
feature_map = ZZFeatureMap(num_inputs)

# construct ansatz
ansatz = RealAmplitudes(num_inputs, reps=1)

# construct quantum circuit
qc = QuantumCircuit(num_inputs)
qc.append(feature_map, range(num_inputs))
qc.append(ansatz, range(num_inputs))
qc.decompose().draw(output='mpl')
[10]:
../_images/tutorials_02_neural_network_classifier_and_regressor_14_0.png
[11]:
# parity maps bitstrings to 0 or 1
def parity(x):
    return '{:b}'.format(x).count('1') % 2
output_shape = 2  # corresponds to the number of classes, possible outcomes of the (parity) mapping.
[12]:
# construct QNN
circuit_qnn = CircuitQNN(circuit=qc,
                         input_params=feature_map.parameters,
                         weight_params=ansatz.parameters,
                         interpret=parity,
                         output_shape=output_shape,
                         quantum_instance=quantum_instance)
[13]:
# construct classifier
circuit_classifier = NeuralNetworkClassifier(neural_network=circuit_qnn,
                                             optimizer=COBYLA(),
                                             callback=callback_graph)
[14]:
# create empty array for callback to store evaluations of the objective function
objective_func_vals = []
plt.rcParams["figure.figsize"] = (12, 6)

# fit classifier to data
circuit_classifier.fit(X, y01)

# return to default figsize
plt.rcParams["figure.figsize"] = (6, 4)

# score classifier
circuit_classifier.score(X, y01)
../_images/tutorials_02_neural_network_classifier_and_regressor_18_0.png
[14]:
0.65
[15]:
# evaluate data points
y_predict = circuit_classifier.predict(X)

# plot results
# red == wrongly classified
for x, y_target, y_p in zip(X, y01, y_predict):
    if y_target == 1:
        plt.plot(x[0], x[1], 'bo')
    else:
        plt.plot(x[0], x[1], 'go')
    if y_target != y_p:
        plt.scatter(x[0], x[1], s=200, facecolors='none', edgecolors='r', linewidths=2)
plt.plot([-1, 1], [1, -1], '--', color='black')
plt.show()
../_images/tutorials_02_neural_network_classifier_and_regressor_19_0.png

Classifieur Variationnel Quantique (VQC)

VQC est une variante spéciale de NeuralNetworkClassifier avec un CircuitQNN. Il applique une correspondance de parité (ou des extensions à plusieurs classes) pour mapper la chaîne de bits à la classification, ce qui donne lieu à un vecteur de probabilité, qui est interprété comme un résultat codé à chaud. Par défaut, il applique la fonction CrossEntropyLoss qui attend les étiquettes données en un format codé à chaud et qui renverra également les prédictions dans ce format.

[16]:
# construct feature map, ansatz, and optimizer
feature_map = ZZFeatureMap(num_inputs)
ansatz = RealAmplitudes(num_inputs, reps=1)

# construct variational quantum classifier
vqc = VQC(feature_map=feature_map,
          ansatz=ansatz,
          loss='cross_entropy',
          optimizer=COBYLA(),
          quantum_instance=quantum_instance,
          callback=callback_graph)
[17]:
# create empty array for callback to store evaluations of the objective function
objective_func_vals = []
plt.rcParams["figure.figsize"] = (12, 6)

# fit classifier to data
vqc.fit(X, y_one_hot)

# return to default figsize
plt.rcParams["figure.figsize"] = (6, 4)

# score classifier
vqc.score(X, y_one_hot)
../_images/tutorials_02_neural_network_classifier_and_regressor_22_0.png
[17]:
0.6
[18]:
# evaluate data points
y_predict = vqc.predict(X)

# plot results
# red == wrongly classified
for x, y_target, y_p in zip(X, y_one_hot, y_predict):
    if y_target[0] == 1:
        plt.plot(x[0], x[1], 'bo')
    else:
        plt.plot(x[0], x[1], 'go')
    if not np.all(y_target == y_p):
        plt.scatter(x[0], x[1], s=200, facecolors='none', edgecolors='r', linewidths=2)
plt.plot([-1, 1], [1, -1], '--', color='black')
plt.show()
../_images/tutorials_02_neural_network_classifier_and_regressor_23_0.png

Régression

Nous préparons un ensemble de données de régression simple pour illustrer les algorithmes suivants.

[19]:
num_samples = 20
eps = 0.2
lb, ub = -np.pi, np.pi
X_ = np.linspace(lb, ub, num=50).reshape(50, 1)
f = lambda x: np.sin(x)

X = (ub - lb)*np.random.rand(num_samples, 1) + lb
y = f(X[:,0]) + eps*(2*np.random.rand(num_samples)-1)

plt.plot(X_, f(X_), 'r--')
plt.plot(X, y, 'bo')
plt.show()
../_images/tutorials_02_neural_network_classifier_and_regressor_25_0.png

Régression avec OpflowQNN

Ici, nous limitons à la régression avec OpflowQNN qui renvoie des valeurs dans \([ -1, +1]\). Des modèles plus complexes et aussi multidimensionnels pourraient être construits, également basés sur CircuitQNN mais cela dépasse la cadre de ce tutoriel.

[20]:
# construct simple feature map
param_x = Parameter('x')
feature_map = QuantumCircuit(1, name='fm')
feature_map.ry(param_x, 0)

# construct simple ansatz
param_y = Parameter('y')
ansatz = QuantumCircuit(1, name='vf')
ansatz.ry(param_y, 0)

# construct QNN
regression_opflow_qnn = TwoLayerQNN(1, feature_map, ansatz, quantum_instance=quantum_instance)
[21]:
# construct the regressor from the neural network
regressor = NeuralNetworkRegressor(neural_network=regression_opflow_qnn,
                                   loss='l2',
                                   optimizer=L_BFGS_B(),
                                   callback=callback_graph)
[22]:
# create empty array for callback to store evaluations of the objective function
objective_func_vals = []
plt.rcParams["figure.figsize"] = (12, 6)

# fit to data
regressor.fit(X, y)

# return to default figsize
plt.rcParams["figure.figsize"] = (6, 4)

# score the result
regressor.score(X, y)
../_images/tutorials_02_neural_network_classifier_and_regressor_29_0.png
[22]:
0.9696567935175576
[23]:
# plot target function
plt.plot(X_, f(X_), 'r--')

# plot data
plt.plot(X, y, 'bo')

# plot fitted line
y_ = regressor.predict(X_)
plt.plot(X_, y_, 'g-')
plt.show()
../_images/tutorials_02_neural_network_classifier_and_regressor_30_0.png

Régression avec le Régresseur Quantique Variationnel (VQR)

A l’instar du VQC pour la classification, le VQR est une variante spéciale de NeuralNetworkRegressor avec un OpflowQNN. Par défaut, il considère la fonction L2Loss pour minimiser l’erreur quadratique moyenne entre les prédictions et les cibles.

[24]:
vqr = VQR(feature_map=feature_map,
          ansatz=ansatz,
          optimizer=L_BFGS_B(),
          quantum_instance=quantum_instance,
          callback=callback_graph)
[25]:
# create empty array for callback to store evaluations of the objective function
objective_func_vals = []
plt.rcParams["figure.figsize"] = (12, 6)

# fit regressor
vqr.fit(X, y)

# return to default figsize
plt.rcParams["figure.figsize"] = (6, 4)

# score result
vqr.score(X, y)
../_images/tutorials_02_neural_network_classifier_and_regressor_33_0.png
[25]:
0.9684356876095139
[26]:
# plot target function
plt.plot(X_, f(X_), 'r--')

# plot data
plt.plot(X, y, 'bo')

# plot fitted line
y_ = vqr.predict(X_)
plt.plot(X_, y_, 'g-')
plt.show()
../_images/tutorials_02_neural_network_classifier_and_regressor_34_0.png
[27]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.19.0.dev0+803bd0d
qiskit-aer0.8.2
qiskit-machine-learning0.3.0
System information
Python3.9.6 (default, Aug 18 2021, 15:44:49) [MSC v.1916 64 bit (AMD64)]
OSWindows
CPUs4
Memory (Gb)11.83804702758789
Sun Aug 29 01:09:16 2021 Hora de verano romance

This code is a part of Qiskit

© Copyright IBM 2017, 2021.

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.