เคอร์เนลควอนตัม
บทนำเกี่ยวกับเคอร์เนลควอนตัม
"วิธีเคอร์เนลควอนตัม" หมายถึงวิธีการใดก็ตามที่ใช้คอมพิวเตอร์ควอนตัมในการประมาณค่าเคอร์เนล ในบริบทนี้ "เคอร์เนล" จะหมายถึงเมทริกซ์เคอร์เนลหรือสมาชิกแต่ละตัวในนั้น จำไว้ว่าการแมปฟีเจอร์ คือการแมปจาก ไปยัง โดยมักจะมี และเป้าหมายของการแมปนี้คือทำให้หมวดหมู่ของข้อมูลสามารถแยกออกจากกันได้ด้วยไฮเปอร์เพลน ฟังก์ชันเคอร์เนลรับเวกเตอร์ในพื้นที่ที่ถูกแมปฟีเจอร์มาเป็นอาร์กิวเมนต์และคืนค่าผลคูณภายใน นั่นคือ โดยที่ ในเชิงคลาสสิก เราสนใจการแมปฟีเจอร์ที่ทำให้ประเมินฟังก์ชันเคอร์เนลได้ง่าย ซึ่งมักหมายถึงการหาฟังก์ชันเคอร์เนลที่สามารถเขียนผลคูณภายในในพื้นที่ที่ถูกแมปฟีเจอร์ได้ในรูปของเวกเตอร์ข้อมูลต้นฉบับ โดยไม่ต้องสร้าง และ ก่อน ในวิธีเคอร์เนลควอนตัม การแมปฟีเจอร์ทำโดย Circuit ควอนตัม และเคอร์เนลจะถูกประมาณโดยใช้การวัดบน Circuit นั้นและความน่าจะเป็นสัมพัทธ์ของการวัด
ในบทเรียนนี้ เราจะสำรวจความลึกของ Circuit การเข้ารหัสที่เขียนไว้ล่วงหน้าซึ่งใช้การพัวพันอย่างมาก และเปรียบเทียบกับความลึกของ Circuit ที่เราเขียนเอง ไม่ใช่เพื่อสนับสนุนวิธีใดวิธีหนึ่ง คุณอาจพบว่า Circuit ที่เขียนไว้ล่วงหน้ามีความลึกมากเกินไป และการพัวพันใน Circuit ที่สร้างเองก็ไม่เพียงพอที่จะมีประโยชน์ สิ่งเหล่านี้แสดงขึ้นเพื่อให้คุณสามารถสำรวจได้เท่านั้น
ก่อนที่จะอธิบายขั้นตอนการประมาณเมทริกซ์เคอร์เนลโดยละเอียด มาสรุปขั้นตอนการทำงานโดยใช้ภาษาของ Qiskit patterns กัน
ขั้นตอนที่ 1: แมปอินพุตคลาสสิกเป็นปัญหาควอนตัม
- อินพุต: ชุดข้อมูลสำหรับฝึก
- เอาต์พุต: Circuit นามธรรมสำหรับคำนวณค่าสมาชิกในเมทริกซ์เคอร์เนล
จากชุดข้อมูลที่มี จุดเริ่มต้นคือการเข้ารหัสข้อมูลลงใน Circuit ควอนตัม กล่าวคือเราต้องแมปข้อมูลไปยังปริภูมิฮิลเบิร์ตของสถานะในคอมพิวเตอร์ควอนตัม เราทำสิ่งนี้โดยสร้าง Circuit ที่ขึ้นกับข้อมูล มีหลายวิธีในการทำเช่นนี้ และบทเรียนก่อนหน้าได้สรุปตัวเลือกต่างๆ ไว้แล้ว คุณสามารถสร้าง Circuit เองเพื่อเข้ารหัสข้อมูล หรือใช้แผนที่ฟีเจอร์ที่สร้างไว้แล้วอย่าง zz_feature_map ในบทเรียนนี้ เราจะทำทั้งสองแบบ
โปรดทราบว่าในการคำนวณค่าสมาชิกเมทริกซ์เคอร์เนลเพียงค่าเดียว เราต้องการเข้ารหัสจุดสองจุดที่แตกต่างกัน เพื่อที่เราจะได้ประมาณผลคูณภายในได้ ขั้นตอนการทำงานของเคอร์เนลควอนตัมทั้งหมดจะเกี่ยวข้องกับผลคูณภายในระหว่างเวกเตอร์ข้อมูลที่ถูกแมปหลายค่า รวมถึงวิธีการเรียนรู้ของเครื่องแบบคลาสสิก แต่ขั้นตอนหลักที่ทำซ้ำคือการประมาณค่าสมาชิกเมทริกซ์เคอร์เนลเพียงค่าเดียว สำหรับสิ่งนี้เราเลือก Circuit ควอนตัมที่ขึ้นกับข้อมูล และแมปเวกเตอร์ข้อมูลสองตัวไปยังพื้นที่ฟีเจอร์

