Langkau ke kandungan utama

Latihan kernel kuantum

Anggaran penggunaan: kurang dari satu minit pada pemproses Heron r3 (NOTA: Ini adalah anggaran sahaja. Masa jalan sebenar anda mungkin berbeza.)

Hasil pembelajaran

Selepas melengkapkan tutorial ini, anda dijangka memahami maklumat berikut:

  • Kaedah kernel dan kegunaannya
  • Kernel kuantum dan bagaimana ia boleh menyediakan ruang ciri yang dipertingkatkan
  • Pembinaan litar kernel kuantum
  • Cara melatih kernel kuantum menggunakan corak Qiskit: petakan, optimumkan, laksanakan, dan pasca-proses

Prasyarat

Adalah disyorkan agar anda membiasakan diri dengan kernel kuantum, mengapa ia penting, dan bagaimana ia digunakan dalam amalan.

Adalah juga berguna untuk mempunyai pemahaman asas tentang teori kumpulan.

Latar belakang

Kaedah kernel adalah perkara biasa dalam aplikasi pembelajaran mesin. Dalam konteks ini, "kernel" merujuk kepada matriks kernel atau entri individu di dalamnya. Secara umum, kernel adalah ukuran persamaan antara data yang dikodkan dalam ruang ciri berdimensi tinggi dan boleh digunakan, contohnya, dalam tugasan pengelasan dengan mesin vektor sokongan.

Kaedah kernel kuantum adalah kaedah yang menggunakan komputer kuantum untuk menganggar kernel. Diketahui bahawa komputer kuantum boleh mengkodkan data dalam ruang ciri yang dipertingkatkan secara kuantum, menggantikan analog klasik secara berkesan. Untuk xR\vec{x} \in \mathbb{R} dan Ψ(x)Rd\Psi(\vec{x}) \in \mathbb{R}^{d'}, biasanya dengan d>dd' >d, Ψ(x)\Psi(\vec{x}) adalah peta ciri, xΨ(x)\vec{x} \mapsto \Psi(\vec{x}). Matlamat Ψ(x)\Psi(\vec{x}) adalah untuk menjadikan kategori data dipisahkan oleh satah hiper. Mengambil vektor dalam ruang berpeta-ciri sebagai argumen, fungsi kernel K(x,y)=Ψ(x)Ψ(y)K(\vec{x}, \vec{y}) = \langle{\Psi(\vec{x}) | \Psi(\vec{y}) \rangle{}} mengembalikan hasil darab dalaman mereka: K:RdK: \mathbb{R}^d \rightarrow Rd\mathbb{R}^d. Secara klasik, peta ciri yang diminati adalah yang fungsi kernelnya boleh dinilai dengan mudah; iaitu, apabila hasil darab dalaman dalam ruang berpeta-ciri boleh ditulis dari segi vektor data asal dan Ψ(x)\Psi(\vec{x}) serta Ψ(y)\Psi(\vec{y}) tidak perlu dibina. Dalam kes kernel kuantum, pemetaan ciri dilakukan oleh litar kuantum, dan kernel dianggar menggunakan kebarangkalian pengukuran yang disampel dari litar.

Tutorial ini menunjukkan cara membina corak Qiskit untuk menilai entri dalam matriks kernel kuantum yang digunakan untuk pengelasan binari.

Keperluan

Sebelum memulakan tutorial ini, pastikan anda telah memasang perkara berikut:

  • Qiskit SDK v2.3.1 atau lebih baharu, dengan sokongan visualization
  • Qiskit Runtime v0.44.0 atau lebih baharu (pip install qiskit-ibm-runtime)

Persediaan

# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy pandas qiskit qiskit-ibm-runtime
# General Imports and helper functions
import urllib.request

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 unitary_overlap
from qiskit.primitives import StatevectorSampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

from qiskit_ibm_runtime import QiskitRuntimeService, Sampler

# Download the dataset (portable across platforms)
urllib.request.urlretrieve(
"https://raw.githubusercontent.com/qiskit-community/prototype-quantum-kernel-training/main/data/dataset_graph7.csv",
"dataset_graph7.csv",
)

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

Contoh simulator berskala kecil

Dalam bahagian ini, kita berjalan melalui empat langkah corak Qiskit pada contoh tujuh-qubit masalah pelabelan-koset-dengan-ralat dan menilai satu entri matriks kernel menggunakan primitif StatevectorSampler dari Qiskit. Simulator statevector adalah tepat (sehingga bunyi tembakan) dan menunjukkan kepada kita kaedah dari awal hingga akhir tanpa menggunakan masa QPU. Kita kemudian mengulangi contoh yang sama pada perkakasan sebenar dalam bahagian contoh perkakasan.

Langkah 1: Petakan input klasik kepada masalah kuantum

  • Input: Dataset latihan.
  • Output: Circuit abstrak untuk mengira entri matriks kernel.

Masalah pengelasan binari yang kita cuba selesaikan di sini dirujuk sebagai "pelabelan koset dengan ralat." Dataset latihan input mengandungi struktur kumpulan, terdiri daripada dua koset yang dibentuk oleh kumpulan dan subkumpulan. Kumpulan tersebut diambil sebagai G=SU(2)nG = SU(2)^{\otimes n} untuk qubit, iaitu kumpulan unit istimewa daripada matriks 2×22 \times 2 dan mempunyai kebolehgunaan yang luas dalam alam semula jadi; contohnya, Model Standard fizik zarah. Kita mengambil subkumpulan (penstabil-graf) Sgraph<GS_\text{graph} < G dengan Sgraph={Xik:(k,i)EZk}iV}S_\text{graph} = \langle \{ X_i \otimes _{k:(k,i) \in \mathcal{E}} Z_k\} _{i \in \mathcal{V}} \} \rangle untuk graf dengan tepi E\mathcal{E} dan bucu V\mathcal{V}. Perhatikan bahawa penstabil menetapkan keadaan penstabil supaya Dsψ=ψ, sSgraphD_s | \psi \rangle = | \psi \rangle,~ \forall s \in S_\text{graph}. Akhirnya, kita mentakrifkan dua koset kiri C±=c±SgraphC_\pm = c_\pm S_\text{graph} dengan mengambil dua c±Gc_\pm \in G secara rawak.

