Antrenarea kernelului cuantic
Estimare de utilizare: sub un minut pe un procesor Heron r3 (NOTĂ: Aceasta este doar o estimare. Timpul tău de execuție poate varia.)
Rezultate de învățare
După finalizarea acestui tutorial, te poți aștepta să înțelegi următoarele informații:
- Metodele kernel și utilizările lor
- Kernelurile cuantice și cum pot oferi spații de caracteristici îmbunătățite
- Construcția circuitului kernel cuantic
- Cum să antrenezi un kernel cuantic folosind un pattern Qiskit: mapare, optimizare, execuție și post-procesare
Condiții prealabile
Se recomandă să te familiarizezi cu kernelurile cuantice, de ce sunt importante și cum sunt folosite în practică.
- Kerneluri cuantice covariante pentru date cu structură de grup (articol)
- Introducere în Kernelurile Cuantice și Mașinile cu Vectori Suport (video)
- Kerneluri Cuantice în Practică (video)
De asemenea, este util să ai o înțelegere de bază a teoriei grupurilor.
Fundal
Metodele kernel sunt frecvente în aplicațiile de învățare automată. În acest context, „kernel" se referă la matricea kernel sau la intrările individuale din aceasta. În general, un kernel este o măsură de similitudine între date codificate într-un spațiu de caracteristici de dimensiune înaltă și poate fi utilizat, de exemplu, în sarcini de clasificare cu mașini cu vectori suport.
Metodele kernel cuantice sunt cele care utilizează calculatoare cuantice pentru a estima un kernel. Se știe că calculatoarele cuantice pot codifica date în spații de caracteristici îmbunătățite cuantic, înlocuind efectiv analogii clasici. Pentru și , de obicei cu , este o hartă de caracteristici, . Scopul lui este de a face categoriile de date separate printr-un hiperplan. Luând vectorii din spațiul mapat de caracteristici ca argumente, funcția kernel returnează produsul lor scalar: . Clasic, hărțile de caracteristici de interes sunt cele în care funcția kernel poate fi evaluată cu ușurință; adică atunci când produsul scalar din spațiul mapat de caracteristici poate fi scris în termenii vectorilor de date originali, iar și nu trebuie construiți. În cazul kernelurilor cuantice, maparea caracteristicilor este realizată de un circuit cuantic, iar kernelul este estimat folosind probabilitățile de măsurare eșantionate din circuit.
Acest tutorial arată cum să construiești un pattern Qiskit pentru evaluarea intrărilor într-o matrice de kernel cuantic utilizată pentru clasificare binară.
Cerințe
Înainte de a începe acest tutorial, asigură-te că ai instalate următoarele:
- Qiskit SDK v2.3.1 sau mai recent, cu suport pentru vizualizare
- Qiskit Runtime v0.44.0 sau mai recent (
pip install qiskit-ibm-runtime)
Configurare
# 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
Exemplu cu simulator la scară mică
În această secțiune, parcurgem cei patru pași ai pattern-ului Qiskit pe o instanță cu șapte qubiți a problemei de etichetare a coseturilor cu erori și evaluăm o singură intrare din matricea kernel folosind primitiva StatevectorSampler din Qiskit. Un simulator cu vector de stare este exact (cu excepția zgomotului de eșantionare) și ne arată metoda de la capăt la capăt fără a consuma timp QPU. Apoi repetăm aceeași instanță pe hardware real în secțiunea cu exemplul hardware.
Pasul 1: Mapează intrările clasice la o problemă cuantică
- Intrare: Set de date de antrenament.
- Ieșire: Circuit abstract pentru calculul unei intrări în matricea de kernel.
Problema de clasificare binară pe care ne propunem să o rezolvăm aici este denumită „etichetarea coseturilor cu erori." Setul de date de antrenament de intrare conține o structură de grup, constând din două coseturi formate de un grup și un subgrup. Grupul este luat ca pentru qubiți, care este grupul unitar special de matrice și are o largă aplicabilitate în natură; de ex., Modelul Standard al fizicii particulelor. Luăm subgrupul (stabilizator de graf) cu pentru un graf cu muchii și vârfuri . Observă că stabilizatorii fixează o stare stabilizator astfel încât . În final, definim două coseturi stângi trăgând aleatoriu două .
Pentru mai multe detalii despre setul de date și cum este generat, vezi acest notebook din Quantum Kernel Training Toolkit.
Creăm circuitul cuantic utilizat pentru evaluarea unei intrări din matricea kernel.
Datele de intrare sunt folosite pentru a determina unghiurile de rotație ale porților parametrizate ale circuitului.
Pentru simplitate, vom folosi eșantioanele de date x1=14 și x2=19.
Notă: Setul de date utilizat în acest tutorial poate fi descărcat aici.
# 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")
Pasul 2: Optimizează problema pentru execuția pe hardware cuantic
- Intrare: Circuit abstract, neoptimizat pentru un anumit Backend.
- Ieșire: Circuit țintă, optimizat pentru QPU-ul selectat.
Pentru calea cu simulatorul de vector de stare folosită în această secțiune, nu este necesară nicio optimizare specifică Backend-ului: circuitul abstract poate fi eșantionat direct. Vom aplica acest pas în exemplul hardware de mai jos, unde circuitul este transpilat față de un QPU real folosind generate_preset_pass_manager cu optimization_level=3.
Pasul 3: Execută folosind primitivele Qiskit
- Intrare: Circuit abstract.
- Ieșire: Distribuție quasi-probabilistică.
Folosește primitiva StatevectorSampler din Qiskit pentru a reconstitui o distribuție quasi-probabilistică a stărilor obținute prin eșantionarea circuitului. Pentru sarcina de generare a unei matrice de kernel, suntem în special interesați de probabilitatea de a măsura starea |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)
Pasul 4: Post-procesează și returnează rezultatul în formatul clasic dorit
- Intrare: Distribuție de probabilitate.
- Ieșire: Un singur element din matricea de kernel.
Calculează probabilitatea de a măsura pe circuitul de suprapunere și populează matricea de kernel în poziția corespunzătoare eșantioanelor reprezentate de acest circuit de suprapunere particular (rândul 15, coloana 20).
kernel_matrix[x1, x2] = counts.get(0, 0.0) / num_shots
print(f"Fidelity (simulator): {kernel_matrix[x1, x2]}")
Fidelity (simulator): 0.8261
Exemplu hardware
O matrice kernel cuantică are intrări pentru eșantioane de antrenament, iar fiecare intrare necesită rularea unui circuit de suprapunere a cărui adâncime de porți cu doi qubiți crește cu dimensiunea hărții de caracteristici. Ca urmare, scalarea acestui tutorial la o problemă mai mare are două costuri cumulative: timpul QPU per matrice kernel crește pătratic cu , iar adâncimea lui unitary_overlap (care compune harta de caracteristici cu adjuncta sa) erodează fidelitatea la dimensiunea sistemului și conectivitatea hardware-ului actual. Pentru a menține demonstrația scurtă și pentru o comparație clară, rulăm deci aceeași instanță cu șapte qubiți din exemplul la scară mică pe un QPU real și comparăm fidelitatea unei singure intrări din matricea kernel cu valoarea calculată de simulator mai sus.
# ------------------------------ 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
Fidelity (hardware): 0.7517
Pentru a completa întreaga matrice kernel, am rula un experiment cuantic pentru fiecare dintre cele intrări unice. Figura de mai jos arată matricea rezultată pentru acest set de date; roșul mai închis indică fidelități mai aproape de 1.0.
Pași următori
Dacă ai găsit această lucrare interesantă, s-ar putea să fii interesat de următoarele materiale:
- Quantum Kernel Training Toolkit - repository-ul prototip pe care se bazează acest tutorial
- Quantum Kernel Training for Machine Learning Applications - un tutorial Qiskit Machine Learning care arată cum să antrenezi parametrul antrenabil
- Introduction to Quantum Machine Learning - un curs despre învățarea automată cuantică
- Quantum Machine Learning from IBM Research - o prezentare generală a cercetării QML la IBM
- Covariant quantum kernels for data with group structure - articolul pe care se bazează acest tutorial