สำหรับการสร้างเมทริกซ์เคอร์เนล เราสนใจเป็นพิเศษในความน่าจะเป็นของการวัดสถานะ ซึ่ง Qubit ทั้ง ตัวอยู่ในสถานะ เพื่อให้เข้าใจสิ่งนี้ สมมติว่า Circuit ที่รับผิดชอบการเข้ารหัสและการแมปเวกเตอร์ข้อมูล สามารถเขียนเป็น และ Circuit สำหรับเข้ารหัสและแมป คือ และกำหนดสถานะที่ถูกแมปว่า
สถานะเหล่านี้ คือ การแมปข้อมูลไปยังมิติที่สูงขึ้น ดังนั้นค่าสมาชิกเคอร์เนลที่เราต้องการคือผลคูณภายใน
ถ้าเราดำเนินการบนสถานะเริ่มต้นดีฟอลต์ ด้วย Circuit ทั้งสอง และ ความน่าจะเป็นในการวัดสถานะ คือ
นี่คือค่าที่เราต้องการ (ถึงค่า ) เลเยอร์การวัดของ Circuit จะคืนค่าความน่าจะเป็นของการวัด (หรือที่เรียกว่า "quasi-probabilities" หากใช้วิธีการลดข้อผิดพลาดบางอย่าง) ความน่าจะเป็นที่เราสนใจคือของสถานะศูนย์
ขั้นตอนที่ 2: ปรับปัญหาให้เหมาะสมสำหรับการประมวลผลควอนตัม
- อินพุต: Circuit นามธรรม ที่ยังไม่ได้ปรับสำหรับ Backend เฉพาะ
- เอาต์พุต: Circuit เป้าหมายและ observable ที่ปรับให้เหมาะสมกับ QPU ที่เลือก
ในขั้นตอนนี้ เราจะใช้ฟังก์ชัน generate_preset_pass_manager จาก Qiskit เพื่อกำหนดรูทีนการปรับให้เหมาะสมสำหรับ Circuit เทียบกับคอมพิวเตอร์ควอนตัมจริงที่เราวางแผนจะทดลอง เราตั้งค่า optimization_level=3 ซึ่งหมายความว่าเราจะใช้ preset pass manager ที่ให้ระดับการปรับสูงสุด ในบริบทนี้ "การปรับ" หมายถึงการปรับการนำ Circuit ไปใช้งานบนคอมพิวเตอร์ควอนตัมจริง ซึ่งรวมถึงการพิจารณาต่างๆ เช่น การเลือก Qubit ทางกายภาพที่จะลดความลึกของ Gate หรือการเลือก Qubit ทางกายภาพที่มีอัตราข้อผิดพลาดต่ำสุด ซึ่งไม่เกี่ยวข้องโดยตรงกับการปรับปัญหาการเรียนรู้ของเครื่อง (เช่น optimizer แบบคลาสสิกอย่าง COBYLA)
ขึ้นอยู่กับวิธีการที่คุณนำขั้นตอนที่ 2 ไปใช้ คุณอาจต้องปรับ Circuit มากกว่าหนึ่งครั้ง เนื่องจากแต่ละคู่ของจุดที่เกี่ยวข้องในสมาชิกเมทริกซ์จะสร้าง Circuit ที่แตกต่างกันสำหรับการวัด
ขั้นตอนที่ 3: ประมวลผลโดยใช้ Qiskit Runtime Primitives
- อินพุต: Circuit เป้าหมาย
- เอาต์พุต: การกระจายความน่าจะเป็น
ใช้ primitive Sampler จาก Qiskit Runtime เพื่อสร้างการกระจายความน่าจะเป็นของสถานะที่ได้จากการสุ่มตัวอย่าง Circuit โปรดทราบว่าคุณอาจเห็นสิ่งนี้เรียกว่า "quasi-probability distribution" ซึ่งเป็นคำที่ใช้ได้ในกรณีที่มีสัญญาณรบกวนและมีการนำขั้นตอนเพิ่มเติมมาใช้ เช่น ในการลดข้อผิดพลาด ในกรณีเหล่านี้ ผลรวมของความน่าจะเป็นทั้งหมดอาจไม่เท่ากับ 1 พอดี จึงเรียกว่า "quasi-probability"
ขั้นตอนที่ 4: ประมวลผลหลังการวัด คืนผลลัพธ์ในรูปแบบคลาสสิก
- อินพุต: การกระจายความน่าจะเป็น
- เอาต์พุต: ค่าสมาชิกเมทริกซ์เคอร์เนลเพียงค่าเดียว หรือเมทริกซ์เคอร์เนลทั้งหมดหากทำซ้ำ
คำนวณความน่าจะเป็นของการวัด บน Circuit ควอนตัม และเติมค่าเมทริกซ์เคอร์เนลในตำแหน่งที่สอดคล้องกับเวกเตอร์ข้อมูลสองตัวที่ใช้ เพื่อเติมเมทริกซ์เคอร์เนลทั้งหมด เราต้องทำการทดลองควอนตัมสำหรับแต่ละสมาชิก เมื่อมีเมทริกซ์เคอร์เนลแล้ว เราสามารถใช้ในอัลกอริทึมการเรียนรู้ของเครื่องแบบคลาสสิกหลายอย่างที่รับ pre-calculated kernels ตัวอย่างเช่น: qml_svc = SVC(kernel="precomputed") จากนั้นเราสามารถใช้ขั้นตอนการทำงานแบบคลาสสิกเพื่อนำโมเดลไปใช้กับข้อมูลทดสอบและได้คะแนนความแม่นยำ ขึ้นอยู่กับความพอใจของเราต่อคะแนนความแม่นยำ เราอาจต้องทบทวนส่วนต่างๆ ของการคำนวณ เช่น แผนที่ฟีเจอร์
โครงร่างบทเรียน
ในบทเรียนนี้ เราจะดำเนินการตามขั้นตอนเหล่านี้หลายวิธีเพื่อใช้เวลาบนคอมพิวเตอร์ควอนตัมจริงได้อย่างมีประสิทธิภาพ เราจะนำวิธีเคอร์เนลควอนตัมไปใช้กับ
- ค่าสมาชิกเมทริกซ์เคอร์เนลเพียงค่าเดียวสำหรับข้อมูลที่มีฟีเจอร์จำนวนน้อย โดยใช้ Backend จริง เพื่อให้เราสามารถติดตามสิ่งที่เกิดขึ้นในแต่ละขั้นตอนได้ง่าย
- ชุดข้อมูลทั้งหมดที่มีฟีเจอร์จำนวนน้อย โดยใช้ Backend จำลอง เพื่อให้เราเห็นว่าขั้นตอนการทำงานควอนตัมเชื่อมต่อกับวิธีการเรียนรู้ของเครื่องแบบคลาสสิกอย่างไร
- ค่าสมาชิกเมทริกซ์เคอร์เนลเพียงค่าเดียวสำหรับข้อมูลที่มีฟีเจอร์จำนวนมาก โดยใช้คอมพิวเตอร์ควอนตัมจริง เราจะไม่ประมาณเมทริกซ์เคอร์เนลทั้งหมดสำหรับชุดข้อมูลขนาดใหญ่ เพื่อเคารพเวลาบนคอมพิวเตอร์ควอนตัมของ IBM®
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy pandas qiskit qiskit-ibm-runtime scikit-learn
# If you have not already, install scikit learn
#!pip install scikit-learn
ค่าสมาชิกเมทริกซ์เคอร์เนลเพียงค่าเดียว
ขั้นตอนที่ 1: แมปอินพุตคลาสสิกเป็นปัญหาควอนตัม
มาเริ่มพิจารณาชุดข้อมูลที่มีฟีเจอร์เพียงไม่กี่ตัว สมมติว่า 10 ตัว ชุดข้อมูลสามารถมีขนาดใหญ่ตามต้องการ เนื่องจากเราคำนวณค่าสมาชิกเมทริกซ์เคอร์เนลทีละค่า เราต้องการอย่างน้อยสองจุด ดังนั้นเราจะเริ่มด้วยนั้น (ในตัวอย่างถัดไป เราจะนำเข้าชุดข้อมูลเต็มรูปแบบ) มาดึงแพ็กเกจที่จำเป็นไม่กี่ตัวก่อน:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Two mock data points, including category labels, as in training
small_data = [
[-0.194, 0.114, -0.006, 0.301, -0.359, -0.088, -0.156, 0.342, -0.016, 0.143, 1],
[-0.1, 0.002, 0.244, 0.127, -0.064, -0.086, 0.072, 0.043, -0.053, 0.02, -1],
]
# Data points with labels removed, for inner product
train_data = [small_data[0][:-1], small_data[1][:-1]]
เราสามารถลองใช้ z_feature_map ได้
# from qiskit.circuit.library import zz_feature_map
# fm = zz_feature_map(feature_dimension=np.shape(train_data)[1], entanglement='linear', reps=1)
from qiskit.circuit.library import z_feature_map
fm = z_feature_map(feature_dimension=np.shape(train_data)[1])
unitary1 = fm.assign_parameters(train_data[0])
unitary2 = fm.assign_parameters(train_data[1])
ยูนิทารีสองตัวข้างต้นสอดคล้องกับ และ ที่อธิบายไว้ในบทนำ เราสามารถรวมกันโดยใช้ unitary_overlap และอย่างเคย เราต้องคอยดูความลึกของ Circuit เสมอ
from qiskit.circuit.library import unitary_overlap
overlap_circ = unitary_overlap(unitary1, unitary2)
overlap_circ.measure_all()
print("circuit depth = ", overlap_circ.decompose().depth())
overlap_circ.decompose().draw("mpl", scale=0.6, style="iqp")
circuit depth = 9
ขั้นตอนที่ 2: ปรับปัญหาให้เหมาะสมสำหรับการประมวลผลควอนตัม
เราเริ่มต้นด้วยการเลือก Backend ที่ว่างที่สุด จากนั้นปรับ Circuit ของเราสำหรับการรันบน Backend นั้น
# Import needed packages
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService
# Get the least busy backend
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=fm.num_qubits
)
print(backend)
<IBMBackend('ibm_brisbane')>
# Apply level 3 optimization to our overlap circuit
pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
overlap_ibm = pm.run(overlap_circ)
สำหรับ Circuit ที่ซับซ้อน ขั้นตอนนี้จะเพิ่มความลึกของ Circuit อย่างมากเมื่อแมปไปยัง Gate แบบเนทีฟสำหรับคอมพิวเตอร์ควอนตัมจริง และข้อมูลอาจต้องถูกย้ายจาก Qubit หนึ่งไปยังอีก Qubit หนึ่ง ในกรณีง่ายๆ นี้ ความลึกแทบไม่ได้รับผลกระทบเลย
print("circuit depth = ", overlap_ibm.decompose().depth())
overlap_ibm.decompose().depth(lambda instr: len(instr.qubits) > 1)
circuit depth = 10
1
ขั้นตอนที่ 3: ประมวลผลโดยใช้ Qiskit Runtime Primitives
ซินแท็กซ์สำหรับการรันบนซิมูเลเตอร์ถูกแสดงเป็นคอมเมนต์ด้านล่าง สำหรับชุดข้อมูลนี้ที่มีฟีเจอร์จำนวนน้อย การรันบนซิมูเลเตอร์ยังเป็นตัวเลือกได้อยู่ สำหรับการคำนวณระดับ utility การจำลองมักไม่สามารถทำได้จริง ควรใช้ซิมูเลเตอร์เพื่อดีบักโค้ดในระดับขนาดเล็กเท่านั้น
# Run this for a simulator
# from qiskit.primitives import StatevectorSampler
# from qiskit_ibm_runtime import Options, Session, Sampler
# num_shots = 10000
# Evaluate the problem using state vector-based primitives from Qiskit
# sampler = StatevectorSampler()
# results = sampler.run([overlap_circ], shots=num_shots).result()
# .get_counts() returns counts associated with a state labeled by bit results
# such as |001101...01>.
# counts_bit = results[0].data.meas.get_counts()
# .get_int_counts returns the same counts, but labeled by integer equivalent
# of the above bit string.
# counts = results[0].data.meas.get_int_counts()
# Benchmarked on an Eagle processor, 7-11-24, took 4 sec.
# Import our runtime primitive
from qiskit_ibm_runtime import Session, SamplerV2 as Sampler
num_shots = 10000
# Use sampler and get the counts
sampler = Sampler(mode=backend)
results = sampler.run([overlap_ibm], shots=num_shots).result()
# .get_counts() returns counts associated with a state labeled by bit results such as |001101...01>.
counts_bit = results[0].data.meas.get_counts()
# .get_int_counts returns the same counts, but labeled by integer equivalent
# of the above bit string.
counts = results[0].data.meas.get_int_counts()
ขั้นตอนที่ 4: ประมวลผลหลังการวัด คืนผลลัพธ์ในรูปแบบคลาสสิก
ตามที่อธิบายไว้ในบทนำ การวัดที่มีประโยชน์ที่สุดในที่นี้คือความน่าจะเป็นของการวัดสถานะศูนย์
counts.get(0, 0.0) / num_shots
0.6525
นี่คือผลลัพธ์ที่เราต้องการ: การประมาณค่าผลคูณภายใน (ถึงค่า mod กำลังสอง) ของเวกเตอร์ที่สอดคล้องกับจุดข้อมูลสองจุด หากต้องการดูการกระจายความน่าจะเป็น (หรือ quasiprobability) ทั้งหมดของการวัด เราสามารถทำได้โดยใช้ฟังก์ชัน plot_distribution ดังที่แสดงด้านล่าง จะเห็นว่าสำหรับ Qubit จำนวนมาก ภาพเช่นนี้จะซับซ้อนเกินกว่าจะจัดการได้อย่างรวดเร็ว
from qiskit.visualization import plot_distribution
plot_distribution(counts_bit)

