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

注釈

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

Qiskit機械学習モデルの保存、読み込み、継続的なトレーニング

このチュートリアルでは、Qiskit機械学習モデルを保存およびロードする方法を示します。モデルを保存する機能は非常に重要です。特に、実際のハードウェアでモデルをトレーニングするためにかなりの時間が費やされている場合です。また、以前に保存したモデルのトレーニングを再開する方法も示します。

このチュートリアルでは、次の方法について説明します。

  • 単純なデータセットを生成し、それをトレーニング/テストデータセットに分割してプロットします

  • モデルをトレーニングして保存する

  • 保存したモデルをロードしてトレーニングを再開します

  • モデルのパフォーマンスを評価する

  • PyTorchハイブリッドモデル

First off, we start from the required imports. We’ll heavily use SciKit-Learn on the data preparation step. In the next cell we also fix a random seed for reproducibility purposes.

[1]:
import matplotlib.pyplot as plt
import numpy as np
from qiskit.algorithms.optimizers import COBYLA
from qiskit.circuit.library import RealAmplitudes
from qiskit.primitives import Sampler
from qiskit.utils import algorithm_globals
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder, MinMaxScaler

from qiskit_machine_learning.algorithms.classifiers import VQC

from IPython.display import clear_output

algorithm_globals.random_seed = 42

We will be using two quantum simulators, in particular, two instances of the Sampler primitive. We’ll start training on the first one, then will resume training on the second one. The approach shown in this tutorial can be used to train a model on a real hardware available on the cloud and then re-use the model for inference on a local simulator.

[2]:
sampler1 = Sampler()

sampler2 = Sampler()

1. データセットの準備

次のステップは、データセットを準備することです。ここでは、他のチュートリアルと同じ方法でいくつかのデータを生成します。違いは、生成されたデータにいくつかの変換を適用することです。 40 のサンプルを生成し、各サンプルには 2 の特徴があるため、私たちの特徴は形状 (40, 2) の配列です。ラベルは、列ごとに特徴を合計することによって取得され、合計が 1 より大きい場合、このサンプルは 1 および 0 としてラベル付けされます。

[3]:
num_samples = 40
num_features = 2
features = 2 * algorithm_globals.random.random([num_samples, num_features]) - 1
labels = 1 * (np.sum(features, axis=1) >= 0)  # in { 0,  1}

次に、SciKit-Learnの MinMaxScaler を適用して、特徴量を [0, 1] の範囲に削減します。この変換を適用すると、モデルトレーニングの収束が向上します。

[4]:
features = MinMaxScaler().fit_transform(features)
features.shape
[4]:
(40, 2)

Let’s take a look at the features of the first 5 samples of our dataset after the transformation.

[5]:
features[0:5, :]
[5]:
array([[0.79067335, 0.44566143],
       [0.88072937, 0.7126244 ],
       [0.06741233, 1.        ],
       [0.7770372 , 0.80422817],
       [0.10351936, 0.45754615]])

トレーニングするモデルとして、VQC または変分量子分類器を選択します。このモデルは、デフォルトでワンホットエンコードされたラベルを使用するため、 {0, 1} のセットに含まれるラベルをワンホット表現に変換する必要があります。この変換にもSciKit-Learnを採用しています。入力配列は、最初に (num_samples, 1) に再変換する必要があることに注意してください。 OneHotEncoder エンコーダーは一次元配列では機能せず、ラベルは一次元配列です。この場合、ユーザーは、配列に特徴量がひとつしかない(この場合!)か、サンプルがひとつあるかを判断する必要があります。また、デフォルトでは、エンコーダーはスパース配列を返しますが、データセットプロットの場合、密な配列を使用する方が簡単なので、 sparseFalse に設定します。

[6]:
labels = OneHotEncoder(sparse=False).fit_transform(labels.reshape(-1, 1))
labels.shape
[6]:
(40, 2)

Let’s take a look at the labels of the first 5 labels of the dataset. The labels should be one-hot encoded.

[7]:
labels[0:5, :]
[7]:
array([[0., 1.],
       [0., 1.],
       [0., 1.],
       [0., 1.],
       [1., 0.]])

次に、データセットをトレーニングデータセットとテストデータセットの2つの部分に分割します。経験則として、完全なデータセットの80%はトレーニング部分に、20%はテスト部分に入れる必要があります。トレーニングデータセットには 30 のサンプルがあります。テストデータセットは、モデルが見えないデータでどの程度適切に動作するかを検証するためにモデルがトレーニングされている場合に、一度だけ使用する必要があります。SciKit-Learnの train_test_split を採用しています。