Untuk maklumat lanjut tentang dataset dan cara ia dijana, lihat buku nota ini dari Quantum Kernel Training Toolkit.

Kita mencipta litar kuantum yang digunakan untuk menilai satu entri dalam matriks kernel. Data input digunakan untuk menentukan sudut putaran bagi gate-gate berparameter dalam litar. Untuk kesederhanaan, kita akan gunakan sampel data x1=14 dan x2=19.

Nota: Dataset yang digunakan dalam tutorial ini boleh dimuat turun di sini.

# 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 = unitary_overlap(unitary1, unitary2)
overlap_circ.measure_all()
overlap_circ.draw("mpl", scale=0.6, style="iqp")

Output of the previous code cell

Langkah 2: Optimumkan masalah untuk pelaksanaan perkakasan kuantum

  • Input: Circuit abstrak, belum dioptimumkan untuk Backend tertentu.
  • Output: Circuit sasaran, dioptimumkan untuk QPU yang dipilih.

Untuk laluan simulator statevector yang digunakan dalam bahagian ini, tiada pengoptimuman khusus-backend diperlukan: circuit abstrak boleh disampel secara terus. Kita menggunakan langkah ini dalam contoh perkakasan di bawah, di mana circuit ditranspil terhadap QPU sebenar menggunakan generate_preset_pass_manager dengan optimization_level=3.

Langkah 3: Laksanakan menggunakan primitif Qiskit

  • Input: Circuit abstrak.
  • Output: Taburan quasi-kebarangkalian.

