Hybrydowa klasyfikacja zespołowa z ulepszeniem kwantowym (przepływ pracy dla stabilności sieci)
Szacowany czas użycia: 20 minut na QPU dla każdego zadania na procesorze Eagle r3. (UWAGA: To jedynie szacunek. Rzeczywisty czas może się różnić.)
Wprowadzenie
Ten samouczek przedstawia hybrydowy przepływ pracy kwantowo-klasyczny, który wzbogaca klasyczny zespół modeli o krok optymalizacji kwantowej. Korzystając z funkcji „Singularity Machine Learning – Classification" firmy Multiverse Computing (funkcja Qiskit), trenujemy pulę konwencjonalnych uczniów (na przykład drzewa decyzyjne, k-NN, regresję logistyczną), a następnie udoskonalamy tę pulę za pomocą warstwy kwantowej, aby poprawić różnorodność i zdolność generalizacji. Cel jest praktyczny: na rzeczywistym zadaniu predykcji stabilności sieci energetycznej porównujemy silną linię bazową klasyczną z kwantowo-optymalizowaną alternatywą przy tych samych podziałach danych, dzięki czemu możesz zobaczyć, gdzie krok kwantowy pomaga i ile kosztuje.
Dlaczego to ma znaczenie: wybór dobrego podzbioru spośród wielu słabych uczniów to problem kombinatoryczny, który szybko rośnie wraz z rozmiarem zespołu. Klasyczne heurystyki, takie jak boosting, bagging i stacking, sprawdzają się dobrze w umiarkowanych skalach, ale mogą mieć trudności z efektywną eksploracją dużych, redundantnych bibliotek modeli. Funkcja integruje algorytmy kwantowe — konkretnie QAOA (a opcjonalnie VQE w innych konfiguracjach) — aby skuteczniej przeszukiwać tę przestrzeń po wytrenowaniu klasycznych uczniów, zwiększając szansę na znalezienie zwartego, zróżnicowanego podzbioru, który lepiej generalizuje.
Co istotne, skala danych nie jest ograniczona przez qubity. Główna praca na danych — przetwarzanie wstępne, trening puli uczniów i ewaluacja — pozostaje klasyczna i może obsługiwać miliony przykładów. Qubity określają jedynie rozmiar zespołu używanego w kroku kwantowego wyboru. To rozdzielenie sprawia, że podejście jest wykonalne na obecnym sprzęcie: zachowujesz znane przepływy pracy scikit-learn do obsługi danych i trenowania modeli, wywołując krok kwantowy przez przejrzysty interfejs akcji w Qiskit Functions.
W praktyce, choć do zespołu można dostarczyć różne typy uczniów (np. drzewa decyzyjne, regresję logistyczną lub k-NN), drzewa decyzyjne zazwyczaj działają najlepiej. Optymalizator konsekwentnie faworyzuje silniejszych członków zespołu — gdy dostarczane są heterogeniczne uczniowie, słabsze modele, takie jak regresory liniowe, są zazwyczaj eliminowane na rzecz bardziej ekspresywnych, jak drzewa decyzyjne.
Co zrobisz w tym samouczku: przygotujesz i zbalânsujesz zbiór danych stabilności sieci; ustanowisz klasyczną linię bazową AdaBoost; uruchomisz kilka konfiguracji kwantowych z różną szerokością zespołu i regularyzacją; wykonasz obliczenia na symulatorach IBM® lub QPU przez Qiskit Serverless; oraz porównasz dokładność, precyzję, recall i F1 we wszystkich uruchomieniach. Po drodze użyjesz wzorca akcji funkcji (create, fit, predict, fit_predict, create_fit_predict) oraz kluczowych parametrów:
- Typy regularyzacji:
onsite(λ) dla bezpośredniej rzadkości ialphadla proporcjonalnego kompromisu między składnikami interakcji a onsite - Automatyczna regularyzacja: ustaw
regularization="auto"z docelowym współczynnikiem wyboru, aby automatycznie dostosować rzadkość - Opcje optymalizatora: symulator versus QPU, powtórzenia, klasyczny optymalizator i jego opcje, głębokość transpilacji oraz ustawienia Sampler/Estimator środowiska uruchomieniowego
Benchmarki w dokumentacji pokazują, że dokładność poprawia się wraz ze wzrostem liczby uczniów (qubitów) w trudniejszych problemach, a klasyfikator kwantowy dorównuje lub przewyższa porównywalny klasyczny zespół. W tym samouczku odtworzysz cały przepływ pracy od początku do końca i sprawdzisz, kiedy zwiększenie szerokości zespołu lub przełączenie na adaptacyjną regularyzację przynosi lepszy wynik F1 przy rozsądnym zużyciu zasobów. Rezultatem jest praktyczny wgląd w to, jak krok optymalizacji kwantowej może uzupełniać, a nie zastępować, klasyczne uczenie zespołowe w rzeczywistych zastosowaniach.
Wymagania
Przed rozpoczęciem tego samouczka upewnij się, że w swoim środowisku Python masz zainstalowane następujące pakiety:
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
Konfiguracja
W tej sekcji inicjalizujemy klienta Qiskit Serverless i ładujemy funkcję Singularity Machine Learning – Classification dostarczoną przez Multiverse Computing. Dzięki Qiskit Serverless możesz uruchamiać hybrydowe przepływy pracy kwantowo-klasyczne na zarządzanej infrastrukturze chmurowej IBM bez martwienia się o zarządzanie zasobami. Będziesz potrzebować klucza API IBM Quantum Platform oraz nazwy zasobu chmurowego (CRN), aby uwierzytelnić się i uzyskać dostęp do Qiskit Functions.
Pobierz zbiór danych
Aby uruchomić ten samouczek, używamy wstępnie przetworzonego zbioru danych do klasyfikacji stabilności sieci energetycznej zawierającego oznaczone odczyty czujników systemu energetycznego.
Poniższa komórka automatycznie tworzy wymaganą strukturę folderów i pobiera zarówno pliki treningowe, jak i testowe bezpośrednio do twojego środowiska przy użyciu wget.
Jeśli masz już te pliki lokalnie, ten krok bezpiecznie je nadpisze, aby zapewnić spójność wersji.
# 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
Importuj wymagane pakiety
W tej sekcji importujemy wszystkie pakiety Pythona i moduły Qiskit używane w całym samouczku.
Obejmują one podstawowe biblioteki naukowe do obsługi danych i ewaluacji modeli — takie jak NumPy, pandas i scikit-learn — wraz z narzędziami do wizualizacji i komponentami Qiskit do uruchamiania modelu z ulepszeniem kwantowym.
Importujemy również QiskitRuntimeService i QiskitFunctionsCatalog, aby połączyć się z usługami IBM Quantum® i uzyskać dostęp do funkcji 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")
Ustaw stałe zmienne
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"
Połącz się z IBM Quantum i załaduj funkcję Singularity
Następnie uwierzytelniamy się w usługach IBM Quantum i ładujemy funkcję Singularity Machine Learning – Classification z katalogu Qiskit Functions Catalog.
QiskitRuntimeService nawiązuje bezpieczne połączenie z platformą IBM Quantum Platform przy użyciu tokenu API i CRN instancji, umożliwiając dostęp do kwantowych backendów.
QiskitFunctionsCatalog jest następnie używany do pobierania funkcji Singularity po nazwie ("multiverse/singularity"), co pozwala nam ją później wywołać do hybrydowych obliczeń kwantowo-klasycznych.
Jeśli konfiguracja się powiedzie, zobaczysz komunikat potwierdzający, że funkcja została poprawnie załadowana.
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)
Zdefiniuj funkcje pomocnicze
Przed uruchomieniem głównych eksperymentów definiujemy kilka małych funkcji narzędziowych, które upraszczają ładowanie danych i ewaluację modeli.
load_data()wczytuje wejściowe pliki CSV do tablic NumPy, rozdzielając cechy i etykiety w celu zapewnienia kompatybilności z przepływami pracyscikit-learni kwantowymi.evaluate_predictions()oblicza kluczowe metryki wydajności — dokładność, precyzję, recall i wynik F1 — i opcjonalnie raportuje czas wykonania, jeśli dostarczone są informacje o czasie.
Te funkcje pomocnicze upraszczają powtarzające się operacje w dalszej części notebooka i zapewniają spójne raportowanie metryk zarówno dla klasycznych, jak i kwantowych klasyfikatorów.
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
Krok 1: Odwzoruj klasyczne dane wejściowe na problem kwantowy
Zaczynamy od przygotowania zbioru danych do hybrydowej eksperymentacji kwantowo-klasycznej. Celem tego kroku jest konwersja surowych danych o stabilności sieci na zbalansowane podziały treningowe, walidacyjne i testowe, które mogą być spójnie używane zarówno w klasycznych, jak i kwantowych przepływach pracy. Utrzymanie identycznych podziałów zapewnia, że późniejsze porównania wydajności są rzetelne i odtwarzalne.
Ładowanie i przetwarzanie danych
Najpierw ładujemy pliki CSV z danymi treningowymi i testowymi, tworzymy podział walidacyjny i balansujemy zbiór danych za pomocą losowego nadpróbkowania. Balansowanie zapobiega stronniczości w kierunku klasy większościowej i zapewnia bardziej stabilny sygnał uczenia zarówno dla klasycznych, jak i kwantowych modeli zespołowych.
# 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,)
Klasyczna linia bazowa: referencja AdaBoost
Przed uruchomieniem jakiejkolwiek optymalizacji kwantowej trenujemy silną klasyczną linię bazową — standardowy klasyfikator AdaBoost — na tych samych zbalansowanych danych. Zapewnia to odtwarzalny punkt odniesienia do późniejszych porównań, pomagając określić, czy optymalizacja kwantowa poprawia generalizację lub efektywność ponad dobrze skonfigurowany klasyczny zespół.
# ----- 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
Krok 2: Zoptymalizuj problem pod kątem wykonania na sprzęcie kwantowym
Zadanie wyboru zespołu jest sformułowane jako kombinatoryczny problem optymalizacji, w którym każdy słaby uczący jest binarną zmienną decyzyjną, a cel balansuje dokładność z rzadkością przez składnik regularyzacyjny. QuantumEnhancedEnsembleClassifier rozwiązuje to za pomocą QAOA na sprzęcie IBM, pozwalając jednocześnie na eksplorację opartą na symulatorze. optimizer_options kontrolują pętlę hybrydową: simulator=False kieruje obwody do wybranego QPU, num_solutions zwiększa szerokość przeszukiwania, a classical_optimizer_options (dla wewnętrznego klasycznego optymalizatora) sterują zbieżnością; wartości około 60 iteracji stanowią dobry kompromis między jakością a czasem wykonania. Opcje środowiska uruchomieniowego — takie jak umiarkowana głębokość obwodu (reps) i standardowy poziom transpilacji — pomagają zapewnić solidną wydajność na różnych urządzeniach. Poniższa konfiguracja to profil „najlepszych wyników", którego będziemy używać do uruchomień na sprzęcie; możesz również utworzyć czysto symulowaną wariant, przełączając simulator=True, aby przetestować przepływ pracy bez zużywania czasu 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
Krok 3: Wykonanie przy użyciu prymitywów Qiskit
Teraz wykonujemy pełny przepływ pracy, korzystając z akcji create_fit_predict funkcji Singularity, aby wytrenować, zoptymalizować i ocenić QuantumEnhancedEnsembleClassifier od początku do końca na infrastrukturze IBM. Funkcja buduje zespół, stosuje optymalizację kwantową za pomocą prymitywów Qiskit i zwraca zarówno predykcje, jak i metadane zadania (w tym czas wykonania i zużycie zasobów). Podział danych klasycznych z Kroku 1 jest ponownie wykorzystywany dla odtwarzalności, a dane walidacyjne są przekazywane przez fit_params, dzięki czemu optymalizacja może wewnętrznie dostrajać hiperparametry przy zachowaniu nietkniętego zestawu testowego.
W tym kroku badamy kilka konfiguracji kwantowego zespołu, aby zrozumieć, jak kluczowe parametry — konkretnie num_learners i regularization — wpływają zarówno na jakość wyników, jak i na wykorzystanie QPU.
num_learnersokreśla szerokość zespołu (i pośrednio liczbę qubitów), wpływając na pojemność modelu i koszt obliczeniowy.regularizationkontroluje rzadkość i nadmierne dopasowanie, kształtując liczbę uczących się, którzy pozostają aktywni po optymalizacji.
Zmieniając te parametry, możemy obserwować, jak szerokość zespołu i regularyzacja wzajemnie na siebie oddziałują: zwiększenie szerokości zazwyczaj poprawia F1, ale kosztuje więcej czasu QPU, natomiast silniejsza lub adaptacyjna regularyzacja może poprawić uogólnianie przy mniej więcej tym samym nakładzie sprzętowym. Kolejne podsekcje omawiają trzy reprezentatywne konfiguracje ilustrujące te efekty.
Wartość bazowa
Ta konfiguracja używa num_learners = 10 i regularization = 7.
num_learnerskontroluje szerokość zespołu — efektywnie liczbę słabych uczących się połączonych razem, a na sprzęcie kwantowym — liczbę wymaganych qubitów. Większa wartość rozszerza kombinatoryczną przestrzeń poszukiwań i może poprawić dokładność oraz czułość, ale jednocześnie zwiększa szerokość obwodu, czas kompilacji i ogólne zużycie QPU.regularizationustawia siłę kary za dołączenie dodatkowych uczących się. Przy domyślnej regularyzacji „onsite" wyższe wartości wymuszają silniejszą rzadkość (mniej zachowanych uczących się), natomiast niższe wartości pozwalają na bardziej złożone zespoły.
Ta konfiguracja stanowi tanią wartość bazową, pokazując zachowanie małego zespołu przed skalowaniem szerokości lub dostrajaniem rzadkości.
# 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
Zwiększenie liczby uczących się
Tutaj zwiększamy num_learners z 10 → 30, zachowując regularization = 7.
- Więcej uczących się rozszerza przestrzeń hipotez, pozwalając modelowi uchwycić bardziej subtelne wzorce, co może nieznacznie podnieść F1.
- W większości przypadków różnica w czasie wykonania między 10 a 30 uczącymi się nie jest znacząca, co wskazuje, że zwiększona szerokość obwodu nie podnosi istotnie kosztów wykonania.
- Poprawa jakości nadal podąża za krzywą malejących zwrotów: wczesne zyski pojawiają się wraz z rozrostem zespołu, ale plateau jest osiągane, gdy kolejni uczący się wnoszą coraz mniej nowych informacji.
Ten eksperyment uwydatnia kompromis między jakością a wydajnością — zwiększenie szerokości zespołu może oferować niewielkie wzrosty dokładności bez znacznej kary za czas wykonania, w zależności od Backend i warunków transpilacji.
# 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
Regularyzacja
W tej konfiguracji zwiększamy do num_learners = 60 i wprowadzamy adaptacyjną regularyzację, aby bardziej intuicyjnie zarządzać rzadkością.
- Przy
regularization = "auto"optymalizator automatycznie znajduje odpowiednią siłę regularyzacji, która wybiera mniej więcejregularization_ratio * num_learnerssłabych uczących się do końcowego zespołu, zamiast ręcznego ustalania kary. Zapewnia to wygodniejszy interfejs do zarządzania równowagą między rzadkością a rozmiarem zespołu. regularization_type = "alpha"definiuje sposób stosowania kary. W odróżnieniu odonsite, które jest nieograniczone[0, ∞],alphajest ograniczone do[0, 1], co ułatwia dostrajanie i interpretację. Parametr kontroluje kompromis między karami indywidualnymi a parami, oferując płynniejszy zakres konfiguracji.regularization_desired_ratio ≈ 0.82określa docelową proporcję uczących się, którzy mają pozostać aktywni po regularyzacji — tutaj zachowanych jest około 82% uczących się, a najsłabsze 18% jest automatycznie przycinanych.
Choć adaptacyjna regularyzacja upraszcza konfigurację i pomaga utrzymać zrównoważony zespół, niekoniecznie gwarantuje lepszą lub bardziej stabilną wydajność. Rzeczywista jakość zależy od wyboru odpowiedniego parametru regularyzacji, a jego dostrajanie przez walidację krzyżową może być kosztowne obliczeniowo. Główna zaleta leży w poprawie użyteczności i interpretowalności, a nie bezpośrednich wzrostach dokładności.
# 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
Krok 4: Post-przetwarzanie i zwrócenie wyników w pożądanym formacie klasycznym
Teraz przetwarzamy wyniki zarówno z przebiegu klasycznego, jak i kwantowego, konwertując je do spójnego formatu dla dalszej oceny. Ten krok porównuje jakość predykcji przy użyciu standardowych metryk — dokładności, precyzji, czułości i F1 — oraz analizuje, jak szerokość zespołu (num_learners) i kontrola rzadkości (regularization) wpływają zarówno na wydajność, jak i na zachowanie obliczeniowe.
Klasyczna wartość bazowa AdaBoost stanowi zwartą i stabilną referencję dla uczenia na małą skalę. Działa dobrze przy ograniczonych zespołach przy zaniedbywalnym koszcie obliczeniowym, odzwierciedlając siłę tradycyjnego boostingu, gdy przestrzeń hipotez jest jeszcze wykonalna. Konfiguracje kwantowe (qeec_pred_job_1, qeec_pred_job_2 i qeec_pred_job_3) rozszerzają tę wartość bazową, osadzając proces wyboru zespołu w wariacyjnej kwantowej pętli optymalizacyjnej. Pozwala to systemowi eksplorować wykładniczo duże podzbiory uczących się jednocześnie w superpozycji, bardziej wydajnie adresując kombinatoryczną naturę wyboru zespołu w miarę wzrostu skali.
Wyniki pokazują, że zwiększenie num_learners z 10 do 30 poprawia czułość i F1, potwierdzając, że szerszy zespół uchwytuje bogatsze interakcje między słabymi uczącymi się. Zysk jest podliniowy na obecnym sprzęcie — każdy dodatkowy uczący się przynosi mniejsze przyrosty dokładności — ale leżące u podstaw zachowanie skalowania pozostaje korzystne, ponieważ optymalizator kwantowy może przeszukiwać szersze przestrzenie konfiguracji bez wykładniczego wzrostu typowego dla klasycznego wyboru podzbiorów. Regularyzacja wprowadza dodatkowe niuanse: stałe λ=7 wymusza spójną rzadkość i stabilizuje konwergencję, natomiast adaptacyjna α-regularyzacja automatycznie dostosowuje rzadkość na podstawie korelacji między uczącymi się. To dynamiczne przycinanie często osiąga nieznacznie wyższe F1 przy tej samej szerokości qubitowej, równoważąc złożoność modelu i uogólnianie.
W bezpośrednim porównaniu z wartością bazową AdaBoost, najmniejsza konfiguracja kwantowa (L=10) odtwarza podobną dokładność, potwierdzając poprawność hybrydowego potoku. Przy większych szerokościach warianty kwantowe — zwłaszcza z automatyczną regularyzacją — zaczynają nieznacznie przewyższać klasyczną wartość bazową, wykazując poprawioną czułość i F1 bez liniowego wzrostu kosztu obliczeniowego. Te ulepszenia nie wskazują na natychmiastową „przewagę kwantową", lecz raczej na wydajność skalowania: optymalizator kwantowy utrzymuje wykonalną wydajność w miarę rozrastania się zespołu, podczas gdy podejście klasyczne napotykałoby wykładniczy wzrost złożoności wyboru podzbiorów.
W praktyce:
- Używaj klasycznej wartości bazowej do szybkiej walidacji i benchmarkingu na małych zbiorach danych.
- Stosuj kwantowe zespoły, gdy szerokość modelu lub złożoność cech rośnie — wyszukiwanie oparte na QAOA skaluje się łagodniej w tych reżimach.
- Używaj adaptacyjnej α-regularyzacji, aby utrzymać rzadkość i uogólnianie bez zwiększania szerokości obwodu.
- Monitoruj czas QPU i głębokość, aby zrównoważyć wzrosty jakości z ograniczeniami sprzętu bliskiej perspektywy.
Razem te eksperymenty pokazują, że kwantowo-zoptymalizowane zespoły uzupełniają metody klasyczne: odtwarzają dokładność bazową na małych skalach, oferując jednocześnie ścieżkę do wydajnego skalowania na większych, kombinatorycznych problemach uczenia. W miarę poprawy sprzętu oczekuje się, że te zalety skalowania będą się kumulować, rozszerzając wykonalny rozmiar i głębokość modeli opartych na zespołach poza to, co jest klasycznie praktyczne.
Ocena metryk dla każdej konfiguracji
Teraz oceniamy wszystkie konfiguracje — klasyczną wartość bazową AdaBoost i trzy kwantowe zespoły — używając pomocnika evaluate_predictions do obliczenia dokładności, precyzji, czułości i F1 na tym samym zestawie testowym. To porównanie wyjaśnia, jak optymalizacja kwantowa skaluje się względem podejścia klasycznego: przy małych szerokościach oba działają podobnie; w miarę wzrostu zespołów metoda kwantowa może bardziej wydajnie eksplorować większe przestrzenie hipotez. Wynikowa tabela ujmuje te tendencje w spójnej, ilościowej formie.
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
Wizualizacja trendów jakości w różnych konfiguracjach
Grupowany wykres słupkowy poniżej porównuje dokładność i F1 w klasycznej wartości bazowej i kwantowych zespołach (L=10, L=30 i L=60 auto-α). Ilustruje, jak dokładność stabilizuje się, podczas gdy F1 stopniowo poprawia się wraz ze wzrostem szerokości kwantowego zespołu, demonstrując, że metoda hybrydowa utrzymuje skalowanie wydajności bez wykładniczego wzrostu kosztów typowego dla klasycznego wyboru podzbiorów.
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()
Interpretacja
Wykres potwierdza oczekiwany wzorzec skalowania. Klasyczny AdaBoost działa mocno dla mniejszych zespołów, ale jego skalowanie staje się coraz kosztowniejsze wraz ze wzrostem liczby słabych uczących się, ponieważ problem wyboru podzbiorów rozrasta się kombinatorycznie. Kwantowo-ulepszone modele odtwarzają klasyczną dokładność przy niskich szerokościach i zaczynają ją przewyższać w miarę wzrostu rozmiaru zespołu, zwłaszcza pod adaptacyjną α-regularyzacją. Odzwierciedla to zdolność optymalizatora kwantowego do próbkowania i oceniania wielu kandydujących podzbiorów równolegle przez superpozycję, utrzymując wykonalne przeszukiwanie nawet przy wyższych szerokościach. Choć obecne narzuty sprzętowe kompensują część teoretycznych zysków, tendencja ilustruje zalety wydajności skalowania kwantowej formuły. W praktyce metoda klasyczna pozostaje preferowana dla lekkich benchmarków, natomiast kwantowo-ulepszone zespoły stają się korzystne w miarę wzrostu wymiarowości modelu i rozmiaru zespołu, oferując lepsze kompromisy między dokładnością, uogólnianiem i wzrostem obliczeniowym.
Dodatek: Zalety skalowania i ulepszenia
Zalety skalowalności QuantumEnhancedEnsembleClassifier wynikają ze sposobu, w jaki proces wyboru zespołu mapuje się na optymalizację kwantową.
Klasyczne metody uczenia zespołowego, takie jak AdaBoost czy lasy losowe, stają się kosztowne obliczeniowo wraz ze wzrostem liczby słabych uczących się, ponieważ wybranie optymalnego podzbioru jest problemem kombinatorycznym, który skaluje się wykładniczo.
W przeciwieństwie do tego, kwantowa formuła — zaimplementowana tutaj za pomocą Quantum Approximate Optimization Algorithm (QAOA) — może bardziej wydajnie eksplorować te wykładniczo duże przestrzenie poszukiwań, oceniając wiele konfiguracji w superpozycji. W rezultacie czas trenowania nie rośnie znacząco wraz z liczbą uczących się, co pozwala modelowi pozostać wydajnym nawet w miarę zwiększania szerokości zespołu.
Choć obecny sprzęt wprowadza pewien szum i ograniczenia głębokości, ten przepływ pracy demonstruje hybrydowe podejście bliskiej perspektywy, gdzie komponenty klasyczne i kwantowe współpracują: optymalizator kwantowy zapewnia lepszy krajobraz inicjalizacji dla klasycznej pętli, poprawiając konwergencję i końcową jakość modelu. W miarę ewolucji procesorów kwantowych oczekuje się, że te zalety skalowalności rozciągną się na większe zbiory danych, szersze zespoły i głębsze głębokości obwodów.
Materiały źródłowe
Ankieta dotycząca samouczka
Poświęć chwilę na przekazanie opinii na temat tego samouczka. Twoje spostrzeżenia pomogą nam ulepszyć ofertę treści i doświadczenie użytkownika.
Note: This survey is provided by IBM Quantum and relates to the original English content. To give feedback on doQumentation's website, translations, or code execution, please open a GitHub issue.