דלג לתוכן הראשי

סיווג היברידי קוונטי-מוגבר עם אנסמבלים (תהליך עבודה ליציבות רשת חשמל)

הערכת שימוש: 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.0
  • qiskit-serverless~=0.24.0
  • qiskit-ibm-runtime v0.40.1
  • qiskit-ibm-catalog~=0.8.0
  • scikit-learn==1.5.2
  • pandas>=2.0.0,<3.0.0
  • imbalanced-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

שלב 3: הרצה באמצעות primitives של Qiskit

כעת אנו מריצים את תהליך העבודה המלא באמצעות פעולת create_fit_predict של פונקציית Singularity כדי לאמן, לבצע אופטימיזציה ולהעריך את ה-QuantumEnhancedEnsembleClassifier מקצה לקצה על תשתית IBM. הפונקציה בונה את האנסמבל, מיישמת אופטימיזציה קוונטית דרך primitives של Qiskit, ומחזירה גם תחזיות וגם מטא-נתוני עבודה (כולל זמן ריצה ושימוש במשאבים). החלוקה הקלאסית של הנתונים משלב 1 נעשית בה שימוש חוזר לצורך יכולת שחזור, כאשר נתוני ולידציה מועברים דרך fit_params כך שהאופטימיזציה יכולה לכוון היפר-פרמטרים באופן פנימי תוך שמירה על מערך המבחן שהושארה בצד ללא נגיעה.

בשלב זה, אנו חוקרים מספר תצורות של האנסמבל הקוונטי כדי להבין איך פרמטרי מפתח - במיוחד num_learners ו-regularization - משפיעים הן על איכות התוצאה והן על שימוש ב-QPU.

  • num_learners קובע את רוחב האנסמבל (ובמשתמע, את מספר ה-qubits), ומשפיע על הקיבולת של המודל והעלות החישובית.
  • regularization שולטת בדלילות ו-overfitting, ומעצבת כמה לומדים נשארים פעילים לאחר האופטימיזציה.

על ידי שינוי פרמטרים אלה, אנו יכולים לראות איך רוחב האנסמבל ו-regularization מתקשרים: הגדלת רוחב בדרך כלל משפרת F1 אך עולה יותר בזמן QPU, בעוד ש-regularization חזקה יותר או אדפטיבית יכולה לשפר הכללה בערך באותו טביעת רגל חומרה. תת-הסעיפים הבאים עוברים על שלוש תצורות מייצגות כדי להמחיש אפקטים אלה.

בסיס

תצורה זו משתמשת ב-num_learners = 10 ו-regularization = 7.

  • num_learners שולטת ברוחב האנסמבל - למעשה מספר הלומדים החלשים המשולבים, ועל חומרה קוונטית, מספר ה-qubits הנדרשים. ערך גדול יותר מרחיב את מרחב החיפוש הקומבינטורי ויכול לשפר דיוק ו-recall, אך גם מגדיל רוחב מעגל, זמן קומפילציה ושימוש כולל ב-QPU.
  • regularization מגדירה את חוזק העונש להכללת לומדים נוספים. עם regularization ברירת מחדל "onsite", ערכים גבוהים יותר אוכפים דלילות חזקה יותר (פחות לומדים נשמרים), בעוד שערכים נמוכים יותר מאפשרים אנסמבלים מורכבים יותר.

הגדרה זו מספקת בסיס בעלות נמוכה, ומראה איך אנסמבל קטן מתנהג לפני הגדלת רוחב או כיוון דלילות.