Gunakan primitif StatevectorSampler dari Qiskit untuk membina semula taburan quasi-kebarangkalian bagi keadaan yang dihasilkan daripada pensampelan circuit. Untuk tugasan menjana matriks kernel, kita khususnya berminat dengan kebarangkalian mengukur keadaan |0>.

sampler = StatevectorSampler()

# Execute and get counts
num_shots = 10_000
results = sampler.run([overlap_circ], shots=num_shots).result()
counts = results[0].data.meas.get_int_counts()

# Plot counts
visualize_counts(counts, num_qubits, num_shots)

Output of the previous code cell

Langkah 4: Pasca-proses dan kembalikan keputusan dalam format klasik yang dikehendaki

  • Input: Taburan kebarangkalian.
  • Output: Satu elemen matriks kernel.

Kira kebarangkalian mengukur 0|0 \rangle pada circuit tindihan, dan isi matriks kernel pada kedudukan yang sepadan dengan sampel yang diwakili oleh circuit tindihan tertentu ini (baris 15, lajur 20).

kernel_matrix[x1, x2] = counts.get(0, 0.0) / num_shots
print(f"Fidelity (simulator): {kernel_matrix[x1, x2]}")
Fidelity (simulator): 0.8261

Contoh perkakasan

Matriks kernel kuantum mempunyai O(N2)\mathcal{O}(N^2) entri untuk NN sampel latihan, dan setiap entri memerlukan menjalankan circuit tindihan yang kedalaman gate dua-qubit-nya berkembang mengikut saiz peta ciri. Akibatnya, menskalakan tutorial ini kepada masalah yang lebih besar mempunyai dua kos yang bergabung: masa QPU per matriks kernel berkembang secara kuadratik dengan NN, dan kedalaman unitary_overlap (yang menggabungkan peta ciri dengan adjointnya) menghakis kesetiaan pada saiz sistem dan ketersambungan perkakasan semasa. Untuk memastikan demo singkat dan membuat perbandingan yang jelas, kita oleh itu menjalankan contoh tujuh-qubit yang sama dari contoh berskala kecil pada QPU sebenar dan membandingkan kesetiaan satu entri matriks kernel dengan nilai simulator yang dikira di atas.

# ------------------------------ Step 1 ------------------------------
# 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 = unitary_overlap(unitary1, unitary2)
overlap_circ.measure_all()

# ------------------------------ Step 2 ------------------------------
service = QiskitRuntimeService()
# backend = service.least_busy(
# operational=True, simulator=False, min_num_qubits=overlap_circ.num_qubits
# )
backend = service.backend("ibm_pittsburgh")
print(f"Using backend: {backend.name}")
pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
overlap_ibm = pm.run(overlap_circ)

# ------------------------------ Step 3 ------------------------------
sampler = Sampler(mode=backend)
sampler.options.environment.job_tags = ["TUT_QKT"]

num_shots = 10_000
results = sampler.run([overlap_ibm], shots=num_shots).result()
counts = results[0].data.meas.get_int_counts()
visualize_counts(counts, num_qubits, num_shots)

# ------------------------------ Step 4 ------------------------------
kernel_matrix[x1, x2] = counts.get(0, 0.0) / num_shots
print(f"Fidelity (hardware): {kernel_matrix[x1, x2]}")
Using backend: ibm_pittsburgh

Output of the previous code cell

Fidelity (hardware): 0.7517

Untuk melengkapkan keseluruhan matriks kernel, kita akan menjalankan eksperimen kuantum untuk setiap N(N+1)/2N(N+1)/2 entri uniknya. Rajah di bawah menunjukkan matriks yang terhasil untuk dataset ini; merah gelap menunjukkan kesetiaan yang lebih hampir kepada 1.0.

kernel_matrix.png

Langkah seterusnya

Recommendations

Jika anda mendapati karya ini menarik, anda mungkin berminat dengan bahan berikut: