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

注釈

このページは docs/tutorials/02_neural_network_classifier_and_regressor.ipynb から生成されました。

ニューラル・ネットワーク分類器と回帰器

このチュートリアルでは、NeuralNetworkClassifierNeuralNetworkRegressor がどのように使用されるかを示します。どちらも入力として (量子) NeuralNetwork を受け取り、特定のコンテキストでそれを活用します。どちらの場合も、利便性のためにあらかじめ設定されたバリエーション、変分量子分類器 (Variational Quantum Classifier, VQC) と変分量子回帰器 (Variational Quantum Regressor, VQR) を提供しています。チュートリアルの構成は以下の通りです。

  1. 分類

    • OpflowQNN による分類

    • CircuitQNN による分類

    • 変分量子分類器 (VQC)

  2. 回帰

    • 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 による分類

まず、 OpflowQNNNeuralNetworkClassifier の中でどのように分類に使われるかを示します。ここでは、 OpflowQNN は、 \([-1, +1]\) の1次元の出力を返すことが期待されています。 これは、二値分類にしか使えないので、2つのクラスを \(\{-1, +1\}\) に割り当てます。ここでは、便宜上、特徴マップとansatzを用いて定義された OpflowQNN の特別なタイプである TwoLayerQNN を使用します。

[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 というコールバック関数を追加します。 これはオプティマイザの反復ごとに呼び出され、現在の重みとその重みでの目的関数の値という、2つのパラメータが渡されます。 ここでは関数に、目的関数の値を配列に追加します。これによって反復と目的関数の値をプロットし、反復ごとにグラフを更新することができます。とはいえ、2つのパラメータが渡される限り、コールバック関数であなたは何でも好きなことをすることができます。

[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 による分類

次に、 CircuitQNNNeuralNetworkClassifier の中でどのように分類に使われるかを示します。ここでは、 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 は、 CircuitQNN を用いた NeuralNetworkClassifier の特別なバリエーションです。これは、パリティー・マッピング(または複数のクラスへの拡張)を適用して、ビット列から分類にマッピングし、その結果、確率ベクトルが得られ、ワンショットでエンコードされた結果として解釈されます。デフォルトでは、 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 による回帰

ここでは、 \([-1, +1]\) の値を返す OpflowQNN を使った回帰に限定します。もっと複雑で多次元のモデルを 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) による回帰

VQR は、分類用の VQC と同様に、 OpflowQNN を用いた NeuralNetworkRegressor の特別な改良版です。デフォルトでは、予測値と目標値の間の平均二乗誤差を最小化するために、 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.