[8]:
train_features, test_features, train_labels, test_labels = train_test_split(
    features, labels, train_size=30, random_state=algorithm_globals.random_seed
)
train_features.shape
[8]:
(30, 2)

Now it is time to see how our dataset looks like. Let’s plot it.

[9]:
def plot_dataset():
    plt.scatter(
        train_features[np.where(train_labels[:, 0] == 0), 0],
        train_features[np.where(train_labels[:, 0] == 0), 1],
        marker="o",
        color="b",
        label="Label 0 train",
    )
    plt.scatter(
        train_features[np.where(train_labels[:, 0] == 1), 0],
        train_features[np.where(train_labels[:, 0] == 1), 1],
        marker="o",
        color="g",
        label="Label 1 train",
    )

    plt.scatter(
        test_features[np.where(test_labels[:, 0] == 0), 0],
        test_features[np.where(test_labels[:, 0] == 0), 1],
        marker="o",
        facecolors="w",
        edgecolors="b",
        label="Label 0 test",
    )
    plt.scatter(
        test_features[np.where(test_labels[:, 0] == 1), 0],
        test_features[np.where(test_labels[:, 0] == 1), 1],
        marker="o",
        facecolors="w",
        edgecolors="g",
        label="Label 1 test",
    )

    plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left", borderaxespad=0.0)
    plt.plot([1, 0], [0, 1], "--", color="black")


plot_dataset()
plt.show()
../_images/tutorials_09_saving_and_loading_models_18_0.png

上記のプロットでは、次のようになります。

  • 青に塗られた点は、 0 というラベルの付いたトレーニングデータセットからのサンプルです。

  • 青い枠線だけの点は、 0 というラベルの付いたテストデータセットからのサンプルです。

  • 緑に塗られた点は、 1 というラベルの付いたトレーニングデータセットからのサンプルです。

  • 緑色の枠線だけの点は、 1 というラベルの付いたテストデータセットからのサンプルです。

We’ll train our model using solid dots and verify it using empty dots.

2. モデルをトレーニングして保存する

We’ll train our model in two steps. On the first step we train our model in 20 iterations.

[10]:
maxiter = 20

目的関数の値を格納するためのコールバック用の空の配列を作成します。

[11]:
objective_values = []

ニューラル・ネットワーク分類(Neural Network Classifier & Regressor)のチュートリアルのコールバック関数を再利用して、反復と目的関数の値をプロットし、いくつかの微調整を加えて、各ステップで目的値をプロットします。

[12]:
# callback function that draws a live plot when the .fit() method is called
def callback_graph(_, objective_value):
    clear_output(wait=True)
    objective_values.append(objective_value)

    plt.title("Objective function value against iteration")
    plt.xlabel("Iteration")
    plt.ylabel("Objective function value")

    stage1_len = np.min((len(objective_values), maxiter))
    stage1_x = np.linspace(1, stage1_len, stage1_len)
    stage1_y = objective_values[:stage1_len]

    stage2_len = np.max((0, len(objective_values) - maxiter))
    stage2_x = np.linspace(maxiter, maxiter + stage2_len - 1, stage2_len)
    stage2_y = objective_values[maxiter : maxiter + stage2_len]

    plt.plot(stage1_x, stage1_y, color="orange")
    plt.plot(stage2_x, stage2_y, color="purple")
    plt.show()


plt.rcParams["figure.figsize"] = (12, 6)

上記のように、 VQC モデルをトレーニングし、 maxiter パラメーターの選択された値を使用して COBYLA をオプティマイザーとして設定します。次に、モデルのパフォーマンスを評価して、モデルがどの程度適切にトレーニングされたかを確認します。次に、このモデルをファイルに保存します。2番目のステップでは、このモデルをロードし、引き続き作業します。

ここでは、最適化を開始する最初のポイントを修正するために、手動で ansatzを作成します。

[13]:
original_optimizer = COBYLA(maxiter=maxiter)

ansatz = RealAmplitudes(num_features)
initial_point = np.asarray([0.5] * ansatz.num_parameters)

モデルを作成し、sampler を先ほど作成した最初のsampler に設定します。

[14]:
original_classifier = VQC(
    ansatz=ansatz, optimizer=original_optimizer, callback=callback_graph, sampler=sampler1
)

次に、モデルをトレーニングします。

[15]:
original_classifier.fit(train_features, train_labels)
../_images/tutorials_09_saving_and_loading_models_31_0.png
[15]:
<qiskit_machine_learning.algorithms.classifiers.vqc.VQC at 0x17b8cad4d08>

