Skip to main content
IBM Quantum Platform

Classificazione ibrida potenziata dal quantum (flusso di lavoro sulla stabilità della rete)

Stima di utilizzo: 20 minuti di tempo QPU per ogni lavoro su un processore Eagle r3. (NOTA: questa è solo una stima. Il tempo di esecuzione può variare)


Sfondo

Questo tutorial illustra un flusso di lavoro ibrido quantistico-classico che potenzia un insieme classico con una fase di ottimizzazione quantistica. Utilizzando la funzione "Singularity Machine Learning –Classification" di Multiverse Computing (una funzione di Qiskit), addestriamo un insieme di modelli di apprendimento convenzionali (ad esempio, alberi decisionali, k-NN, regressione logistica) e poi perfezioniamo tale insieme con un livello quantistico per migliorare la diversità e la generalizzazione. L'obiettivo è di natura pratica: in un vero e proprio compito di previsione della stabilità della rete, mettiamo a confronto un solido modello di riferimento classico con un'alternativa ottimizzata quantisticamente, utilizzando le stesse suddivisioni dei dati, in modo da poter vedere in quali ambiti l'approccio quantistico offre un vantaggio e quali sono i relativi costi.

Perché questo è importante: la selezione di un buon sottoinsieme tra molti apprendenti deboli è un problema combinatorio che cresce rapidamente con le dimensioni dell'ensemble. Le euristiche classiche come il boosting, il bagging e lo stacking funzionano bene su scale moderate, ma possono faticare a esplorare in modo efficiente librerie di modelli grandi e ridondanti. La funzione integra algoritmi quantistici - in particolare QAOA (e opzionalmente VQE in altre configurazioni) - per cercare in modo più efficace in questo spazio dopo l'addestramento degli apprendenti classici, aumentando la possibilità di trovare un sottoinsieme compatto e diversificato che generalizzi meglio.

La scala dei dati non è limitata dai qubit. Il lavoro pesante sui dati - preelaborazione, formazione del pool di discenti e valutazione - rimane classico e può gestire milioni di esempi. I Qubit determinano solo la dimensione dell'ensemble utilizzato nella fase di selezione quantistica. Questo disaccoppiamento è ciò che rende l'approccio praticabile sull'hardware odierno: si mantengono i familiari flussi di lavoro di scikit-learn per l'addestramento dei dati e dei modelli, mentre si richiama la fase quantistica attraverso un'interfaccia di azione pulita in Qiskit Functions.

In pratica, sebbene all'ensemble possano essere forniti diversi tipi di learner (ad esempio, alberi decisionali, regressione logistica o k-NN), gli alberi decisionali tendono a dare le migliori prestazioni. L'ottimizzatore favorisce costantemente i membri più forti dell'ensemble: quando vengono forniti learners eterogenei, i modelli più deboli, come i regressori lineari, vengono tipicamente eliminati a favore di quelli più espressivi, come gli alberi decisionali.

Cosa farete qui: preparate e bilanciate il dataset della stabilità della griglia; stabilite una linea di base classica AdaBoost; eseguite diverse configurazioni quantistiche che variano l'ampiezza dell'ensemble e la regolarizzazione; eseguite sui simulatori IBM® o sulle QPU tramite Qiskit Serverless; e confrontate l'accuratezza, la precisione, il richiamo e F1 tra tutte le esecuzioni. Durante il percorso, si utilizzerà lo schema di azione della funzione (create, fit, predict, fit_predict, create_fit_predict) e i controlli dei tasti:

  • Tipi di regolarizzazione: onsite (λ) per una sparsità diretta e alpha per un trade-off basato sul rapporto tra termini di interazione e termini in loco
  • Auto-regolarizzazione: impostare regularization="auto" con un rapporto di selezione target per adattare automaticamente la spaziosità
  • Opzioni dell'ottimizzatore: simulatore o QPU, ripetizioni, ottimizzatore classico e relative opzioni, profondità di transpilazione e impostazioni del campionatore o dello stimatore IBM Quantum

