סיווג היברידי קוונטי-מוגבר עם אנסמבלים (תהליך עבודה ליציבות רשת חשמל)
הערכת שימוש: 20 דקות בזמן QPU עבור כל עבודה על מעבד Eagle r3. (הערה: זו הערכה בלבד. זמן הריצה שלך עשוי להשתנות.)
רקע
מדריך זה מדגים תהליך עבודה היברידי קוונטי-קלאסי המשפר אנסמבל קלאסי באמצעות שלב אופטימיזציה קוונטי. באמצעות "Singularity Machine Learning – Classification" של Multiverse Computing (פונקציית Qiskit), אנחנו מאמנים מאגר של לומדים קונבנציונליים (לדוגמה, עצי החלטה, k-NN, רגרסיה לוגיסטית) ולאחר מכן משכללים את המאגר עם שכבה קוונטית כדי לשפר גיוון והכללה. המטרה היא מעשית: במשימת ניבוי יציבות רשת חשמל אמיתית, אנחנו משווים בסיס קלאסי חזק עם חלופה מאופטמת קוונטית תחת אותן חלוקות נתונים, כך שתוכלו לראות היכן השלב הקוונטי עוזר ומה המחיר שלו.
מדוע זה חשוב: בחירת תת-קבוצה טובה ממספר רב של לומדים חלשים היא בעיה קומבינטורית שגדלה במהירות עם גודל האנסמבל. היוריסטיקות קלאסיות כמו boosting, bagging ו-stacking מתפקדות היטב בסקאלות בינוניות אך יכולות להתקשות לחקור באופן יעיל ספריות גדולות ומיותרות של מודלים. הפונקציה משלבת אלגוריתמים קוונטיים - במיוחד QAOA (ובאופן אופציונלי VQE בתצורות אחרות) - כדי לחפש במרחב זה בצורה יעילה יותר לאחר שהלומדים הקלאסיים אומנו, מה שמגביר את הסיכוי למצוא תת-קבוצה קומפקטית ומגוונת שמכללה טוב יותר.
חשוב לציין, סקאלת הנתונים אינה מוגבלת על ידי qubits. העבודה הכבדה על הנתונים - עיבוד מקדים, אימון מאגר הלומדים והערכה - נשארת קלאסית ויכולה לטפל במיליוני דוגמאות. Qubits רק קובעים את גודל האנסמבל המשמש בשלב הבחירה הקוונטי. הפרדה זו היא מה שהופך את הגישה לישימה על חומרה של היום: אתם שומרים על תהליכי עבודה מוכרים של scikit-learn עבור נתונים ואימון מודלים תוך קריאה לשלב הקוונטי דרך ממשק פעולה נקי ב-Qiskit Functions.
בפועל, בעוד שניתן לספק לאנסמבל סוגי לומדים שונים (לדוגמה, עצי החלטה, רגרסיה לוגיסטית או k-NN), עצי החלטה נוטים להציג ביצועים הטובים ביותר. האופטימייזר מעדיף באופן עקבי חברי אנסמבל חזקים יותר - כאשר לומדים הטרוגניים מסופקים, מודלים חלשים יותר כמו רגרסורים ליניאריים בדרך כלל נגזמים לטובת כאלה אקספרסיביים יותר כמו עצי החלטה.
מה תעשו כאן: הכנה ואיזון של מערך נתוני יציבות רשת חשמל; הקמת בסיס AdaBoost קלאסי; הרצת מספר תצורות קוונטיות שמשנות את רוחב האנסמבל והרגולריזציה; הרצה על סימולטורים של IBM® או QPUs דרך Qiskit Serverless; והשוואת דיוק, precision, recall ו-F1 בכל הרצות. לאורך הדרך, תשתמשו בדפוס הפעולה של הפונקציה (create, fit, predict, fit_predict, create_fit_predict) ובקרות מפתח:
- סוגי regularization:
onsite(λ) לדלילות ישירה ו-alphaלטרייד-אוף מבוסס יחס בין תנאי אינטראקציה ו-onsite - Auto-regularization: הגדרת
regularization="auto"עם יחס בחירה יעד כדי להתאים דלילות אוטומטית - אפשרויות אופטימייזר: סימולטור מול QPU, חזרות, אופטימייזר קלאסי והאפשרויות שלו, עומק טרנספילציה והגדרות sampler/estimator של runtime
ביצועי ייחוס בתיעוד מראים שהדיוק משתפר כאשר מספר הלומדים (qubits) עולה בבעיות מאתגרות, כאשר המסווג הקוונטי משתווה או עולה על אנסמבל קלאסי דומה. במדריך זה, תשחזרו את תהליך העבודה מקצה לקצה ותבחנו מתי הגדלת רוחב האנסמבל או מעבר ל-regularization אדפטיבי מניבים F1 טוב יותר בשימוש סביר במשאבים. התוצאה היא תצוגה מבוססת של איך שלב אופ טימיזציה קוונטי יכול להשלים, במקום להחליף, למידת אנסמבל קלאסית ביישומים אמיתיים.
דרישות
לפני תחילת מדריך זה, ודאו שהחבילות הבאות מותקנות בסביבת Python שלכם:
qiskit[visualization]~=2.1.0qiskit-serverless~=0.24.0qiskit-ibm-runtime v0.40.1qiskit-ibm-catalog~=0.8.0scikit-learn==1.5.2pandas>=2.0.0,<3.0.0imbalanced-learn~=0.12.3
הגדרה
בסעיף זה, אנחנו מאתחלים את לקוח Qiskit Serverless וטוענים את פונקציית Singularity Machine Learning – Classification שמסופקת על ידי Multiverse Computing. עם Qiskit Serverless, אתם יכולים להריץ תהליכי עבודה היברידיים קוונטיים-קלאסיים על תשתית ענן מנוהלת של IBM מבלי לדאוג לניהול משאבים. תזדקקו למפתח API של IBM Quantum Platform ושם משאב הענן שלכם (CRN) כדי לאמת ולגשת ל-Qiskit Functions.
הורדת מערך הנתונים
כדי להריץ מדריך זה, אנחנו משתמשים במערך נתוני סיווג יציבות רשת חשמל מעובד המכיל קריאות חיישני מערכת חשמל מתויגות.
התא הבא יוצר אוטומטית את מבנה התיקיות הנדרש ומוריד את קבצי האימון והמבחן ישירות לסביבה שלכם באמצעות wget.
אם יש לכם את הקבצים האלה מקומית כבר, שלב זה ידרוס אותם בבטחה כדי להבטיח עקביות גרסה.
# Added by doQumentation — required packages for this notebook
!pip install -q imbalanced-learn matplotlib numpy pandas qiskit-ibm-catalog qiskit-ibm-runtime scikit-learn
## Download dataset for Grid Stability Classification
# Create data directory if it doesn't exist
!mkdir -p data_tutorial/grid_stability
# Download the training and test sets from the official Qiskit documentation repo
!wget -q --show-progress -O data_tutorial/grid_stability/train.csv \
https://raw.githubusercontent.com/Qiskit/documentation/main/datasets/tutorials/grid_stability/train.csv
!wget -q --show-progress -O data_tutorial/grid_stability/test.csv \
https://raw.githubusercontent.com/Qiskit/documentation/main/datasets/tutorials/grid_stability/test.csv
# Check the files have been downloaded
!echo "Dataset files downloaded:"
!ls -lh data_tutorial/grid_stability/*.csv
data_tutorial/grid_ 100%[===================>] 612.94K --.-KB/s in 0.01s
data_tutorial/grid_ 100%[===================>] 108.19K --.-KB/s in 0.006s
Dataset files downloaded:
-rw-r--r-- 1 coder coder 109K Nov 8 18:50 data_tutorial/grid_stability/test.csv
-rw-r--r-- 1 coder coder 613K Nov 8 18:50 data_tutorial/grid_stability/train.csv
ייבוא חבילות נדרשות
בסעיף זה, אנחנו מייבאים את כל חבילות Python ומודולי Qiskit המשמשים לאורך המדריך.
אלה כוללים ספריות מדעיות ליבה לטיפול בנתונים והערכת מודלים - כמו NumPy, pandas ו-scikit-learn - יחד עם כלי ויזואליזציה ורכיבי Qiskit להרצת המודל המוגבר קוונטית.
אנחנו גם מייבאים את QiskitRuntimeService ו-QiskitFunctionsCatalog כדי להתחבר עם שירותי IBM Quantum® ולגשת לפונקציית Singularity Machine Learning.
from typing import Tuple
import warnings
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from imblearn.over_sampling import RandomOverSampler
from qiskit_ibm_catalog import QiskitFunctionsCatalog
from qiskit_ibm_runtime import QiskitRuntimeService
from sklearn.ensemble import AdaBoostClassifier
from sklearn.metrics import (
accuracy_score,
f1_score,
precision_score,
recall_score,
)
from sklearn.model_selection import train_test_split
warnings.filterwarnings("ignore")
הגדרת משתנים קבועים
IBM_TOKEN = ""
IBM_INSTANCE_TEST = ""
IBM_INSTANCE_QUANTUM = ""
FUNCTION_NAME = "multiverse/singularity"
RANDOM_STATE: int = 123
TRAIN_PATH = "data_tutorial/grid_stability/train.csv"
TEST_PATH = "data_tutorial/grid_stability/test.csv"
חיבור ל-IBM Quantum וטעינת פונקציית Singularity
כעת, אנחנו מאמתים עם שירותי IBM Quantum וטוענים את פונקציית Singularity Machine Learning – Classification מקטלוג Qiskit Functions.
ה-QiskitRuntimeService מקים חיבור מאובטח ל-IBM Quantum Platform באמצעות אסימון ה-API שלכם ו-instance CRN, ומאפשר גישה ל-backends קוונטיים.
לאחר מכן נעשה שימוש ב-QiskitFunctionsCatalog כדי לאחזר את פונקציית Singularity לפי שם ("multiverse/singularity"), מה שמאפשר לנו לקרוא לה מאוחר יותר לחישוב היברידי קוונטי-קלאסי.
אם ההגדרה מצליחה, תראו הודעת אישור המציינת שהפונקציה נטענה כראוי.
service = QiskitRuntimeService(
token=IBM_TOKEN,
channel="ibm_quantum_platform",
instance=IBM_INSTANCE_QUANTUM,
)
backend = service.least_busy()
catalog = QiskitFunctionsCatalog(
token=IBM_TOKEN,
instance=IBM_INSTANCE_TEST,
channel="ibm_quantum_platform",
)
singularity = catalog.load(FUNCTION_NAME)
print(
"Successfully connected to IBM Qiskit Serverless and loaded the Singularity function."
)
print("Catalog:", catalog)
print("Singularity function:", singularity)
Successfully connected to IBM Qiskit Serverless and loaded the Singularity function.
Catalog: <QiskitFunctionsCatalog>
Singularity function: QiskitFunction(multiverse/singularity)
הגדרת פונקציות עזר
לפני הרצת הניסויים העיקריים, אנחנו מגדירים מספר פונקציות עזר קטנות שמייעלות טעינת נתונים והערכת מודלים.
load_data()קוראת את קבצי ה-CSV לתוך מערכי NumPy, מפרידה features ו-labels לתאימות עםscikit-learnותהליכי עבודה קוונטיים.evaluate_predictions()מחשבת מדדי ביצוע מפתח - accuracy, precision, recall ו-F1-score - ומדווחת באופן אופציונלי זמן ריצה אם מסופק מידע תזמון.
פונקציות עזר אלה מפשטות פעולות חוזרות בהמשך המחברת ומבטיחות דיווח מדדים עקבי על פני מסווגים קלאסיים וקוונטיים כאחד.
def load_data(data_path: str) -> Tuple[np.ndarray, np.ndarray]:
"""Load data from the given path to X and y arrays."""
df: pd.DataFrame = pd.read_csv(data_path)
return df.iloc[:, :-1].values, df.iloc[:, -1].values
def evaluate_predictions(predictions, y_true):
"""Compute and print accuracy, precision, recall, and F1 score."""
accuracy = accuracy_score(y_true, predictions)
precision = precision_score(y_true, predictions)
recall = recall_score(y_true, predictions)
f1 = f1_score(y_true, predictions)
print("Accuracy:", accuracy)
print("Precision:", precision)
print("Recall:", recall)
print("F1:", f1)
return accuracy, precision, recall, f1
שלב 1: מיפוי קלטים קלאסיים לבעיה קוונטית
אנחנו מתחילים בהכנת מערך הנתונים לניסוי היברידי קוונטי-קלאסי. המטרה של שלב זה היא להמיר את נתוני יציבות הרשת הגולמיים לחלוקות אימון, ולידציה ומבחן מאוזנות שניתן להשתמש בהן באופן עקבי הן על ידי תהליכי עבודה קלאסיים והן קוונטיים. שמירה על חלוקות זהות מבטיחה שהשוואות ביצועים מאוחר יותר יהיו הוגנות ושניתן לשחזר אותן.
טעינת נתונים ועיבוד מקדים
תחילה אנחנו טוענים את קבצי ה-CSV של האימון והמבחן, יוצרים חלוקת ולידציה, ומאזנים את מערך הנתונים באמצעות over-sampling אקראי. איזון מונע הטיה כלפי המחלקה הרוב ומספק אות למידה יציב יותר עבור מודלי אנסמבל קלאסיים וקוונטיים כאחד.
# Load and upload the data
X_train, y_train = load_data(TRAIN_PATH)
X_test, y_test = load_data(TEST_PATH)
X_train, X_val, y_train, y_val = train_test_split(
X_train, y_train, test_size=0.2, random_state=RANDOM_STATE
)
# Balance the dataset through over-sampling of the positive class
ros = RandomOverSampler(random_state=RANDOM_STATE)
X_train_bal, y_train_bal = ros.fit_resample(X_train, y_train)
print("Shapes:")
print(" X_train_bal:", X_train_bal.shape)
print(" y_train_bal:", y_train_bal.shape)
print(" X_val:", X_val.shape)
print(" y_val:", y_val.shape)
print(" X_test:", X_test.shape)
print(" y_test:", y_test.shape)
Shapes:
X_train_bal: (5104, 12)
y_train_bal: (5104,)
X_val: (850, 12)
y_val: (850,)
X_test: (750, 12)
y_test: (750,)
בסיס קלאסי: ייחוס AdaBoost
לפני הרצת אופטימיזציה קוונטית כלשהי, אנחנו מאמנים בסיס קלאסי חזק - מסווג AdaBoost סטנדרטי - על אותם נתונים מאוזנים. זה מספק נקודת ייחוס שניתן לשחזר להשוואה מאוחר יותר, ועוזר לכמת האם אופטימיזציה קוונטית משפרת הכללה או יעילות מעבר לאנסמבל קלאסי מכוון היטב.
# ----- Classical baseline: AdaBoost -----
baseline = AdaBoostClassifier(n_estimators=60, random_state=RANDOM_STATE)
baseline.fit(X_train_bal, y_train_bal)
baseline_pred = baseline.predict(X_test)
print("Classical AdaBoost baseline:")
_ = evaluate_predictions(baseline_pred, y_test)
Classical AdaBoost baseline:
Accuracy: 0.7893333333333333
Precision: 1.0
Recall: 0.7893333333333333
F1: 0.8822652757078987
שלב 2: אופטימיזציה של הבעיה להרצה על חומרה קוונטית
משימת בחירת האנסמבל מיוצגת כבעיית אופטימיזציה קומבינטורית שבה כל לומד חלש הוא משתנה החלטה בינארי, והמטרה מאזנת דיוק עם דלילות דרך תנאי regularization. ה-QuantumEnhancedEnsembleClassifier פותר זאת עם QAOA על חומרה של IBM, תוך שמירה על אפשרות חקירה מבוססת סימולטור. ה-optimizer_options שולטות בלולאה ההיברידית: simulator=False מנתבת מעגלים ל-QPU שנבחר, num_solutions מגדילה את רוחב החיפוש, ו-classical_optimizer_options (עבור האופטימייזר הקלאסי הפנימי) שולטות בהתכנסות; ערכים סביב 60 איטרציות הם איזון טוב לאיכות וזמן ריצה. אפשרויות runtime - כמו עומק מעגל מתון (reps) ומאמץ transpilation סטנדרטי - עוזרות להבטיח ביצועים איתנים על פני מכשירים. התצורה למטה היא פרופיל "התוצאות הטובות ביותר" שבו נשתמש להרצות חומרה; ייתכן שתרצו גם ליצור גרסה מדומה לחלוטין על ידי החלפת simulator=True כדי להריץ את תהליך העבודה מבלי לצרוך זמן QPU.
# QAOA / runtime configuration for best results on hardware
optimizer_options = {
"simulator": False, # set True to test locally without QPU
"num_solutions": 100_000, # broaden search over candidate ensembles
"reps": 3, # QAOA depth (circuit layers)
"optimization_level": 3, # transpilation effort
"num_transpiler_runs": 30, # explore multiple layouts
"classical_optimizer": "COBYLA", # robust default for this landscape
"classical_optimizer_options": {
"maxiter": 60 # practical convergence budget
},
# You can pass backend-specific options; leaving None uses least-busy routing
"estimator_options": None,
"sampler_options": None,
}
print("Configured hardware optimization profile:")
for key, value in optimizer_options.items():
print(f" {key}: {value}")
Configured hardware optimization profile:
simulator: False
num_solutions: 100000
reps: 3
optimization_level: 3
num_transpiler_runs: 30
classical_optimizer: COBYLA
classical_optimizer_options: {'maxiter': 60}
estimator_options: None
sampler_options: None