อีกทางหนึ่ง เราอาจกำหนดการแสดงผลแบบด้านล่างเพื่อดูเฉพาะ 10 การวัดที่มีความน่าจะเป็นสูงสุด ซึ่งอาจมีความสำคัญสำหรับการแก้ปัญหาหรือพยายามทำความเข้าใจข้อมูลให้ดีขึ้น แต่ความน่าจะเป็นการวัดของสถานะศูนย์คือค่าสมาชิกเมทริกซ์เคอร์เนลของเรา
def visualize_counts(probs, num_qubits):
"""Visualize the outputs from the Qiskit Sampler primitive."""
zero_prob = probs.get(0, 0.0)
top_10 = dict(sorted(probs.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]))
xvals, yvals = list(zip(*by_key.items()))
xvals = [bin(xval)[2:].zfill(num_qubits) for xval in xvals]
plt.bar(xvals, yvals)
plt.xticks(rotation=75)
plt.title("Results of sampling")
plt.xlabel("Measured bitstring")
plt.ylabel("Counts")
plt.show()
visualize_counts(counts, overlap_circ.num_qubits)
จากข้อมูลเกี่ยวกับผลคูณภายในระหว่างจุดข้อมูลสองจุดในพื้นที่ฟีเจอร์มิติสูงเพียงค่าเดียว สิ่งที่เราบอกได้คือการซ้อนทับของพวกมันค่อนข้างมากเมื่อเทียบกับการซ้อนทับสูงสุด (ซึ่งจะเป็น 1.0) นี่อาจเป็นตัวบ่งชี้ว่าจุดข้อมูลสองจุดนี้มีความคล้ายคลึงกันในบางลักษณะและจะถูกจัดหมวดหมู่ในกลุ่มเดียวกัน หรืออาจเป็นตัวบ่งชี้ว่าแผนที่ฟีเจอร์ของเราไม่มีประสิทธิภาพในการแมปไปยังพื้นที่ที่ข้อมูลที่คล้ายกันมีการซ้อนทับสูงและข้อมูลที่ต่างกันมีการซ้อนทับต่ำ เพื่อทราบว่าสิ่งใดเป็นจริง เราต้องนำแผนที่ฟีเจอร์ไปใช้กับชุดข้อมูลทั้งหมดและดูว่าเมทริกซ์เคอร์เนลที่ได้สามารถนำไปใช้แยกหมวดหมู่ด้วยความแม่นยำสูงได้หรือไม่
เป็นที่น่าสังเกตว่าเราใช้ z_feature_map ซึ่งทำให้ความลึก two-qubit transpiled ต่ำ (ความลึก 1 จริงๆ) หาก Circuit ของคุณลึกเกินไป จะทำให้มีสัญญาณรบกวนมาก ซึ่งจะทำให้ความน่าจะเป็นของการวัดสถานะศูนย์ต่ำมาก แม้ว่าแผนที่ฟีเจอร์ของคุณจะเหมาะกับข้อมูลก็ตาม ตัวอย่างเช่น การทำซ้ำกระบวนการข้างต้นโดยใช้ zz_feature_map และ , entanglement='linear', reps=1 ให้ผล dist.get(0,0.0) = 0.0015 โดยใช้จุดข้อมูลเดียวกัน ซึ่งเกิดจากความลึกของ Circuit และความลึก two-qubit ที่มากกว่าจาก zz_feature_map ภาพด้านล่างแสดงการกระจายความน่าจะเป็นสำหรับการคำนวณนั้น