# Problem scale and regularization
NUM_LEARNERS = 10
REGULARIZATION = 7
# ----- Quantum-enhanced ensemble on IBM hardware -----
print("\n-- Submitting quantum-enhanced ensemble job --")
job_1 = singularity.run(
action="create_fit_predict",
name="grid_stability_qeec",
quantum_classifier="QuantumEnhancedEnsembleClassifier",
num_learners=NUM_LEARNERS,
regularization=REGULARIZATION,
optimizer_options=optimizer_options, # from Step 2
backend_name=backend, # least-busy compatible backend
instance=IBM_INSTANCE_QUANTUM,
random_state=RANDOM_STATE,
X_train=X_train_bal,
y_train=y_train_bal,
X_test=X_test,
fit_params={"validation_data": (X_val, y_val)},
options={"save": False},
)
result_1 = job_1.result()
print("Action status:", result_1.get("status"))
print("Action message:", result_1.get("message"))
print("Metadata:", result_1.get("metadata"))
qeec_pred_job_1 = np.array(result_1["data"]["predictions"])
_ = evaluate_predictions(qeec_pred_job_1, y_test)
-- Submitting quantum-enhanced ensemble job --
Action status: ok
Action message: Classifier created, fitted, and predicted.
Metadata: {'resource_usage': {'RUNNING: MAPPING': {'CPU_TIME': 267.05158376693726}, 'RUNNING: WAITING_QPU': {'CPU_TIME': 3336.8785166740417}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 152.4274561405182}, 'RUNNING: EXECUTING_QPU': {'QPU_TIME': 1550.1889700889587}}}
Accuracy: 0.868
Precision: 1.0
Recall: 0.868
F1: 0.9293361884368309
status_1 = job_1.status()
print("\nQuantum job status:", status_1)
Quantum job status: DONE

הגדלת מספר הלומדים

כאן אנו מגדילים num_learners מ-10 ← 30 תוך שמירה על regularization = 7.

  • לומדים נוספים מרחיבים את מרחב ההשערות, ומאפשרים למודל ללכוד דפוסים עדינים יותר, מה שיכול להרים מעט את F1.
  • ברוב המקרים, הפרש זמן הריצה בין 10 ל-30 לומדים אינו משמעותי, מה שמצביע על כך שרוחב המעגל הנוסף אינו מגדיל באופן משמעותי את עלות ההרצה.
  • השיפור באיכות עדיין עוקב אחר עקומת תשואות פוחתות: רווחים מוקדמים מופיעים כאשר האנסמבל גדל, אך הם מתייצבים כאשר לומדים נוספים תורמים פחות מידע חדש.

ניסוי זה מדגיש את הטרייד-אוף איכות-יעילות - הגדלת רוחב האנסמבל עשויה להציע רווחי דיוק קטנים ללא עונש משמעותי בזמן ריצה, בהתאם ל-backend ולתנאי transpilation.

# Problem scale and regularization
NUM_LEARNERS = 30
REGULARIZATION = 7
# ----- Quantum-enhanced ensemble on IBM hardware -----
print("\n-- Submitting quantum-enhanced ensemble job --")
job_2 = singularity.run(
action="create_fit_predict",
name="grid_stability_qeec",
quantum_classifier="QuantumEnhancedEnsembleClassifier",
num_learners=NUM_LEARNERS,
regularization=REGULARIZATION,
optimizer_options=optimizer_options, # from Step 2
backend_name=backend, # least-busy compatible backend
instance=IBM_INSTANCE_QUANTUM,
random_state=RANDOM_STATE,
X_train=X_train_bal,
y_train=y_train_bal,
X_test=X_test,
fit_params={"validation_data": (X_val, y_val)},
options={"save": False},
)
result_2 = job_2.result()
print("Action status:", result_2.get("status"))
print("Action message:", result_2.get("message"))
print("QPU Time:", result_2.get("metadata"))
qeec_pred_job_2 = np.array(result_2["data"]["predictions"])
_ = evaluate_predictions(qeec_pred_job_2, y_test)
-- Submitting quantum-enhanced ensemble job --
Action status: ok
Action message: Classifier created, fitted, and predicted.
QPU Time: {'resource_usage': {'RUNNING: MAPPING': {'CPU_TIME': 680.2116754055023}, 'RUNNING: WAITING_QPU': {'CPU_TIME': 80.80395102500916}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 154.4466371536255}, 'RUNNING: EXECUTING_QPU': {'QPU_TIME': 1095.822762966156}}}
Accuracy: 0.8946666666666667
Precision: 1.0
Recall: 0.8946666666666667
F1: 0.944405348346235
status_2 = job_2.status()
print("\nQuantum job status:", status_2)
Quantum job status: DONE