Let’s see how well our model performs after the first step of training.

[16]:
print("Train score", original_classifier.score(train_features, train_labels))
print("Test score ", original_classifier.score(test_features, test_labels))
Train score 0.8
Test score  0.9

次に、モデルを保存します。任意のファイル名を選択できます。ファイル名に拡張子が指定されていない場合、 save メソッドは拡張子を追加しないことに注意してください。

[17]:
original_classifier.save("vqc_classifier.model")

3. モデルをロードし、トレーニングを続行する

モデルをロードするには、ユーザーは対応するモデルクラスのクラスメソッド load を呼び出す必要があります。 私たちの場合は VQC です。モデルを保存した前のセクションで使用したのと同じファイル名を渡します。

[18]:
loaded_classifier = VQC.load("vqc_classifier.model")

次に、このモデルをさらに別のシミュレーターで学習できるように変更したいと思います。そのために、 warm_start プロパティを設定します。このプロパティを True に設定し、再び fit() を呼び出すと、モデルは前回のフィットで得られた重みを使用して、新しいフィットを開始します。また、基礎となるネットワークの sampler プロパティを、チュートリアルの最初に作成した Sampler primitive の2番目のインスタンスに設定します。最後に、新しいオプティマイザーを作成し、 maxiter80 に設定して、反復処理の合計回数を 100 に設定します。

[19]:
loaded_classifier.warm_start = True
loaded_classifier.neural_network.sampler = sampler2
loaded_classifier.optimizer = COBYLA(maxiter=80)

次に、前のセクションで終了した状態からモデルのトレーニングを続けます。

[20]:
loaded_classifier.fit(train_features, train_labels)
../_images/tutorials_09_saving_and_loading_models_41_0.png
[20]:
<qiskit_machine_learning.algorithms.classifiers.vqc.VQC at 0x17b8cda4808>
[21]:
print("Train score", loaded_classifier.score(train_features, train_labels))
print("Test score", loaded_classifier.score(test_features, test_labels))
Train score 0.9
Test score 0.8

Let’s see which data points were misclassified. First, we call predict to infer predicted values from the training and test features.

[22]:
train_predicts = loaded_classifier.predict(train_features)
test_predicts = loaded_classifier.predict(test_features)

データセット全体をプロットし、誤って分類されたポイントを強調表示します。

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

plot_dataset()

# plot misclassified data points
plt.scatter(
    train_features[np.all(train_labels != train_predicts, axis=1), 0],
    train_features[np.all(train_labels != train_predicts, axis=1), 1],
    s=200,
    facecolors="none",
    edgecolors="r",
    linewidths=2,
)
plt.scatter(
    test_features[np.all(test_labels != test_predicts, axis=1), 0],
    test_features[np.all(test_labels != test_predicts, axis=1), 1],
    s=200,
    facecolors="none",
    edgecolors="r",
    linewidths=2,
)
[23]:
<matplotlib.collections.PathCollection at 0x17b8cb4f5c8>
../_images/tutorials_09_saving_and_loading_models_46_1.png

したがって、大きなデータセットまたは大きなモデルがある場合は、このチュートリアルに示すように、複数のステップでトレーニングできます。

4. PyTorchハイブリッドモデル

ハイブリッドモデルを保存およびロードするには、TorchConnector を使用する場合、モデルの保存およびロードに関する PyTorch の推奨事項に従ってください。 詳細については、 こちら のPyTorch Connectorチュートリアルを参照してください。ここでは、短いスニペットでその方法を示しています。

この疑似的なコードを見て、アイデアを見つけてください。

# create a QNN and a hybrid model
qnn = create_qnn()
model = Net(qnn)
# ... train the model ...

# save the model
torch.save(model.state_dict(), "model.pt")

# create a new model
new_qnn = create_qnn()
loaded_model = Net(new_qnn)
loaded_model.load_state_dict(torch.load("model.pt"))
[24]:
import qiskit.tools.jupyter

%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
qiskit-terra0.22.0
qiskit-aer0.11.1
qiskit-ignis0.7.0
qiskit0.33.0
qiskit-machine-learning0.5.0
System information
Python version3.7.9
Python compilerMSC v.1916 64 bit (AMD64)
Python builddefault, Aug 31 2020 17:10:11
OSWindows
CPUs4
Memory (Gb)31.837730407714844
Thu Nov 03 10:21:38 2022 GMT Standard Time

This code is a part of Qiskit

© Copyright IBM 2017, 2022.

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.