คุ้มค่าที่จะลองเล่นกับจุดข้อมูลไม่กี่จุดจากหมวดหมู่เดียวกันเพื่อดูว่าความลึกต้องน้อยแค่ไหนจึงจะได้ผลลัพธ์ที่ดี ต่อไปนี้คือคำแนะนำโดยประมาณที่แน่นอนว่ามีข้อยกเว้น โดยทั่วไปแล้ว ความลึก two-qubit transpiled ที่ 10 หรือต่ำกว่าไม่ควรมีปัญหา ความลึก two-qubit transpiled ที่ 50-60 ถือเป็นระดับ state-of-the-art และต้องใช้การลดข้อผิดพลาดขั้นสูงและเครื่องมืออื่นๆ ในระหว่างนั้น ผลลัพธ์ของคุณอาจแตกต่างกันตามความคล้ายคลึงของข้อมูล ความสามารถในการแสดงออกของแผนที่ฟีเจอร์ ความกว้างของ Circuit และปัจจัยอื่นๆ โดยปกติแล้ว ขั้นตอนการประมวลผลหลังการวัดยังรวมถึงกระบวนการเรียนรู้ของเครื่องแบบคลาสสิกด้วย ในส่วนถัดไป เราจะขยายกระบวนการนี้ไปยังชุดข้อมูลทั้งหมดและแสดงขั้นตอนการทำงานของการเรียนรู้ของเครื่องแบบคลาสสิก
ทดสอบความเข้าใจ
อ่านคำถามด้านล่าง คิดเกี่ยวกับคำตอบ แล้วคลิกที่สามเหลี่ยมเพื่อเปิดเผยคำตอบ
ใน Circuit ควอนตัม 10 Qubit โดยทั่วไปมีสถานะที่แตกต่างกันกี่สถานะที่อาจวัดได้?
คำตอบ:
หรือ 1024.
สมมติว่ามีคนที่เพิ่งเริ่มเรียนรู้การประมวลผลควอนตัมพยายามใช้ Circuit ควอนตัมที่มีความลึก two-qubit สูงมาก และไม่ใช้การลดข้อผิดพลาด สมมติต่อไปว่าผลลัพธ์คืออัตราข้อผิดพลาด 10% บนแต่ละ Qubit ถ้าค่าสมาชิกเมทริกซ์เคอร์เนลจริง (ปราศจากข้อผิดพลาด) ที่สอดคล้องกับ Circuit นี้มีค่ามากมาย สมมติว่า 1.0 ความน่าจะเป็นที่จะวัด Qubit ทั้ง 10 ตัวให้อยู่ในสถานะที่ทุก Qubit เป็น |0> จะเป็นเท่าไร?
คำตอบ:
ความน่าจะเป็นที่แต่ละ Qubit จะถูกพบในสถานะ |0> อย่างถูกต้องคือ 0.90 ความน่าจะเป็นที่ Qubit ทั้ง 10 ตัวจะถูกพบในสถานะที่ถูกต้องคือ หรือประมาณ 35%
อธิบายด้วยคำพูดของคุณเองว่าทำไมการติดตามความลึกของ Circuit จึงสำคัญมาก สิ่งนี้เป็นความจริงโดยทั่วไป แต่อธิบายในบริบทของการประมาณเคอร์เนลควอนตัม
คำตอบ:
ในขั้นตอนการทำงาน QKE นี้ การประมาณของเราขึ้นอยู่กับการวัดของสถานะศูนย์ หมายความว่าสถานะที่ทุก Qubit ถูกพบในสถานะ Circuit ที่ลึกมากจะทำให้มีอัตราข้อผิดพลาดสูง เมื่ออัตราข้อผิดพลาดนั้นสะสมบน Qubit จำนวนมาก จะทำให้ความน่าจะเป็นของการวัดสถานะศูนย์ลดลงอย่างมาก
เมทริกซ์เคอร์เนลเต็มรูปแบบ
ในส่วนนี้ เราจะขยายกระบวนการข้างต้นไปยังการจำแนกประเภทไบนารีของชุดข้อมูลทั้งหมด สิ่งนี้จะนำเสนอสององค์ประกอบสำคัญ: (1) ตอนนี้เราสามารถนำการเรียนรู้ของเครื่องแบบคลาสสิกมาใช้ในขั้นตอนหลังการวัดได้ และ (2) เราสามารถได้คะแนนความแม่นยำสำหรับการฝึกของเรา
ขั้นตอนที่ 1: แมปอินพุตคลาสสิกเป็นปัญหาควอนตัม
ตอนนี้เราจะนำเข้าชุดข้อมูลที่มีอยู่สำหรับการจำแนกประเภท ชุดข้อมูลนี้ประกอบด้วย 128 แถว (จุดข้อมูล) และ 14 ฟีเจอร์ในแต่ละจุด มีองค์ประกอบที่ 15 ที่บ่งบอกหมวดหมู่ไบนารีของแต่ละจุด () ชุดข้อมูลถูกนำเข้าด้านล่าง หรือคุณสามารถเข้าถึงชุดข้อมูลและดูโครงสร้าง ที่นี่
เราจะใช้จุดข้อมูล 90 จุดแรกสำหรับการฝึก และ 30 จุดถัดไปสำหรับการทดสอบ
!wget https://raw.githubusercontent.com/qiskit-community/prototype-quantum-kernel-training/main/data/dataset_graph7.csv
df = pd.read_csv("dataset_graph7.csv", sep=",", header=None)
# Prepare training data
train_size = 90
X_train = df.values[0:train_size, :-1]
train_labels = df.values[0:train_size, -1]
# Prepare testing data
test_size = 30
X_test = df.values[train_size : train_size + test_size, :-1]
test_labels = df.values[train_size : train_size + test_size, -1]
--2024-07-11 23:05:22-- https://raw.githubusercontent.com/qiskit-community/prototype-quantum-kernel-training/main/data/dataset_graph7.csv
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.111.133, 185.199.109.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 49405 (48K) [text/plain]
Saving to: ‘dataset_graph7.csv.15’
dataset_graph7.csv. 100%[===================>] 48.25K --.-KB/s in 0.02s
2024-07-11 23:05:23 (2.11 MB/s) - ‘dataset_graph7.csv.15’ saved [49405/49405]
เราจะเตรียมการจัดเก็บเอาต์พุตหลายรายการล่วงหน้าโดยสร้างเมทริกซ์เคอร์เนลและเมทริกซ์ทดสอบที่มีขนาดเหมาะสม
# Empty kernel matrix
num_samples = np.shape(X_train)[0]
kernel_matrix = np.full((num_samples, num_samples), np.nan)
test_matrix = np.full((test_size, num_samples), np.nan)
ตอนนี้เราสร้างแผนที่ฟีเจอร์สำหรับการเข้ารหัสและแมปข้อมูลคลาสสิกใน Circuit ควอนตัม เราสามารถสร้างแผนที่ฟีเจอร์เองหรือใช้แผนที่ฟีเจอร์สำเร็จรูปได้ อย่าลังเลที่จะแก้ไขแผนที่ฟีเจอร์ด้านล่าง หรือสลับกลับไปใช้ ZFeatureMap แต่ให้ระวังความลึกของ Circuit เสมอ จำไว้ว่าในตัวอย่าง 6 Qubit ก่อนหน้า ความลึกของ Circuit transpiled มีค่าสูงเกินไปเมื่อใช้ zz_feature_map เมื่อขนาดและความซับซ้อนของ Circuit เพิ่มขึ้น ความลึกอาจเพิ่มขึ้นอย่างรวดเร็วจนสัญญาณรบกวนท่วมผลลัพธ์ของเรา เมื่อใดก็ตามที่คุณรู้บางอย่างเกี่ยวกับโครงสร้างข้อมูลที่อาจบอกว่าโครงสร้างแผนที่ฟีเจอร์ใดจะมีประโยชน์ที่สุด ขอแนะนำให้สร้างแผนที่ฟีเจอร์แบบกำหนดเองที่ใช้ความรู้นั้น
from qiskit.circuit import Parameter, ParameterVector, QuantumCircuit
# Prepare feature map for computing overlap
num_features = np.shape(X_train)[1]
num_qubits = int(num_features / 2)
# To use a custom feature map use the lines below.
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)
ขั้นตอนที่ 2 และ 3: ปรับปัญหาและประมวลผลโดยใช้ primitives
เราจะสร้าง Circuit overlap และถ้าเราจะรันบนคอมพิวเตอร์ควอนตัมจริงในตัวอย่างนี้ เราจะปรับให้เหมาะสมสำหรับการประมวลผลเหมือนก่อนหน้า แต่ในกรณีนี้ เราตั้งใจจะผ่านจุดข้อมูลทั้งหมดและคำนวณเมทริกซ์เคอร์เนลเต็มรูปแบบ สำหรับแต่ละคู่ของเวกเตอร์ข้อมูล และ เราสร้าง Circuit overlap ที่แตกต่างกัน ดังนั้นเราต้องปรับ Circuit สำหรับแต่ละคู่จุดข้อมูล ดังนั้นขั้นตอนที่ 2 และ 3 จะทำร่วมกันในการวนซ้ำหลายครั้ง
เซลล์โค้ดด้านล่างทำกระบวนการเดิมทุกอย่างสำหรับคู่จุดข้อมูลเดียว ครั้งนี้เพียงแต่ทำซ้ำภายใน for loop สองวง และมีบรรทัดเพิ่มเติมในตอนท้าย kernel_matrix[x_1,x_2] = ... เพื่อเก็บผลลัพธ์ของแต่ละการคำนวณ โปรดทราบว่าเราได้ใช้ประโยชน์จากความสมมาตรของเมทริกซ์เคอร์เนลเพื่อลดจำนวนการคำนวณลง 1/2 นอกจากนี้ เราได้ตั้งค่าองค์ประกอบแนวทแยงให้เป็น 1 ตามที่ควรเป็นโดยไม่มีสัญญาณรบกวน ขึ้นอยู่กับการนำไปใช้งานและความแม่นยำที่ต้องการ คุณยังสามารถใช้องค์ประกอบแนวทแยงเพื่อประมาณสัญญาณรบกวนหรือเรียนรู้เกี่ยวกับมันสำหรับวัตถุประสงค์การลดข้อผิดพลาด
เมื่อเมทริกซ์เคอร์เนลถูกเติมเต็มแล้ว เราจะทำกระบวนการซ้ำสำหรับข้อมูลทดสอบและเติม test_matrix ซึ่งเป็นเมทริกซ์เคอร์เนลเช่นกัน เราเพียงแต่ให้ชื่อต่างกันเพื่อแยกแยะทั้งสอง
# To use a simulator
from qiskit.primitives import StatevectorSampler
# Remember to insert your token in the QiskitRuntimeService constructor
# to use real quantum computers
# service = QiskitRuntimeService()
# backend = service.least_busy(
# operational=True, simulator=False, min_num_qubits=fm.num_qubits
# )
num_shots = 10000
# Evaluate the problem using state vector-based primitives from Qiskit.
sampler = StatevectorSampler()
for x1 in range(0, train_size):
for x2 in range(x1 + 1, train_size):
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()
# These lines run the qiskit sampler primitive.
counts = (
sampler.run([overlap_circ], shots=num_shots)
.result()[0]
.data.meas.get_int_counts()
)
# Assign the probability of the 0 state to the kernel matrix, and the transposed element
# (since this is an inner product)
kernel_matrix[x1, x2] = counts.get(0, 0.0) / num_shots
kernel_matrix[x2, x1] = counts.get(0, 0.0) / num_shots
# Fill in on-diagonal elements with 1, again, since this is an inner-product corresponding to
# probability (or alter the code to check these entries and verify they yield 1)
kernel_matrix[x1, x1] = 1
print("training done")
# Similar process to above, but for testing data.
for x1 in range(0, test_size):
for x2 in range(0, train_size):
unitary1 = fm.assign_parameters(list(X_test[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()
counts = (
sampler.run([overlap_circ], shots=num_shots)
.result()[0]
.data.meas.get_int_counts()
)
test_matrix[x1, x2] = counts.get(0, 0.0) / num_shots
print("test matrix done")
training done
test matrix done
ขั้นตอนที่ 4: ประมวลผลหลังการวัด คืนผลลัพธ์ในรูปแบบคลาสสิก
ตอนนี้ที่เรามีเมทริกซ์เคอร์เนลและ test_matrix ที่มีรูปแบบคล้ายกันจากวิธีเคอร์เนลควอนตัม เราสามารถนำอัลกอริทึมการเรียนรู้ของเครื่องแบบคลาสสิกมาทำนายข้อมูลทดสอบและตรวจสอบความแม่นยำได้ เราจะเริ่มด้วยการนำเข้า sklearn.svc ของ Scikit-Learn ซึ่งเป็น support vector classifier (SVC) เราต้องระบุว่าต้องการให้ SVC ใช้เคอร์เนลที่คำนวณไว้ล่วงหน้าโดยใช้ kernel = precomputed
# import a support vector classifier from a classical ML package.
from sklearn.svm import SVC
# Specify that you want to use a pre-computed kernel matrix
qml_svc = SVC(kernel="precomputed")
โดยใช้ SVC.fit เราสามารถป้อนเมทริกซ์เคอร์เนลและ label การฝึกเพื่อได้การ fit SVC.score จะให้คะแนนข้อมูลทดสอบเทียบกับการ fit นั้นโดยใช้ test_matrix และคืนค่าความแม่นยำ
# Feed in the pre-computed matrix and the labels of the training data.
# The classical algorithm gives you a fit.
qml_svc.fit(kernel_matrix, train_labels)
# Now use the .score to test your data, using the matrix of test data,
# and test labels as your inputs.
qml_score_precomputed_kernel = qml_svc.score(test_matrix, test_labels)
print(f"Precomputed kernel classification test score: {qml_score_precomputed_kernel}")
Precomputed kernel classification test score: 1.0
เราเห็นว่าความแม่นยำของโมเดลที่ฝึกแล้วอยู่ที่ 100% ซึ่งเป็นเรื่องดีและแสดงให้เห็นว่า QKE สามารถทำงานได้ แต่นั่นแตกต่างมากจากข้อได้เปรียบเชิงควอนตัม เคอร์เนลแบบคลาสสิกน่าจะสามารถแก้ปัญหาการจำแนกประเภทนี้ด้วยความแม่นยำ 100% ได้เช่นกัน ยังมีงานอีกมากในการกำหนดลักษณะประเภทข้อมูลและความสัมพันธ์ของข้อมูลต่างๆ เพื่อดูว่าเคอร์เนลควอนตัมจะมีประโยชน์มากที่สุดในยุค utility ปัจจุบัน เราปล่อยให้ผู้เรียนแก้ไขส่วนต่างๆ ของขั้นตอนการทำงานนี้และศึกษาประสิทธิภาพของแผนที่ฟีเจอร์ควอนตัมต่างๆ ต่อไปนี้คือสิ่งที่ควรพิจารณา:
- ความแม่นยำมีความแข็งแกร่งแค่ไหน? มันคงที่สำหรับข้อมูลประเภทต่างๆ หรือเฉพาะข้อมูลการฝึกนี้เท่านั้น?
- โครงสร้างใดในข้อมูลของคุณทำให้คุณสงสัยว่าแผนที่ฟีเจอร์ควอนตัมมีประโยชน์?
- ความแม่นยำได้รับผลกระทบอย่างไรจากการเพิ่ม/ลดจำนวนข้อมูลการฝึก?
- แผนที่ฟีเจอร์ใดที่คุณสามารถใช้ได้และผลลัพธ์แตกต่างกันอย่างไรตามแผนที่ฟีเจอร์?
- ความแม่นยำและเวลาในการรันได้รับผลกระทบอย่างไรจากการเพิ่มจำนวนฟีเจอร์?
- แนวโน้มใด ถ้ามี ที่คุณคาดว่าจะคงอยู่บนคอมพิวเตอร์ควอนตัมจริง?
การขยายไปยังฟีเจอร์และ Qubit จำนวนมากขึ้น
ในส่วนนี้ เราจะทำซ้ำการคำนวณค่าสมาชิกเมทริกซ์เพียงค่าเดียว แต่สำหรับจำนวนฟีเจอร์ที่มากขึ้นอย่างมาก เพื่อร่างเส้นทางในการขยายไปสู่ระดับ utility การจำกัดให้เหลือค่าสมาชิกเมทริกซ์เพียงค่าเดียวเพื่อให้สามารถแสดงกระบวนการได้โดยไม่ต้องใช้เวลาบนคอมพิวเตอร์ควอนตัมที่จัดสรรมากเกินไป
ขั้นตอนที่ 1: แมปอินพุตคลาสสิกเป็นปัญหาควอนตัม
เราจะสมมติจุดเริ่มต้นของชุดข้อมูลที่แต่ละจุดข้อมูลมี 42 ฟีเจอร์ เช่นเดียวกับตัวอย่างแรก เราจะคำนวณค่าสมาชิกเมทริกซ์เคอร์เนลเพียงค่าเดียว ซึ่งต้องใช้จุดข้อมูลสองจุด จุดสองจุดด้านล่างมี 42 ฟีเจอร์และตัวแปรหมวดหมู่เดียว ()
# Two mock data points, including category labels, as in training
large_data = [
[
-0.028,
-1.49,
-1.698,
0.107,
-1.536,
-1.538,
-1.356,
-1.514,
-0.109,
-1.8,
-0.122,
-1.651,
-1.955,
-0.123,
-1.732,
0.091,
-0.048,
-0.128,
-0.026,
0.082,
-1.263,
0.065,
0.004,
-0.055,
-0.08,
-0.173,
-1.734,
-0.39,
-1.451,
0.078,
-1.578,
-0.025,
-0.184,
-0.119,
-1.336,
0.055,
-0.204,
-1.578,
0.132,
-0.121,
-1.599,
-0.187,
-1,
],
[
-1.414,
-1.439,
-1.606,
0.246,
-1.673,
0.002,
-1.317,
-1.262,
-0.178,
-1.814,
0.013,
-1.619,
-1.86,
-0.25,
-0.212,
-0.214,
-0.033,
0.071,
-0.11,
-1.607,
0.441,
-0.143,
-0.009,
-1.655,
-1.579,
0.381,
-1.86,
-0.079,
-0.088,
-0.058,
-1.481,
-0.064,
-0.065,
-1.507,
0.177,
-0.131,
-0.153,
0.07,
-1.627,
0.593,
-1.547,
-0.16,
-1,
],
]
train_data = [large_data[0][:-1], large_data[1][:-1]]
จำไว้ว่า zz_feature_map สร้าง Circuit ที่ค่อนข้างลึกในกรณีที่มีฟีเจอร์จำนวนน้อย (14 ฟีเจอร์) เมื่อเราเพิ่มจำนวนฟีเจอร์ เราต้องติดตามความลึกของ Circuit อย่างใกล้ชิด เพื่อแสดงให้เห็นสิ่งนี้ เราจะลองใช้ zz_feature_map ก่อนและตรวจสอบความลึกของ Circuit ที่ได้
from qiskit.circuit.library import zz_feature_map
fm = zz_feature_map(
feature_dimension=np.shape(train_data)[1], entanglement="linear", reps=1
)
unitary1 = fm.assign_parameters(train_data[0])
unitary2 = fm.assign_parameters(train_data[1])
from qiskit.circuit.library import unitary_overlap
overlap_circ = unitary_overlap(unitary1, unitary2)
overlap_circ.measure_all()
print("circuit depth = ", overlap_circ.decompose(reps=2).depth())
print(
"two-qubit depth",
overlap_circ.decompose().depth(lambda instr: len(instr.qubits) > 1),
)
# overlap_circ.draw("mpl", scale=0.6, style="iqp")
circuit depth = 251
two-qubit depth 165
ตามที่อธิบายไว้ก่อนหน้า การกำหนดว่าลึกแค่ไหนถือว่ามากเกินไปนั้นมีความซับซ้อน แต่ความลึก two-qubit ที่มากกว่า 100 แม้ก่อนการ transpilation ก็เป็นสิ่งที่เริ่มต้นไม่ได้ นี่คือเหตุผลที่เน้นแผนที่ฟีเจอร์แบบกำหนดเองตลอดบทเรียนนี้ หากคุณรู้บางอย่างเกี่ยวกับโครงสร้างของชุดข้อมูลทั้งหมด คุณควรออกแบบแผนที่ entanglement โดยคำนึงถึงโครงสร้างนั้น ที่นี่ เนื่องจากเราคำนวณผลคูณภายในระหว่างจุดข้อมูลสองจุดเท่านั้น เราได้ให้ความสำคัญกับความลึกของ Circuit ต่ำมากกว่าการพิจารณาโครงสร้างข้อมูลโดยละเอียด
from qiskit.circuit import Parameter, ParameterVector, QuantumCircuit
# Prepare feature map for computing overlap
entangler_map = [
[3, 4],
[2, 5],
[1, 4],
[2, 3],
[4, 6],
[7, 9],
[10, 11],
[9, 12],
[8, 11],
[9, 10],
[11, 13],
[14, 16],
[17, 18],
[16, 19],
[15, 18],
[16, 17],
[18, 20],
]
# Use the entangler map above to build a feature map
num_features = np.shape(train_data)[1]
num_qubits = int(num_features / 2)
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)
from qiskit.circuit.library import unitary_overlap
# Assign features of each data point to a unitary, an instance of the general feature map.
unitary1 = fm.assign_parameters(list(train_data[0]) + [np.pi / 2])
unitary2 = fm.assign_parameters(list(train_data[1]) + [np.pi / 2])
# Create the overlap circuit
overlap_circ = unitary_overlap(unitary1, unitary2)
overlap_circ.measure_all()
เราจะไม่ตรวจสอบความลึกตอนนี้ เนื่องจากสิ่งที่สำคัญจริงๆ คือความลึก two-qubit transpiled
ขั้นตอนที่ 2: ปรับปัญหาให้เหมาะสมสำหรับการประมวลผลควอนตัม
เราเริ่มต้นด้วยการเลือก Backend ที่ว่างที่สุด จากนั้นปรับ Circuit ของเราสำหรับการรันบน Backend นั้น
# Import needed packages
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService
# Get the least busy backend
service = QiskitRuntimeService()
backend = service.least_busy(
operational=True, simulator=False, min_num_qubits=fm.num_qubits
)
print(backend)
<IBMBackend('ibm_brisbane')>
สำหรับงานขนาดเล็ก preset pass manager มักจะคืน Circuit เดิมที่มีความลึกเท่าเดิมอย่างน่าเชื่อถือ แต่ใน Circuit ที่ใหญ่และซับซ้อนมาก pass manager อาจคืน Circuit transpiled ที่แตกต่างกันในแต่ละครั้ง เนื่องจากใช้ heuristics และเพราะว่า Circuit ขนาดใหญ่มากจะมีภูมิทัศน์ของการปรับที่เป็นไปได้ที่ซับซ้อน มักมีประโยชน์ที่จะทำการ transpile หลายครั้งและใช้ Circuit ที่ตื้นที่สุด สิ่งนี้เพิ่มเฉพาะ overhead แบบคลาสสิกและอาจปรับปรุงผลลัพธ์จากคอมพิวเตอร์ควอนตัมได้อย่างมาก
ที่นี่ เราทำการ transpile Circuit overlap unitary 20 ครั้ง และดูความลึกของ Circuit ที่ได้
# Apply level 3 optimization to our overlap circuit
transpiled_qcs = []
transpiled_depths = []
transpiled_twoqubit_depths = []
for i in range(1, 20):
pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
overlap_ibm = pm.run(overlap_circ)
transpiled_qcs.append(overlap_ibm)
transpiled_depths.append(overlap_ibm.decompose().depth())
transpiled_twoqubit_depths.append(
overlap_ibm.decompose().depth(lambda instr: len(instr.qubits) > 1)
)
print("circuit depth = ", overlap_ibm.decompose().depth())
circuit depth = 61
print(transpiled_depths)
print(transpiled_twoqubit_depths)
[61, 60, 60, 69, 60, 60, 60, 65, 60, 60, 69, 61, 77, 77, 65, 60, 60, 77, 61]
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13]
ที่นี่คุณจะเห็นว่ามีความแตกต่างในความลึกของ Gate ทั้งหมดกับการ transpilation ที่แตกต่างกัน Circuit ของเรายังไม่ลึก/กว้างพอที่จะเห็นความแตกต่างในความลึก two-qubit transpiled เราจะใช้ transpiled_qcs[1] ซึ่งมีความลึก 60 ซึ่งต่ำกว่าความลึกของ Circuit ที่ลึกที่สุดที่ได้คือ 77 เล็กน้อย
overlap_ibm = transpiled_qcs[1]
ขั้นตอนที่ 3: ประมวลผลโดยใช้ Qiskit Runtime Primitives
เมื่อเราขยายใกล้ระดับ utility ซิมูเลเตอร์จะไม่มีประโยชน์ ที่นี่แสดงเฉพาะซินแท็กซ์สำหรับคอมพิวเตอร์ควอนตัมจริงเท่านั้น
# Run on ibm_osaka, 7-12-24, required 22 sec.
# Import our runtime primitive
from qiskit_ibm_runtime import SamplerV2 as Sampler
# Open a Runtime session:
session = Session(backend=backend)
num_shots = 10000
# Use sampler and get the counts
sampler = Sampler(mode=session)
options = sampler.options
options.dynamical_decoupling.enable = True
options.twirling.enable_gates = True
counts = (
sampler.run([overlap_ibm], shots=num_shots).result()[0].data.meas.get_int_counts()
)
# Close session after done
session.close()
ขั้นตอนที่ 4: ประมวลผลหลังการวัด คืนผลลัพธ์ในรูปแบบคลาสสิก
ตามที่อธิบายไว้ในบทนำ การวัดที่มีประโยชน์ที่สุดในที่นี้คือความน่าจะเป็นของการวัดสถานะศูนย์
counts.get(0, 0.0) / num_shots
0.0138
กระบวนการสำหรับค่าสมาชิกเมทริกซ์เคอร์เนลเพียงค่าเดียวนี้สามารถทำซ้ำระหว่างคู่ข้อมูลอื่นๆ ในชุดข้อมูลของคุณเพื่อได้เมทริกซ์เคอร์เนลเต็มรูปแบบ มิติของเมทริกซ์เคอร์เนลถูกกำหนดโดยจำนวนจุดในข้อมูลการฝึก ไม่ใช่จำนวนฟีเจอร์ ดังนั้นต้นทุนการคำนวณในการจัดการเมทริกซ์เคอร์เนลให้เป็นโมเดลเชิงพยากรณ์จะไม่ขยายตามจำนวนฟีเจอร์หรือ Qubit แม้สำหรับชุดข้อมูลขนาดค่อนข้างเล็กที่มีฟีเจอร์จำนวนมาก ข้อมูลก็ยังต้องถูกจับคู่กับแผนที่ฟีเจอร์ที่ให้การจำแนกประเภทที่มีประสิทธิภาพ
การขยายและงานในอนาคต
วิธีเคอร์เนลต้องการให้เราวัด ได้อย่างแม่นยำที่สุด แต่ข้อผิดพลาดของ Gate และข้อผิดพลาดการอ่านค่าหมายความว่ามีความน่าจะเป็นที่ไม่เป็นศูนย์ ที่ Qubit ใดๆ จะถูกวัดผิดพลาดให้อยู่ในสถานะ แม้จะมีการทำให้ง่ายขึ้นว่าความน่าจะเป็นของ ควรเป็น 100% สำหรับฟีเจอร์จำนวนมากที่เข้ารหัสบน บิต ความน่าจะเป็นของการวัดบิตทั้งหมดให้เป็น อย่างถูกต้องจะลดลงเหลือ เมื่อ มีขนาดใหญ่ขึ้น วิธีการนี้จะเชื่อถือได้น้อยลงและน้อยลง การเอาชนะความยากลำบากนี้และขยายการประมาณเคอร์เนลไปสู่ฟีเจอร์มากขึ้นเรื่อยๆ เป็นพื้นที่ของการวิจัยปัจจุบัน หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับปัญหานี้ ดูงานของ Thanasilp, Wang, Cerezo, and Holmes. เราแนะนำให้คุณสำรวจสิ่งที่สามารถทำได้กับคอมพิวเตอร์ควอนตัมปัจจุบัน และมองไปข้างหน้าถึงสิ่งที่จะเป็นไปได้ในยุคของการแก้ไขข้อผิดพลาด
ทบทวน
การคำนวณเคอร์เนลควอนตัมเกี่ยวข้องกับ
- การคำนวณค่าสมาชิกเมทริกซ์เคอร์เนล โดยใช้คู่จุดข้อมูลการฝึก
- การเข้ารหัสข้อมูลและแมปผ่านการแมปฟีเจอร์
- การปรับ Circuit ของคุณสำหรับการรันบนคอมพิวเตอร์ควอนตัม/Backend จริง
เคอร์เนลควอนตัมสามารถนำไปใช้ในอัลกอริทึมการเรียนรู้ของเครื่องแบบคลาสสิกได้ ดังที่แสดงในบทเรียนนี้
สิ่งสำคัญที่ควรคำนึงเมื่อใช้เคอร์เนลควอนตัม:
- ชุดข้อมูลน่าจะได้ประโยชน์จากวิธีเคอร์เนลควอนตัมหรือไม่?
- ลองใช้แผนที่ฟีเจอร์และรูปแบบ entanglement ต่างๆ
- ความลึกของ Circuit เป็นที่ยอมรับได้หรือไม่?
- ลองรัน pass manager หลายครั้งและใช้ Circuit ที่มีความลึกน้อยที่สุดที่คุณหาได้
วิธีเคอร์เนลควอนตัมเป็นเครื่องมือที่มีศักยภาพสูงเมื่อมีการจับคู่ที่เหมาะสมระหว่างชุดข้อมูลที่มีฟีเจอร์ที่เหมาะกับควอนตัมและแผนที่ฟีเจอร์ควอนตัมที่เหมาะสม หากต้องการเข้าใจดีขึ้นว่าเคอร์เนลควอนตัมจะมีประโยชน์ที่ใด แนะนำให้อ่าน Liu, Arunachalam & Temme (2021)