Regularization

בתצורה זו, אנו מגדילים ל-num_learners = 60 ומציגים regularization אדפטיבית לניהול דלילות בצורה אינטואיטיבית יותר.

  • עם regularization = "auto", האופטימייזר מוצא אוטומטית חוזק regularization מתאים שבוחר בערך regularization_ratio * num_learners לומדים חלשים לאנסמבל הסופי, במקום לתקן את העונש באופן ידני. זה מספק ממשק נוח יותר לניהול האיזון בין דלילות וגודל אנסמבל.
  • regularization_type = "alpha" מגדירה איך העונש מיושם. בניגוד ל-onsite, שהיא לא חסומה [0, ∞], alpha חסומה בין [0, 1], מה שמקל על כיוון ופרשנות. הפרמטר שולט בטרייד-אוף בין עונשים אינדיבידואליים וזוגיים, ומציע טווח תצורה חלק יותר.
  • regularization_desired_ratio ≈ 0.82 מציין את פרופורציית היעד של לומדים לשמור פעילים לאחר regularization - כאן, בערך 82% מהלומדים נשמרים, גוזמים את 18% החלשים ביותר אוטומטית.

בעוד ש-regularization אדפטיבית מפשטת תצורה ועוזרת לשמור על אנסמבל מאוזן, היא לא בהכרח מבטיחה ביצועים טובים או יציבים יותר. האיכות בפועל תלויה בבחירת פרמטר regularization מתאים, וכיוון עדין שלו דרך cross-validation יכול להיות יקר מבחינה חישובית. היתרון העיקרי טמון בשימושיות ופרשנות משופרות במקום ברווחי דיוק ישירים.

# Problem scale and regularization
NUM_LEARNERS = 60
REGULARIZATION = "auto"
REGULARIZATION_TYPE = "alpha"
REGULARIZATION_RATIO = 0.82
# ----- Quantum-enhanced ensemble on IBM hardware -----
print("\n-- Submitting quantum-enhanced ensemble job --")
job_3 = singularity.run(
action="create_fit_predict",
name="grid_stability_qeec",
quantum_classifier="QuantumEnhancedEnsembleClassifier",
num_learners=NUM_LEARNERS,
regularization=REGULARIZATION,
regularization_type=REGULARIZATION_TYPE,
regularization_desired_ratio=REGULARIZATION_RATIO,
optimizer_options=optimizer_options, # from Step 2
backend_name=backend, # least-busy compatible backend
instance=IBM_INSTANCE_QUANTUM,
random_state=RANDOM_STATE,
X_train=X_train_bal,
y_train=y_train_bal,
X_test=X_test,
fit_params={"validation_data": (X_val, y_val)},
options={"save": False},
)
result_3 = job_3.result()
print("Action status:", result_3.get("status"))
print("Action message:", result_3.get("message"))
print("Metadata:", result_3.get("metadata"))
qeec_pred_job_3 = np.array(result_3["data"]["predictions"])
_ = evaluate_predictions(qeec_pred_job_3, y_test)
-- Submitting quantum-enhanced ensemble job --
Action status: ok
Action message: Classifier created, fitted, and predicted.
Metadata: {'resource_usage': {'RUNNING: MAPPING': {'CPU_TIME': 1387.7451872825623}, 'RUNNING: WAITING_QPU': {'CPU_TIME': 95.41597843170166}, 'RUNNING: POST_PROCESSING': {'CPU_TIME': 171.78878355026245}, 'RUNNING: EXECUTING_QPU': {'QPU_TIME': 1146.5584812164307}}}
Accuracy: 0.908
Precision: 1.0
Recall: 0.908
F1: 0.9517819706498952
status_3 = job_3.status()
print("\nQuantum job status:", status_3)
Quantum job status: DONE