I benchmark riportati nella documentazione mostrano che l'accuratezza migliora con l'aumentare del numero di apprendenti (qubit) su problemi impegnativi, con il classificatore quantistico che eguaglia o supera un ensemble classico comparabile. In questa esercitazione, si riprodurrà il flusso di lavoro end-to-end e si esaminerà quando l'aumento dell'ampiezza dell'ensemble o il passaggio alla regolarizzazione adattiva produce un migliore F1 con un utilizzo ragionevole delle risorse. Il risultato è una visione fondata di come una fase di ottimizzazione quantistica possa integrare, piuttosto che sostituire, l'apprendimento classico in ensemble nelle applicazioni reali.


Requisiti

Prima di iniziare questa esercitazione, assicurarsi di avere installato i seguenti pacchetti nell'ambiente 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

Configura

In questa sezione, inizializziamo il client Qiskit Serverless e carichiamo la funzione Singularity Machine Learning - Classificazione fornita da Multiverse Computing. Con Qiskit Serverless è possibile eseguire flussi di lavoro ibridi quantistico-classici sull'infrastruttura cloud gestita da IBM senza preoccuparsi della gestione delle risorse. Per autenticarsi e accedere a Qiskit Functions sono necessari una chiave API IBM Quantum Platform e il nome della risorsa cloud (CRN).

Scarica il set di dati

Per eseguire questo tutorial, utilizziamo un set di dati di classificazione della stabilità della rete preelaborato contenente letture dei sensori del sistema di alimentazione etichettate. La cella seguente crea automaticamente la struttura di cartelle richiesta e scarica i file di addestramento e di prova direttamente nell'ambiente utilizzando wget. Se questi file sono già presenti in locale, questo passaggio li sovrascrive in modo sicuro per garantire la coerenza della versione.

## 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
base_url = (
    "https://raw.githubusercontent.com/Qiskit/documentation/"
    "main/datasets/tutorials/grid_stability"
)
!wget -q --show-progress -O data_tutorial/grid_stability/train.csv {base_url}/train.csv

!wget -q --show-progress -O data_tutorial/grid_stability/test.csv {base_url}/test.csv

