Russian
Языки
English
Bengali
French
Hindi
Italian
Japanese
Korean
Malayalam
Russian
Spanish
Tamil
Turkish
Vietnamese
Shortcuts

Примечание

Страница создана на основе docs/tutorials/02_neural_network_classifier_and_regressor.ipynb.

Классификатор нейросети и регрессор

В этом разделе мы покажем, как используются NeuralNetworkClassifier'' и ``NeuralNetworkRegressor''. Оба принимают на вход (квантовую) ``NeuralNetwork и используют ее в определенном контексте. В обоих случаях мы также предоставляем предварительно настроенные варианты для удобства, Вариационный Квантовый Классификатор (VQC) и Вариационный Квантовый Регрессор (VQR). Руководство построено следующим образом:

  1. Классификация

    • Классификация с помощью » OpflowQNN ` `

    • Классификация с помощью » CircuitQNN ` `

    • Вариационный квантовый классификатор (VQC)

  2. ` Регрессия <#Regression> ` __

    • Регрессия с ` ` OpflowQNN ` `

    • Вариационный Квантовый Регрессор (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, algorithm_globals
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

algorithm_globals.random_seed = 42
[2]:
quantum_instance = QuantumInstance(Aer.get_backend("aer_simulator"), shots=1024)

Классификация

Мы создаем простой набор данных для классификации, чтобы проиллюстрировать следующие алгоритмы.

[3]:
num_inputs = 2
num_samples = 20
X = 2 * algorithm_globals.random.random([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

Классификация с помощью OpflowQNN

Сначала мы покажем, как OpflowQNN можно использовать для классификации в рамках NeuralNetworkClassifier. В этом случае ожидается, что OpflowQNN вернет одномерный результат в \([-1, +1]\). Это работает только для бинарной классификации, и мы присваиваем два класса \(\{-1, +1\}\). Для удобства мы используем TwoLayerQNN, который является специальным типом OpflowQNN, определенным через карту признаков и анзац.

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

Мы добавим функцию обратного вызова под названием callback_graph. Она будет вызываться на каждой итерации оптимизатора и ей будут передаваться два параметра: текущие веса и значение целевой функции при этих весах. Для нашей функции мы добавляем значение объективной функции в массив, чтобы мы могли построить график зависимости итерации от значения объективной функции и обновлять график с каждой итерацией. Однако вы можете делать с функцией обратного вызова все, что захотите, если передадите ей два указанных выше параметра.

[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.8
[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

Классификация с помощью » CircuitQNN ` `

Далее мы покажем, как CircuitQNN можно использовать для классификации в NeuralNetworkClassifier. В этом случае ожидается, что CircuitQNN возвращает \(d\)-размерный вектор вероятности в качестве вывода, где \(d\) обозначает число классов. Выборка из QuantumCircuit автоматически приводит к распределению вероятностей, и нам просто нужно определить соответствие между измеренными битами и разными классами. Для двоичной классификации используется преобра отображение по четности.

[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.75
[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

Вариационный квантовый классификатор (VQC)

VQC - это специальный вариант NeuralNetworkClassifier с CircuitQNN. Он использует отображение по четности (или расширения для нескольких классов) для отображения от битовой строки к классификации, в результате чего получается вектор вероятностей, который интерпретируется как результат, закодированный унитарным кодом. По умолчанию применяется функция CrossEntropyLoss, которая ожидает метки в формате унитарного кода и возвращает предсказания в этом формате.

[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.5
[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

Регрессия

Мы создаем простой регрессионный набор данных для иллюстрации следующих алгоритмов.

[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) * algorithm_globals.random.random([num_samples, 1]) + lb
y = f(X[:, 0]) + eps * (2 * algorithm_globals.random.random(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

Регрессия с ` ` OpflowQNN ` `

Здесь мы ограничимся регрессией с OpflowQNN, которая возвращает значения в \([-1, +1]\). Можно построить более сложные и многомерные модели, также основанные на CircuitQNN, но это выходит за рамки данного руководства.

[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="squared_error",
    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.9763610762801076
[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

Регрессия с помощью Вариационной Квантовой Регрессии (VQR)

По аналогии с VQC для классификации, VQR - это специальный вариант NeuralNetworkRegressor с OpflowQNN. По умолчанию он рассматривает функцию L2Loss для минимизации средней квадратичной ошибки между предсказаниями и целями.

[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.9748043399155905
[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
[28]:
import qiskit.tools.jupyter

%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.19.0
qiskit-aer0.9.0
qiskit-ignis0.7.0
qiskit-ibmq-provider0.17.0
qiskit-aqua0.10.0
qiskit-machine-learning0.3.0
System information
Python3.8.10 (default, Jun 2 2021, 10:49:15) [GCC 9.4.0]
OSLinux
CPUs4
Memory (Gb)7.6849517822265625
Mon Aug 30 16:41:59 2021 IST

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.