שלב 4: עיבוד לאחר והחזרת תוצאה בפורמט קלאסי רצוי

כעת אנו מעבדים פלטים מההרצות הקלאסיות והקוונטיות כאחד, וממירים אותם לפורמט עקבי להערכה במורד הזרם. שלב זה משווה איכות חיזוי באמצעות מדדים סטנדרטיים - accuracy, precision, recall ו-F1 - ומנתח איך רוחב אנסמבל (num_learners) ובקרת דלילות (regularization) משפיעים הן על ביצועים והן על התנהגות חישובית.

בסיס AdaBoost הקלאסי מספק ייחוס קומפקטי ויציב ללמידה בסקאלה קטנה. הוא מתפקד היטב עם אנסמבלים מוגבלים ותקורת חישוב זניחה, ומשקף את החוזק של boosting מסורתי כאשר מרחב ההשערות עדיין בר-טיפול. התצורות הקוונטיות (qeec_pred_job_1, qeec_pred_job_2 ו-qeec_pred_job_3) מרחיבות בסיס זה על ידי הטמעת תהליך בחירת האנסמבל בתוך לולאת אופטימיזציה קוונטית וריאציונית. זה מאפשר למערכת לחקור באופן סימולטני תת-קבוצות גדולות באופן אקספוננציאלי של לומדים בסופרפוזיציה, ומטפל בטבע הקומבינטורי של בחירת אנסמבל בצורה יעילה יותר ככל שהסקאלה עולה.

תוצאות מראות שהגדלת num_learners מ-10 ל-30 משפרת recall ו-F1, ומאשרת שאנסמבל רחב יותר לוכד אינטראקציות עשירות יותר בין לומדים חלשים. הרווח הוא תת-ליניארי על חומרה נוכחית - כל לומד נוסף מניב תוספות דיוק קטנות יותר - אך התנהגות ההגדלה הבסיסית נשארת נוחה כי האופטימייזר הקוונטי יכול לחפש במרחבי תצורה רחבים יותר ללא התפוצצות אקספוננציאלית טיפוסית של בחירת תת-קבוצה קלאסית. Regularization מציגה ניואנס נוסף: λ=7 קבוע אוכפת דלילות עקבית ומייצבת התכנסות, בעוד ש-α-regularization אדפטיבית מכוונת דלילות אוטומטית בהתבסס על קורלציות בין לומדים. גיזום דינמי זה לעתים קרובות משיג F1 מעט גבוה יותר לאותו רוחב qubit, מאזן מורכבות מודל והכללה.

כאשר משווים ישירות עם בסיס AdaBoost, התצורה הקוונטית הקטנה ביותר (L=10) משחזרת דיוק דומה, מה שמאמת את נכונות צינור ההיברידי. ברוחבים גדולים יותר, גרסאות קוונטיות - במיוחד עם auto-regularization - מתחילות לעלות על הבסיס הקלאסי בצורה מתונה, מה שמראה recall ו-F1 משופרים ללא צמיחה ליניארית בעלות חישובית. שיפורים אלה אינם מצביעים על "יתרון קוונטי" מיידי אלא יעילות הגדלה: האופטימייזר הקוונטי שומר על ביצועים ברי-טיפול כאשר האנסמבל מתרחב, שם גישה קלאסית תתמודד עם צמיחה אקספוננציאלית במורכבות בחירת תת-קבוצה.

בפועל:

  • השתמשו בבסיס קלאסי לולידציה והשוואת ביצועים מהירה על מערכי נתונים קטנים.
  • החילו אנסמבלים קוונטיים כאשר רוחב מודל או מורכבות תכונות גדלים - חיפוש מבוסס QAOA מתרחב בצורה יפה יותר באזורים אלה.
  • השתמשו בα-regularization אדפטיבית כדי לשמור על דלילות והכללה ללא הגדלת רוחב מעגל.
  • עקבו אחר זמן QPU ועומק כדי לאזן רווחי איכות מול מגבלות חומרה לטווח קרוב.