# Check the files have been downloaded
!echo "Dataset files downloaded:"
!ls -lh data_tutorial/grid_stability/*.csv

Output:

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

Importa i pacchetti richiesti

In questa sezione vengono importati tutti i pacchetti Python e i moduli Qiskit utilizzati nel corso dell'esercitazione. Queste includono librerie scientifiche di base per la gestione dei dati e la valutazione del modello, come NumPy, pandas e scikit-learn , oltre a strumenti di visualizzazione e componenti Qiskit per l'esecuzione del modello quantistico. Importiamo anche QiskitRuntimeService e QiskitFunctionsCatalog per connetterci ai servizi IBM Quantum® e accedere alla funzione Singularity Machine Learning.

from pprint import pprint
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 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")

Imposta variabili costanti

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"

Connettiti a IBM Quantum e carica la funzione Singularity

Successivamente, ci si autentica con i servizi di IBM Quantum e si carica la funzione Singularity Machine Learning - Classificazione da Qiskit Functions Catalog. QiskitRuntimeService stabilisce una connessione sicura a IBM Quantum Platform utilizzando il token API e il CRN dell'istanza, consentendo l'accesso ai backend quantistici. Il sito QiskitFunctionsCatalog viene quindi utilizzato per recuperare la funzione Singolarità per nome ("multiverse/singularity"), consentendoci di richiamarla in seguito per il calcolo ibrido quantistico-classico. Se l'impostazione riesce, viene visualizzato un messaggio di conferma che indica che la funzione è stata caricata correttamente.

catalog = QiskitFunctionsCatalog(
    token=IBM_TOKEN,
    instance=IBM_INSTANCE_TEST,
    channel="ibm_quantum_platform",
)
backend = catalog.least_busy()

singularity = catalog.load(FUNCTION_NAME)
print(
    "Successfully connected to IBM Qiskit Serverless and "
    "loaded the Singularity function."
)
print("Catalog:", catalog)
print("Singularity function:", singularity)

Output:

Successfully connected to IBM Qiskit Serverless and loaded the Singularity function.
Catalog: <QiskitFunctionsCatalog>
Singularity function: QiskitFunction(multiverse/singularity)

Definire le funzioni di supporto

Prima di eseguire gli esperimenti principali, definiamo alcune piccole funzioni di utilità che semplificano il caricamento dei dati e la valutazione dei modelli.

  • load_data() legge i file CSV di input in array NumPy, dividendo le caratteristiche e le etichette per la compatibilità con scikit-learn e i flussi di lavoro quantistici.
  • evaluate_predictions() calcola le principali metriche di prestazione - accuratezza, precisione, richiamo e F1-score - e opzionalmente riporta il tempo di esecuzione se vengono fornite le informazioni sulla tempistica.

Queste funzioni ausiliarie semplificano le operazioni ripetute in seguito nel blocco note e assicurano una reportistica metrica coerente tra i classificatori classici e quelli quantistici.

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

Fase 1: mappare gli input classici su un problema quantistico

Iniziamo preparando il set di dati per la sperimentazione ibrida quantistica-classica. L'obiettivo di questa fase è quello di convertire i dati grezzi sulla stabilità della griglia in suddivisioni bilanciate per l'addestramento, la convalida e il test che possano essere utilizzate in modo coerente dai flussi di lavoro classici e quantistici. Il mantenimento di split identici garantisce che i confronti successivi delle prestazioni siano equi e riproducibili.

Caricamento e pre-elaborazione dei dati

Per prima cosa carichiamo i file CSV di allenamento e di test, creiamo una suddivisione di convalida e bilanciamo il set di dati utilizzando un sovracampionamento casuale. Il bilanciamento impedisce la polarizzazione verso la classe maggioritaria e fornisce un segnale di apprendimento più stabile per i modelli di ensemble sia classici che quantistici.

# 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)

Output:

Shapes:
  X_train_bal: (5104, 12)
  y_train_bal: (5104,)
  X_val: (850, 12)
  y_val: (850,)
  X_test: (750, 12)
  y_test: (750,)

Riferimento classico: AdaBoost

Prima di eseguire qualsiasi ottimizzazione quantistica, addestriamo una linea di base classica forte - un classificatore standard AdaBoost - sugli stessi dati bilanciati. Questo fornisce un punto di riferimento riproducibile per un successivo confronto, aiutando a quantificare se l'ottimizzazione quantistica migliora la generalizzazione o l'efficienza al di là di un insieme classico ben sintonizzato.

# ----- 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)

Output:

Classical AdaBoost baseline:
Accuracy: 0.7893333333333333
Precision: 1.0
Recall: 0.7893333333333333
F1: 0.8822652757078987

Fase 2: Ottimizzazione del problema per l'esecuzione su hardware quantistico

Il compito di selezione dell’insieme viene formulato come un problema di ottimizzazione combinatoria in cui ogni modello di apprendimento debole rappresenta una variabile decisionale binaria, e l’obiettivo bilancia l’accuratezza con la sparsità attraverso un termine di regolarizzazione. Il sistema risolve QuantumEnhancedEnsembleClassifier questo problema utilizzando il QAOA su hardware di tipo " IBM ", pur consentendo al contempo l'esplorazione tramite simulatore. Il controllo optimizer_options del ciclo ibrido: simulator=False indirizza i circuiti verso la QPU selezionata, num_solutions aumenta l'ampiezza di ricerca e ( classical_optimizer_options per l'ottimizzatore classico interno) regola la convergenza; valori intorno alle 60 iterazioni rappresentano un buon compromesso tra qualità e tempo di esecuzione. Le opzioni di Quantum Compute — quali una profondità dei circuiti moderata (reps) e uno sforzo di transpilazione standard — contribuiscono a garantire prestazioni affidabili su tutti i dispositivi. La configurazione riportata di seguito è il profilo "best-results" che utilizzeremo per le esecuzioni su hardware; è inoltre possibile creare una variante puramente simulata attivando l'opzione simulator=True per eseguire il flusso di lavoro in modalità dry-run senza consumare tempo di 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}")

Output:

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

Passaggio 3: eseguire utilizzando Qiskit primitives

Ora eseguiamo il flusso di lavoro completo utilizzando l'azione create_fit_predict della funzione Singularity per addestrare, ottimizzare e valutare QuantumEnhancedEnsembleClassifier end-to-end sull'infrastruttura IBM. La funzione costruisce l'ensemble, applica l'ottimizzazione quantistica attraverso Qiskit primitives e restituisce sia le previsioni sia i metadati del lavoro (compresi i tempi di esecuzione e l'utilizzo delle risorse). Per la riproducibilità, viene riutilizzata la classica suddivisione dei dati della fase 1, con i dati di validazione passati attraverso fit_params , in modo che l'ottimizzazione possa sintonizzare internamente gli iperparametri, mantenendo inalterato il set di test.

In questa fase, esploriamo diverse configurazioni dell'ensemble quantistico per capire come i parametri chiave - in particolare num_learners e regularization - influenzino la qualità dei risultati e l'utilizzo della QPU.

  • num_learners determina l'ampiezza dell'insieme (e implicitamente il numero di qubit), influenzando la capacità del modello e il costo computazionale.
  • regularization controlla la sparsità e l'overfitting, definendo il numero di apprendenti che rimangono attivi dopo l'ottimizzazione.

Variando questi parametri, possiamo vedere come interagiscono l'ampiezza dell'ensemble e la regolarizzazione: l'aumento dell'ampiezza migliora tipicamente F1 ma costa più tempo alla QPU, mentre una regolarizzazione più forte o adattiva può migliorare la generalizzazione a circa lo stesso ingombro hardware. Le prossime sottosezioni illustrano tre configurazioni rappresentative per illustrare questi effetti.

Informazioni di base

Questa configurazione utilizza num_learners = 10 e regularization = 7.

  • num_learners controlla l'ampiezza dell'ensemble, ovvero il numero di weak learners combinati e, nell'hardware quantistico, il numero di qubit necessari. Un valore maggiore espande lo spazio di ricerca combinatoria e può migliorare l'accuratezza e il richiamo, ma aumenta anche la larghezza del circuito, il tempo di compilazione e l'utilizzo complessivo della QPU.
  • regularization imposta la forza di penalizzazione per l'inclusione di altri apprendenti. Con la regolarizzazione predefinita "onsite", i valori più alti impongono una maggiore sparsità (vengono mantenuti meno apprendenti), mentre i valori più bassi consentono ensemble più complessi.

Questa configurazione fornisce una linea di base a basso costo, mostrando come si comporta un piccolo ensemble prima di scalare l'ampiezza o regolare la spaziosità.

# 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:")
pprint(result_1.get("metadata"))
qeec_pred_job_1 = np.array(result_1["data"]["predictions"])
_ = evaluate_predictions(qeec_pred_job_1, y_test)

Output:


-- Submitting quantum-enhanced ensemble job --
Action status: ok
Action message: Classifier created, fitted, and predicted.
Metadata:
{'resource_usage': {'RUNNING: EXECUTING_QPU': {'QPU_TIME': 1550.1889700889587},
                    'RUNNING: MAPPING': {'CPU_TIME': 267.05158376693726},
                    'RUNNING: POST_PROCESSING': {'CPU_TIME': 152.4274561405182},
                    'RUNNING: WAITING_QPU': {'CPU_TIME': 3336.8785166740417}}}
Accuracy: 0.868
Precision: 1.0
Recall: 0.868
F1: 0.9293361884368309
status_1 = job_1.status()
print("\nQuantum job status:", status_1)

Output:


Quantum job status: DONE

Aumentare il numero di studenti

Qui aumentiamo num_learners da 10 → 30 mantenendo regularization = 7.

  • Un maggior numero di apprendisti espande lo spazio delle ipotesi, consentendo al modello di catturare modelli più sottili, che possono aumentare in modo modesto F1.
  • Nella maggior parte dei casi, la differenza di tempo di esecuzione tra 10 e 30 discenti non è sostanziale, il che indica che la larghezza del circuito aggiunto non aumenta significativamente il costo di esecuzione.
  • Il miglioramento della qualità segue ancora una curva di rendimento decrescente : i primi guadagni appaiono quando l'ensemble cresce, ma si stabilizzano quando gli apprendenti aggiuntivi apportano meno nuove informazioni.

Questo esperimento mette in evidenza il compromesso qualità-efficienza: l'aumento dell'ampiezza dell'ensemble può offrire piccoli guadagni di accuratezza senza una forte penalizzazione dei tempi di esecuzione, a seconda delle condizioni del backend e della trasposizione.

# 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:")
pprint(result_2.get("metadata"))
qeec_pred_job_2 = np.array(result_2["data"]["predictions"])
_ = evaluate_predictions(qeec_pred_job_2, y_test)

Output:


-- Submitting quantum-enhanced ensemble job --
Action status: ok
Action message: Classifier created, fitted, and predicted.
QPU Time:
{'resource_usage': {'RUNNING: EXECUTING_QPU': {'QPU_TIME': 1095.822762966156},
                    'RUNNING: MAPPING': {'CPU_TIME': 680.2116754055023},
                    'RUNNING: POST_PROCESSING': {'CPU_TIME': 154.4466371536255},
                    'RUNNING: WAITING_QPU': {'CPU_TIME': 80.80395102500916}}}
Accuracy: 0.8946666666666667
Precision: 1.0
Recall: 0.8946666666666667
F1: 0.944405348346235
status_2 = job_2.status()
print("\nQuantum job status:", status_2)

Output:


Quantum job status: DONE

Regolarizzazione

In questa configurazione, aumentiamo a num_learners = 60 e introduciamo una regolarizzazione adattiva per gestire la sparsità in modo più intuitivo.

  • Con regularization = "auto", l'ottimizzatore trova automaticamente un'adeguata forza di regolarizzazione che seleziona approssimativamente regularization_ratio * num_learners gli apprendenti deboli per l'ensemble finale, piuttosto che fissare manualmente la penalità. In questo modo si ottiene un'interfaccia più comoda per gestire l'equilibrio tra sparsità e dimensione dell'ensemble.
  • regularization_type = "alpha" definisce il modo in cui viene applicata la penalità. A differenza di onsite, che non è vincolato [0, ∞], alpha è vincolato tra [0, 1], il che lo rende più facile da sintonizzare e interpretare. Il parametro controlla il compromesso tra le penalità individuali e quelle di coppia, offrendo una gamma di configurazione più omogenea.
  • regularization_desired_ratio ≈ 0.82 specifica la percentuale target di apprendenti da mantenere attivi dopo la regolarizzazione - in questo caso, circa l'82% degli apprendenti viene mantenuto, tagliando automaticamente il 18% più debole.

Sebbene la regolarizzazione adattiva semplifichi la configurazione e aiuti a mantenere un insieme equilibrato, non garantisce necessariamente prestazioni migliori o più stabili. La qualità effettiva dipende dalla selezione di un parametro di regolarizzazione appropriato, la cui messa a punto attraverso la convalida incrociata può essere computazionalmente costosa. Il vantaggio principale risiede nel miglioramento dell'usabilità e dell'interpretabilità piuttosto che nell'aumento diretto dell'accuratezza.

# 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:")
pprint(result_3.get("metadata"))
qeec_pred_job_3 = np.array(result_3["data"]["predictions"])
_ = evaluate_predictions(qeec_pred_job_3, y_test)

Output:


-- Submitting quantum-enhanced ensemble job --
Action status: ok
Action message: Classifier created, fitted, and predicted.
Metadata:
{'resource_usage': {'RUNNING: EXECUTING_QPU': {'QPU_TIME': 1146.5584812164307},
                    'RUNNING: MAPPING': {'CPU_TIME': 1387.7451872825623},
                    'RUNNING: POST_PROCESSING': {'CPU_TIME': 171.78878355026245},
                    'RUNNING: WAITING_QPU': {'CPU_TIME': 95.41597843170166}}}
Accuracy: 0.908
Precision: 1.0
Recall: 0.908
F1: 0.9517819706498952
status_3 = job_3.status()
print("\nQuantum job status:", status_3)

Output:


Quantum job status: DONE

Fase 4: Post-elaborazione e restituzione del risultato nel formato classico desiderato

Ora elaboriamo i risultati delle esecuzioni classiche e quantistiche, convertendoli in un formato coerente per la valutazione a valle. Questa fase confronta la qualità predittiva utilizzando metriche standard - accuratezza, precisione, richiamo e F1 - e analizza come l'ampiezza dell'ensemble (num_learners) e il controllo della sparsità (regularization) influenzino le prestazioni e il comportamento computazionale.

La linea di base classica di AdaBoost fornisce un riferimento compatto e stabile per l'apprendimento su piccola scala. Si comporta bene con ensemble limitati e con un overhead di calcolo trascurabile, riflettendo la forza del boosting tradizionale quando lo spazio delle ipotesi è ancora trattabile. Le configurazioni quantistiche (qeec_pred_job_1, qeec_pred_job_2 e qeec_pred_job_3) estendono questa linea di base incorporando il processo di selezione dell'insieme in un ciclo di ottimizzazione quantistica variazionale. Ciò consente al sistema di esplorare simultaneamente sottoinsiemi di apprendenti di dimensioni esponenziali in sovrapposizione, affrontando la natura combinatoria della selezione d'insieme in modo più efficiente all'aumentare della scala.

I risultati mostrano che l'aumento di num_learners da 10 a 30 migliora il richiamo e F1, confermando che un ensemble più ampio cattura interazioni più ricche tra gli apprendenti deboli. Il guadagno è sublineare sull'hardware attuale - ogni discente aggiuntivo produce incrementi di precisione minori - ma il comportamento di scala sottostante rimane favorevole perché l'ottimizzatore quantistico può cercare in spazi di configurazione più ampi senza l'esplosione esponenziale tipica della selezione classica dei sottoinsiemi. La regolarizzazione introduce ulteriori sfumature: un valore fisso di λ=7 impone una sparsità coerente e stabilizza la convergenza, mentre la regolarizzazione adattiva α regola automaticamente la sparsità in base alle correlazioni tra gli apprendenti. Questa potatura dinamica spesso consente di ottenere un F1 leggermente più alto per la stessa larghezza di qubit, bilanciando la complessità del modello e la generalizzazione.

Se confrontata direttamente con la linea di base AdaBoost, la configurazione quantistica più piccola ( L=10 ) riproduce un'accuratezza simile, convalidando la correttezza della pipeline ibrida. A larghezze maggiori, le varianti quantistiche - soprattutto con l'auto-regolarizzazione - iniziano a superare modestamente la linea di base classica, mostrando un miglioramento del richiamo e di F1 senza una crescita lineare del costo computazionale. Questi miglioramenti non indicano un "vantaggio quantistico" immediato, ma piuttosto un' efficienza di scala : l'ottimizzatore quantistico mantiene prestazioni accettabili man mano che l'insieme si espande, laddove un approccio classico affronterebbe una crescita esponenziale della complessità di selezione dei sottoinsiemi.

In pratica:

  • Utilizzare la linea di base classica per una rapida convalida e un benchmarking su piccoli insiemi di dati.
  • Applicare gli ensemble quantistici quando l'ampiezza del modello o la complessità delle caratteristiche crescono. La ricerca basata su QAOA si adatta meglio a questi regimi.
  • Impiegare la regolarizzazione α adattiva per mantenere la sparsità e la generalizzazione senza aumentare la larghezza del circuito.
  • Monitorare il tempo e la profondità della QPU per bilanciare i guadagni di qualità con i vincoli hardware a breve termine.

Insieme, questi esperimenti dimostrano che gli insiemi ottimizzati a livello quantistico sono complementari ai metodi classici: riproducono l'accuratezza di base su piccole scale, offrendo al contempo un percorso di scalabilità efficiente su problemi di apprendimento combinatorio di dimensioni maggiori. Con il miglioramento dell'hardware, si prevede che questi vantaggi di scala aumenteranno, estendendo le dimensioni e la profondità dei modelli basati su ensemble al di là di ciò che è classicamente pratico.

Valutare le metriche per ciascuna configurazione

Valutiamo ora tutte le configurazioni - la linea di base classica AdaBoost e i tre insiemi quantistici - utilizzando l'helper evaluate_predictions per calcolare accuratezza, precisione, richiamo e F1 sullo stesso set di test. Questo confronto chiarisce come l'ottimizzazione quantistica scala rispetto all'approccio classico: a piccole ampiezze, entrambi hanno prestazioni simili; quando gli insiemi crescono, il metodo quantistico può esplorare spazi di ipotesi più ampi in modo più efficiente. La tabella risultante cattura queste tendenze in una forma quantitativa e coerente.

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

Output:

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
, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,0AdaBoost (Classical)0.7893331.00.7893330.8822651QEEC L=10, reg=70.8680001.00.8680000.9293362QEEC L=30, reg=70.8946671.00.8946670.9444053QEEC L=60, reg=auto (α=0.82)0.9080001.00.9080000.951782 ,

Visualizza le tendenze di qualità nelle diverse configurazioni

Il grafico a barre raggruppato qui sotto mette a confronto l' accuratezza e la F1 tra la linea di base classica e gli ensemble quantistici (L=10, L=30 e L=60 auto-α). Illustra come l'accuratezza si stabilizzi mentre F1 migliora gradualmente all'aumentare dell'ampiezza dell'insieme quantistico, dimostrando che il metodo ibrido sostiene la scalabilità delle prestazioni senza la crescita esponenziale dei costi tipica della selezione classica dei sottoinsiemi.

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:

Output of the previous code cell

Interpretazione

Il grafico conferma l'andamento scalare previsto. Il metodo classico di AdaBoost ha prestazioni elevate per gli insiemi più piccoli, ma diventa sempre più costoso da scalare all'aumentare del numero di weak learners, perché il problema della selezione dei sottoinsiemi si espande in modo combinatorio. I modelli potenziati dal punto di vista quantistico replicano l'accuratezza classica a basse larghezze e iniziano a superarla con l'aumentare delle dimensioni dell'ensemble, soprattutto con la regolarizzazione α adattiva. Ciò riflette la capacità dell'ottimizzatore quantistico di campionare e valutare molti sottoinsiemi candidati in parallelo attraverso la sovrapposizione, mantenendo la ricerca praticabile anche a larghezze maggiori. Sebbene l'attuale overhead dell'hardware compensi alcuni dei guadagni teorici, la tendenza illustra il vantaggio dell'efficienza di scala della formulazione quantistica. In termini pratici, il metodo classico rimane preferibile per i benchmark leggeri, mentre gli ensemble quantistici diventano vantaggiosi quando la dimensionalità del modello e la dimensione dell'ensemble si espandono, offrendo un migliore compromesso tra accuratezza, generalizzazione e crescita computazionale.


Appendice: Vantaggi e miglioramenti della scalabilità

Il vantaggio in termini di scalabilità di QuantumEnhancedEnsembleClassifier deriva dal modo in cui il processo di selezione degli ensemble si adatta all'ottimizzazione quantistica. I metodi classici di apprendimento in ensemble, come AdaBoost o le foreste casuali, diventano computazionalmente costosi all'aumentare del numero di weak learners, perché la selezione del sottoinsieme ottimale è un problema combinatorio che scala in modo esponenziale.

Al contrario, la formulazione quantistica - qui implementata tramite il Quantum Approximate Optimization Algorithm (QAOA) - può esplorare questi spazi di ricerca di dimensioni esponenziali in modo più efficiente, valutando più configurazioni in sovrapposizione. Di conseguenza, il tempo di addestramento non cresce significativamente con il numero di apprendenti, consentendo al modello di rimanere efficiente anche quando l'ampiezza dell'ensemble aumenta.

Sebbene l'hardware attuale introduca alcune limitazioni in termini di rumore e profondità, questo flusso di lavoro dimostra un approccio ibrido a breve termine in cui le componenti classiche e quantistiche cooperano: l'ottimizzatore quantistico fornisce un paesaggio di inizializzazione migliore per il ciclo classico, migliorando la convergenza e la qualità del modello finale. Con l'evoluzione dei processori quantistici, si prevede che questi vantaggi di scalabilità si estenderanno a insiemi di dati più grandi, a ensemble più ampi e a profondità di circuito maggiori.


Riferimenti

  1. Introduzione a Qiskit Functions
  2. Singolarità informatica del multiverso Machine Learning

Sondaggio tutorial

Dedicate un minuto a fornire un feedback su questa esercitazione. Le vostre indicazioni ci aiuteranno a migliorare la nostra offerta di contenuti e l'esperienza degli utenti.

Collegamento al sondaggio

Questa pagina è stata utile?
Segnala un bug, un errore di battitura o richiedi contenuti su GitHub.