Quantenkernel-Training
Verbrauchsschätzung: unta ana Minut'n aufm Eagle r3 Prozessor (ACHTUNG: Des is bloß a Schätzung. Ihre Laufzeit kennt anders ausschau'n.)
Hintagrund
Des Tutorial zeigt, wia ma a Qiskit-Musta baut zum Ausrechnen von Einträg'n in ana Quantenkernel-Matrix, de fia binäre Klassifikation g'braucht werd. Fia mehra Informationa üba Qiskit-Musta und wia Qiskit Serverless verwendet werd'n kann, um's in de Cloud z'deployen fia verwaltete Ausführung, schaug'ns auf unsare Dokumentations-Seit'n üba IBM Quantum® Platform.
Voraussetzung'n
Bevor S' mit dem Tutorial anfang'n, stöll'ns sicha, dass S' des do installiert hab'n:
- Qiskit SDK v1.0 oda späta, mit Visualisierung-Untastützung
- Qiskit Runtime v0.22 oda späta (
pip install qiskit-ibm-runtime)
Aufbau
!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
Schritt 1: Klassische Eingab'n auf a Quantenproblem abbüld'n
- Eingab: Trainingsdatnsatz.
- Ausgab: Abstrakta Schaltkreis zum Berechnen von am Kernelmatrix-Eintrag.
Bau'ns den Quantenschaltkreis, dea g'braucht werd zum Ausrechnen von am einzeln'n Eintrag in da Kernelmatrix. Mia brauch'n de Eingab-Dat'n zum festleg'n, wos de Rotationswinkel fia de parametrisiert'n Gates san. Mia werd'n de Dat'n-Prob'n x1=14 und x2=19 verwend'n.
Achtung: Da Datnsatz, dea in dem Tutorial g'braucht werd, kann do runtag'lod'n werd'n.
# 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")
Schritt 2: Des Problem fia Quantenhardware-Ausführung optimier'n
- Eingab: Abstrakta Schaltkreis, net optimiert fia a bestimmts Backend
- Ausgab: Ziel-Schaltkreis und Observable, optimiert fia de ausgsuachte QPU
Verwend'ns de generate_preset_pass_manager-Funktion von Qiskit zum an Optimierungslauf fia unsern Schaltkreis z'spezifizier'n, bezog'n auf de QPU, auf dea mia des Experiment lauf'n loss'n woll'n. Mia setz'n optimization_level=3, wos bedeut, dass mia den vordefiniert'n Pass Manager verwend'n, dea des höchste Optimierungsniveau bringt.
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")
Schritt 3: Ausführung mit Qiskit-Primitiv'n
- Eingab: Ziel-Schaltkreis
- Ausgab: Quasi-Wahrscheinlichkeitsverteilung
Verwend'ns den Sampler-Primitiv von Qiskit Runtime zum a Quasi-Wahrscheinlichkeitsverteilung von Zuständ'n z'rekonstruier'n, de ausm Sampeln vom Schaltkreis rauskumm'n. Fürs Erstell'n von ana Kernelmatrix san mia bsondas interessiert an da Wahrscheinlichkeit, den |0>-Zustand z'mess'n.
Fia des Demo loss'n mia des auf ana QPU mit qiskit-ibm-runtime-Primitiv'n lauf'n. Um des auf qiskit-Statevector-basierte Primitiv'n lauf'n z'loss'n, ersetz'ns den Codeblock fia Qiskit IBM® Runtime-Primitiv'n durch den kommentiert'n Block.
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)
Schritt 4: Nachbearbeitung und des Resultat im g'wünschtn klassisch'n Format zruckgeb'n
- Eingab: Wahrscheinlichkeitsverteilung
- Ausgab: A einzelns Kernelmatrix-Element
Rechna'ns de Wahrscheinlichkeit zum |0> aufm Overlap-Schaltkreis z'mess'n und füll'ns de Kernelmatrix an da Position, de den Prob'n entspricht, de durch den bestimmt'n Overlap-Schaltkreis darg'stellt werd'n (Reih 15, Spalt'n 20). In dera Visualisierung zeigt dünklares Rot Fidelität'n näha an 1.0. Um de ganze Kernelmatrix auszufüll'n, müass'n mia a Quantenexperiment fia jed'n Eintrag lauf'n loss'n.
# 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
Des Qiskit-Musta in de Cloud deploy'n
Um des z'macha, vaschiab'ns den Quellcode von ob'n in a Datei, ./source/generate_kernel_entry.py, pack'ns den Code in a Skript, des Eingab'n nimmt und de endgültige Lösung zruckgibt, und load'ns des dann auf an Fern-Cluster aufi mit da QiskitFunction-Klass von Qiskit Serverless. Fia Anleitungen zum Spezifizier'n von extern'n Abhängigkeitn, zum Übergeb'n von Eingab-Argument'n und mehra, schaug'ns in de Qiskit Serverless-Anleitungen.
De Eingab fürs Musta is a Paar von Dat'n-Prob'n, x1 und x2. De Ausgab is de Fidelität zwisch'n den beid'n Prob'n. Dera Wert werd g'braucht zum den Kernelmatrix-Eintrag z'füll'n, dea den beid'n Prob'n entspricht.
serverless = QiskitServerless()
kernel_entry_pattern = QiskitFunction(
title="generate-kernel-entry",
entrypoint="generate_kernel_entry.py",
working_dir="./source/",
)
serverless.upload(kernel_entry_pattern)
Des Qiskit-Musta als verwalteten Dienst lauf'n loss'n
Nachdem mia des Musta in de Cloud aufig'lod'n hab'n, kenna mia's einfach mit'n IBMServerlessProvider-Client lauf'n loss'n. Um's einfacha z'macha, werd'n mia an exakt'n Quantensimulator in da Cloud-Umgebung verwend'n, sodass de Fidelität, de mia berechna, exakt is.
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]}")
Tutorial-Umfrog
Bitt' macha'ns bei dera kuazn Umfrog mit, um Feedback zu dem Tutorial z'geb'n. Ihre Einsicht'n werd'n uns helf'n, unsare Inhalt und de Benutzer-Erfahrung z'verbessern.