יחד, ניסויים אלה מראים שאנסמבלים מאופטמים קוונטית משלימים שיטות קלאסיות: הם משחזרים דיוק בסיס בסקאלות קטנות תוך הצעת נתיב להגדלה יעילה על בעיות למידה קומבינטוריות גדולות יותר. ככל שהחומרה משתפרת, יתרונות הגדלה אלה צפויים להצטבר, ולהרחיב את הגודל והעומק הישים של מודלים מבוססי אנסמבל מעבר למה שמעשי קלאסית.

הערכת מדדים לכל תצורה

כעת אנו מעריכים את כל התצורות - בסיס AdaBoost הקלאסי ושלושת האנסמבלים הקוונטיים - באמצעות עזר evaluate_predictions כדי לחשב accuracy, precision, recall ו-F1 על אותו מערך מבחן. השוואה זו מבהירה איך אופטימיזציה קוונטית מתרחבת ביחס לגישה הקלאסית: ברוחבים קטנים, שתיהן מתפקדות באופן דומה; ככל שהאנסמבלים גדלים, השיטה הקוונטית יכולה לחקור מרחבי השערות גדולים יותר בצורה יעילה יותר. הטבלה המתקבלת לוכדת מגמות אלה בצורה עקבית וכמותית.

results = []

# Classical baseline
acc_b, prec_b, rec_b, f1_b = evaluate_predictions(baseline_pred, y_test)
results.append(
{
"Config": "AdaBoost (Classical)",
"Accuracy": acc_b,
"Precision": prec_b,
"Recall": rec_b,
"F1": f1_b,
}
)

# Quantum runs
for label, preds in [
("QEEC L=10, reg=7", qeec_pred_job_1),
("QEEC L=30, reg=7", qeec_pred_job_2),
(f"QEEC L=60, reg=auto (α={REGULARIZATION_RATIO})", qeec_pred_job_3),
]:
acc, prec, rec, f1 = evaluate_predictions(preds, y_test)
results.append(
{
"Config": label,
"Accuracy": acc,
"Precision": prec,
"Recall": rec,
"F1": f1,
}
)

df_results = pd.DataFrame(results)
df_results
Accuracy: 0.7893333333333333
Precision: 1.0
Recall: 0.7893333333333333
F1: 0.8822652757078987
Accuracy: 0.868
Precision: 1.0
Recall: 0.868
F1: 0.9293361884368309
Accuracy: 0.8946666666666667
Precision: 1.0
Recall: 0.8946666666666667
F1: 0.944405348346235
Accuracy: 0.908
Precision: 1.0
Recall: 0.908
F1: 0.9517819706498952
Config  Accuracy  Precision    Recall        F1
0 AdaBoost (Classical) 0.789333 1.0 0.789333 0.882265
1 QEEC L=10, reg=7 0.868000 1.0 0.868000 0.929336
2 QEEC L=30, reg=7 0.894667 1.0 0.894667 0.944405
3 QEEC L=60, reg=auto (α=0.82) 0.908000 1.0 0.908000 0.951782

תרשים העמודות המקובץ למטה משווה Accuracy ו-F1 על פני בסיס קלאסי והאנסמבלים הקוונטיים (L=10, L=30 ו-L=60 auto-α). הוא ממחיש איך accuracy מתייצבת בעוד F1 משתפרת בהדרגה ככל שרוחב האנסמבל הקוונטי עולה, מדגים ששיטה היברידית שומרת על הגדלת ביצועים ללא צמיחת עלות אקספוננציאלית טיפוסית של בחירת תת-קבוצה קלאסית.

