量子カーネルトレーニング
使用量の目安: Eagle r3 プロセッサで1分未満(注意: これはあくまで目安です。実際の実行時間は異なる場合があります。)
背景
このチュートリアルでは、二値分類に使用される量子カーネル行列のエントリを評価するための Qiskit pattern を構築する方法を紹介します。Qiskit patterns の詳細や、Qiskit Serverless を使用してクラウドにデプロイしマネージド実行を行う方法については、IBM Quantum® Platform のドキュメントページをご覧ください。
要件
このチュートリアルを始める前に、以下がインストールされていることを確認してください:
- Qiskit SDK v1.0 以降(visualization サポートを含む)
- Qiskit Runtime v0.22 以降 (
pip install qiskit-ibm-runtime)
セットアップ
!wget https://raw.githubusercontent.com/qiskit-community/prototype-quantum-kernel-training/main/data/dataset_graph7.csv
# General Imports and helper functions
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from qiskit.circuit import Parameter, ParameterVector, QuantumCircuit
from qiskit.circuit.library import UnitaryOverlap
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, Sampler
# from qiskit_serverless import IBMServerlessClient, QiskitFunction
from qiskit_ibm_catalog import QiskitServerless, QiskitFunction
def visualize_counts(res_counts, num_qubits, num_shots):
"""Visualize the outputs from the Qiskit Sampler primitive."""
zero_prob = res_counts.get(0, 0.0)
top_10 = dict(
sorted(res_counts.items(), key=lambda item: item[1], reverse=True)[
:10
]
)
top_10.update({0: zero_prob})
by_key = dict(sorted(top_10.items(), key=lambda item: item[0]))
x_vals, y_vals = list(zip(*by_key.items()))
x_vals = [bin(x_val)[2:].zfill(num_qubits) for x_val in x_vals]
y_vals_prob = []
for t in range(len(y_vals)):
y_vals_prob.append(y_vals[t] / num_shots)
y_vals = y_vals_prob
plt.bar(x_vals, y_vals)
plt.xticks(rotation=75)
plt.title("Results of sampling")
plt.xlabel("Measured bitstring")
plt.ylabel("Probability")
plt.show()
def get_training_data():
"""Read the training data."""
df = pd.read_csv("dataset_graph7.csv", sep=",", header=None)
training_data = df.values[:20, :]
ind = np.argsort(training_data[:, -1])
X_train = training_data[ind][:, :-1]
return X_train
7[1A[1G[27G[Files: 0 Bytes: 0 [0 B/s] Re]87[2A[1G[27G[https://raw.githubusercontent.]87[1S[3A[1G[0JSaving 'dataset_graph7.csv.1'
87[2A[1Gdataset_graph7.csv.1 100% [=============================>] 20.25K --.-KB/s87[1S[3A[1G[0JHTTP response 200 [https://raw.githubusercontent.com/qiskit-community/prototype-quantum-kernel-training/main/data/dataset_graph7.csv]
87[2A[1Gdataset_graph7.csv.1 100% [=============================>] 20.25K --.-KB/s87[1A[1G[27G[Files: 1 Bytes: 20.25K [93.33]8[m[m[m[m
ステップ 1: 古典的な入力を量子問題にマッピングする
- 入力: トレーニングデータセット
- 出力: カーネル行列のエントリを計算するための抽象回路
カーネル行列の1つのエントリを評価するために使用する量子回路を作成します。入力データを使用して、回路のパラメータ化されたゲートの回転角を決定します。ここでは、データサンプル x1=14 と x2=19 を使用します。
注意: このチュートリアルで使用するデータセットはこちらからダウンロードできます。
# Prepare training data
X_train = get_training_data()
# Empty kernel matrix
num_samples = np.shape(X_train)[0]
kernel_matrix = np.full((num_samples, num_samples), np.nan)
# Prepare feature map for computing overlap
num_features = np.shape(X_train)[1]
num_qubits = int(num_features / 2)
entangler_map = [[0, 2], [3, 4], [2, 5], [1, 4], [2, 3], [4, 6]]
fm = QuantumCircuit(num_qubits)
training_param = Parameter("θ")
feature_params = ParameterVector("x", num_qubits * 2)
fm.ry(training_param, fm.qubits)
for cz in entangler_map:
fm.cz(cz[0], cz[1])
for i in range(num_qubits):
fm.rz(-2 * feature_params[2 * i + 1], i)
fm.rx(-2 * feature_params[2 * i], i)
# Assign tunable parameter to known optimal value and set the data params for first two samples
x1 = 14
x2 = 19
unitary1 = fm.assign_parameters(list(X_train[x1]) + [np.pi / 2])
unitary2 = fm.assign_parameters(list(X_train[x2]) + [np.pi / 2])
# Create the overlap circuit
overlap_circ = UnitaryOverlap(unitary1, unitary2)
overlap_circ.measure_all()
overlap_circ.draw("mpl", scale=0.6, style="iqp")
ステップ 2: 量子ハードウェア実行のために問題を最適化する
- 入力: 特定のバックエンドに最適化されていない抽象回路
- 出力: 選択したQPUに最適化されたターゲット回路とオブザーバブル
Qiskit の generate_preset_pass_manager 関数を使用して、実験を実行する予定のQPUに対する回路の最適化ルーチンを指定します。optimization_level=3 に設定しており、これは最高レベルの最適化を提供するプリセットパスマネージャを使用することを意味します。
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=overlap_circ.num_qubits
)
pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
overlap_ibm = pm.run(overlap_circ)
overlap_ibm.draw("mpl", scale=0.6, idle_wires=False, fold=-1, style="iqp")
ステップ 3: Qiskit プリミティブを使用して実行する
- 入力: ターゲット回路
- 出力: 擬似確率分布
Qiskit Runtime の Sampler プリミティブを使用して、回路のサンプリングから得られる状態の擬似確率分布を再構築します。カーネル行列を生成するタスクでは、|0> 状態を測定する確率に特に注目します。
このデモでは、qiskit-ibm-runtime プリミティブを使用してQPU上で実行します。qiskit の状態ベクトルベースのプリミティブで実行するには、Qiskit IBM® Runtime プリミティブを使用しているコードブロックをコメントアウトされたブロックに置き換えてください。
num_shots = 10_000
## Evaluate the problem using statevector-based primitives from Qiskit
# from qiskit.primitives import StatevectorSampler
# sampler = StatevectorSampler()
# results = sampler.run([overlap_circ]).result()
# counts = results[0].data.meas.get_int_counts()
# Evaluate the problem using a QPU via Qiskit IBM Runtime
sampler = Sampler(mode=backend)
results = sampler.run([overlap_ibm]).result()
counts = results[0].data.meas.get_int_counts()
visualize_counts(counts, num_qubits, num_shots)
ステップ 4: 後処理を行い、目的の古典形式で結果を返す
- 入力: 確率分布
- 出力: 単一のカーネル行列要素
オーバーラップ回路で |0> を測定する確率を計算し、この特定のオーバーラップ回路が表すサンプルに対応する位置(行15、列20)のカーネル行列を埋めます。この可視化では、濃い赤色ほどフィデリティが1.0に近いことを示しています。カーネル行列全体を埋めるには、各エントリに対して量子実験を実行する必要があります。
# Calculate the fidelity, or the probability to measure 0
kernel_matrix[x1, x2] = counts.get(0, 0.0) / num_shots
print(f"Fidelity: {kernel_matrix[x1, x2]}")
Fidelity: 0.1279
Qiskit パターンをクラウドにデプロイする
これを行うには、上記のソースコードをファイル ./source/generate_kernel_entry.py に移動し、入力を受け取り最終的な解を返すスクリプトでコードをラップし、最後に Qiskit Serverless の QiskitFunction クラスを使用してリモートクラスタにアップロードします。外部依存関係の指定、入力引数の受け渡しなどの詳細については、Qiskit Serverless ガイドをご確認ください。
パターンへの入力はデータサンプルのペア x1 と x2 です。出力は2つのサンプル間のフィデリティです。この値は、これら2つのサンプルに対応するカーネル行列のエントリを埋めるために使用されます。
serverless = QiskitServerless()
kernel_entry_pattern = QiskitFunction(
title="generate-kernel-entry",
entrypoint="generate_kernel_entry.py",
working_dir="./source/",
)
serverless.upload(kernel_entry_pattern)
Qiskit パターンをマネージドサービスとして実行する
パターンをクラウドにアップロードしたら、IBMServerlessProvider クライアントを使用して簡単に実行できます。簡略化のため、クラウド環境では厳密な量子シミュレータを使用するので、計算されるフィデリティは厳密な値 となります。
generate_kernel_entry = serverless.load("generate-kernel-entry")
job = generate_kernel_entry.run(
sample1=list(X_train[x1]), sample2=list(X_train[x2])
)
kernel_matrix[x1, x2] = job.result()["fidelity"]
print(f"fidelity: {kernel_matrix[x1, x2]}")
チュートリアルアンケート
このチュートリアルに関するフィードバックをお寄せいただくため、短いアンケートにご協力ください。皆様の ご意見は、コンテンツの提供およびユーザーエクスペリエンスの向上に役立てさせていただきます。