x = np.arange(len(df_results))
width = 0.35
plt.figure(figsize=(7.6, 4.6))
plt.bar(x - width / 2, df_results["Accuracy"], width=width, label="Accuracy")
plt.bar(x + width / 2, df_results["F1"], width=width, label="F1")
plt.xticks(x, df_results["Config"], rotation=10)
plt.ylabel("Score")
plt.title("Classical vs Quantum ensemble performance")
plt.legend()
plt.ylim(0, 1.0)
plt.tight_layout()
plt.show()

Output of the previous code cell

פרשנות

התרשים מאשר את דפוס ההגדלה הצפוי. AdaBoost הקלאסי מתפקד בצורה חזקה עבור אנסמבלים קטנים יותר אך הופך יקר יותר ויותר להרחבה ככל שמספר הלומדים החלשים גדל, מכיוון שבעיית בחירת תת-הקבוצה שלו מתרחבת קומבינטורית. המודלים המוגברים קוונטית משכפלים דיוק קלאסי ברוחבים נמוכים ומתחילים לעלות עליו ככל שגודל האנסמבל עולה, במיוחד תחת α-regularization אדפטיבית. זה משקף את היכולת של האופטימייזר הקוונטי לדגום ולהעריך תת-קבוצות מועמדות רבות במקביל דרך סופרפוזיציה, לשמור על חיפוש בר-טיפול אפילו ברוחבים גבוהים יותר. בעוד תקורת חומרה נוכחית מקזזת חלק מהרווחים התאורטיים, המגמה ממחישה את יתרון יעילות ההגדלה של הניסוח הקוונטי. במונחים מעשיים, השיטה הקלאסית נשארת עדיפה עבור השוואת ביצועים קלות משקל, בעוד שאנסמבלים מוגברים קוונטית הופכים יתרוניים ככל שממדיות המודל וגודל האנסמבל מתרחבים, ומציעים טרייד-אופים טובים יותר בין דיוק, הכללה וצמיחה חישובית.

נספח: יתרונות הגדלה ושיפורים

יתרון יכולת ההרחבה של QuantumEnhancedEnsembleClassifier נובע מהאופן שבו תהליך בחירת האנסמבל ממופה לאופטימיזציה קוונטית. שיטות למידת אנסמבל קלאסיות, כמו AdaBoost או random forests, הופכות יקרות חישובית ככל שמספר הלומדים החלשים עולה מכיוון שבחירת תת-הקבוצה האופטימלית היא בעיה קומבינטורית שמתרחבת אקספוננציאלית.

לעומת זאת, הניסוח הקוונטי - המיושם כאן דרך אלגוריתם האופטימיזציה הקוונטי המקורב (QAOA) - יכול לחקור מרחבי חיפוש גדולים אקספוננציאלית אלה בצורה יעילה יותר על ידי הערכת תצורות מרובות בסופרפוזיציה. כתוצאה מכך, זמן האימון אינו גדל באופן משמעותי עם מספר הלומדים, מה שמאפשר למודל להישאר יעיל גם ככל שרוחב האנסמבל עולה.

בעוד שחומרה נוכחית מציגה קצת רעש ומגבלות עומק, תהליך עבודה זה מדגים גישה היברידית לטווח קרוב שבה רכיבים קלאסיים וקוונטיים משתפים פעולה: האופטימייזר הקוונטי מספק נוף אתחול טוב יותר ללולאה הקלאסית, משפר התכנסות ואיכות מודל סופית. ככל שמעבדים קוונטיים מתפתחים, יתרונות יכולת ההרחבה האלה צפויים להתרחב למערכי נתונים גדולים יותר, אנסמבלים רחבים יותר ועומקי מעגל עמוקים יותר.

אסמכתאות

  1. Introduction to Qiskit Functions
  2. Multiverse Computing Singularity Machine Learning

סקר מדריך

אנא הקדישו דקה למתן משוב על מדריך זה. התובנות שלכם יעזרו לנו לשפר את הצעות התוכן שלנו וחווית המשתמש.

קישור לסקר