Clasificación híbrida con conjunto cuántico mejorado (flujo de trabajo de estabilidad de red)
Estimación de uso: 20 minutos de tiempo de QPU para cada trabajo en un procesador Eagle r3. (NOTA: Esto es solo una estimación. Su tiempo de ejecución puede variar.)
Antecedentes
Este tutorial demuestra un flujo de trabajo híbrido cuántico-clásico que mejora un conjunto clásico con un paso de optimización cuántica. Utilizando "Singularity Machine Learning – Classification" de Multiverse Computing (una función Qiskit), entrenamos un conjunto de aprendices convencionales (por ejemplo, árboles de decisión, k-NN, regresión logística) y luego refinamos ese conjunto con una capa cuántica para mejorar la diversidad y la generalización. El objetivo es práctico: en una tarea real de predicción de estabilidad de red, comparamos una línea base clásica sólida con una alternativa optimizada cuánticamente bajo las mismas particiones de datos, para que puedas ver dónde ayuda el paso cuántico y cuál es su costo.
Por qué esto es importante: seleccionar un buen subconjunto entre muchos aprendices débiles es un problema combinatorio que crece rápidamente con el tamaño del conjunto. Las heurísticas clásicas como boosting, bagging y stacking funcionan bien a escalas moderadas, pero pueden tener dificultades para explorar bibliotecas grandes y redundantes de modelos de manera eficiente. La función integra algoritmos cuánticos — específicamente QAOA (y opcionalmente VQE en otras configuraciones) — para buscar en ese espacio de manera más efectiva después de que los aprendices clásicos han sido entrenados, aumentando la probabilidad de encontrar un subconjunto compacto y diverso que generalice mejor.
De manera crucial, la escala de los datos no está limitada por los qubits. El trabajo pesado con los datos — preprocesamiento, entrenamiento del conjunto de aprendices y evaluación — sigue siendo clásico y puede manejar millones de ejemplos. Los qubits solo determinan el tamaño del conjunto utilizado en el paso de selección cuántica. Este desacoplamiento es lo que hace que el enfoque sea viable en el hardware actual: mantienes los flujos de trabajo familiares de scikit-learn para datos y entrenamiento de modelos mientras invoca el paso cuántico a través de una interfaz de acción limpia en Qiskit Functions.
En la práctica, aunque se pueden proporcionar diferentes tipos de aprendices al conjunto (por ejemplo, árboles de decisión, regresión logística o k-NN), los árboles de decisión tienden a funcionar mejor. El optimizador favorece consistentemente a los miembros más fuertes del conjunto — cuando se suministran aprendices heterogéneos, los modelos más débiles como los regresores lineales son típicamente eliminados en favor de modelos más expresivos como los árboles de decisión.
Lo que harás aquí: preparar y balancear el conjunto de datos de estabilidad de red; establecer una línea base clásica con AdaBoost; ejecutar varias configuraciones cuánticas que varían el ancho del conjunto y la regularización; ejecutar en simuladores o QPUs de IBM® a través de Qiskit Serverless; y comparar la exactitud, precisión, exhaustividad y F1 en todas las ejecuciones. A lo largo del proceso, utilizarás el patrón de acciones de la función (create, fit, predict, fit_predict, create_fit_predict) y los controles clave:
- Tipos de regularización:
onsite(λ) para dispersión directa yalphapara un equilibrio basado en proporción entre términos de interacción y términos onsite - Auto-regularización: establece
regularization="auto"con una proporción de selección objetivo para adaptar la dispersión automáticamente - Opciones del optimizador: simulador versus QPU, repeticiones, optimizador clásico y sus opciones, profundidad de transpilación, y configuraciones del sampler/estimator del runtime
Los benchmarks en la documentación muestran que la exactitud mejora a medida que aumenta el número de aprendices (qubits) en problemas desafiantes, con el clasificador cuántico igualando o superando a un conjunto clásico comparable. En este tutorial, reproducirás el flujo de trabajo de principio a fin y examinará cuándo aumentar el ancho del conjunto o cambiar a regularización adaptativa produce un mejor F1 con un uso razonable de recursos. El resultado es una visión fundamentada de cómo un paso de optimización cuántica puede complementar, en lugar de reemplazar, el aprendizaje clásico por conjuntos en aplicaciones reales.
Requisitos
Antes de comenzar este tutorial, asegúrate de tener los siguientes paquetes instalados en tu entorno de Python:
qiskit[visualization]~=2.1.0qiskit-serverless~=0.24.0qiskit-ibm-runtime v0.40.1qiskit-ibm-catalog~=0.8.0scikit-learn==1.5.2pandas>=2.0.0,<3.0.0imbalanced-learn~=0.12.3
Configuración
En esta sección, inicializamos el cliente de Qiskit Serverless y cargamos la función Singularity Machine Learning – Classification proporcionada por Multiverse Computing. Con Qiskit Serverless, puedes ejecutar flujos de trabajo híbridos cuántico-clásicos en la infraestructura de nube gestionada por IBM sin preocuparse por la gestión de recursos. Necesitarás una clave API de IBM Quantum Platform y el nombre de su recurso en la nube (CRN) para autenticarse y acceder a las funciones Qiskit.
Descarga el conjunto de datos
Para ejecutar este tutorial, utilizamos un conjunto de datos de clasificación de estabilidad de red preprocesado que contiene lecturas etiquetadas de sensores de sistemas de energía.
La siguiente celda crea automáticamente la estructura de carpetas necesaria y descarga tanto los archivos de entrenamiento como los de prueba directamente en tu entorno utilizando wget.
Si ya tienes estos archivos localmente, este paso los sobrescribirá de forma segura para garantizar la consistencia de versiones.
# 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
Importa los paquetes necesarios
En esta sección, importamos todos los paquetes de Python y módulos de Qiskit utilizados a lo largo del tutorial.
Estos incluyen bibliotecas científicas fundamentales para el manejo de datos y la evaluación de modelos — como NumPy, pandas y scikit-learn — junto con herramientas de visualización y componentes de Qiskit para ejecutar el modelo con mejora cuántica.
También importamos QiskitRuntimeService y QiskitFunctionsCatalog para conectarnos con los servicios de IBM Quantum® y acceder a la función 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")
Establece las variables constantes
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"
Conéctese a IBM Quantum y carga la función Singularity
A continuación, nos autenticamos con los servicios de IBM Quantum y cargamos la función Singularity Machine Learning – Classification del catálogo de funciones Qiskit.
QiskitRuntimeService establece una conexión segura con IBM Quantum Platform utilizando tu token API y el CRN de la instancia, permitiendo el acceso a los backends cuánticos.
Luego se utiliza QiskitFunctionsCatalog para recuperar la función Singularity por nombre ("multiverse/singularity"), lo que nos permite invocarla posteriormente para la computación híbrida cuántico-clásica.
Si la configuración es exitosa, verás un mensaje de confirmación indicando que la función se ha cargado correctamente.
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)
Define las funciones auxiliares
Antes de ejecutar los experimentos principales, definimos algunas pequeñas funciones de utilidad que simplifican la carga de datos y la evaluación de modelos.
load_data()lee los archivos CSV de entrada en arreglos de NumPy, separando características y etiquetas para la compatibilidad conscikit-learny los flujos de trabajo cuánticos.evaluate_predictions()calcula métricas de rendimiento clave — exactitud, precisión, exhaustividad y puntuación F1 — y opcionalmente informa el tiempo de ejecución si se proporciona información de temporización.
Estas funciones auxiliares simplifican las operaciones repetidas más adelante en el cuaderno y garantizan informes de métricas consistentes en los clasificadores tanto clásicos como cuánticos.
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
Paso 1: Mapea las entradas clásicas a un problema cuántico
Comenzamos preparando el conjunto de datos para la experimentación híbrida cuántico-clásica. El objetivo de este paso es convertir los datos crudos de estabilidad de red en particiones balanceadas de entrenamiento, validación y prueba que puedan ser utilizadas de manera consistente tanto por los flujos de trabajo clásicos como cuánticos. Mantener particiones idénticas asegura que las comparaciones de rendimiento posteriores sean justas y reproducibles.
Carga y preprocesamiento de datos
Primero cargamos los archivos CSV de entrenamiento y prueba, creamos una partición de validación y balanceamos el conjunto de datos mediante sobremuestreo aleatorio. El balanceo previene el sesgo hacia la clase mayoritaria y proporciona una señal de aprendizaje más estable tanto para los modelos de conjunto clásicos como cuánticos.
# 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,)
Línea base clásica: referencia AdaBoost
Antes de ejecutar cualquier optimización cuántica, entrenamos una línea base clásica sólida — un clasificador AdaBoost estándar — con los mismos datos balanceados. Esto proporciona un punto de referencia reproducible para la comparación posterior, ayudando a cuantificar si la optimización cuántica mejora la generalización o la eficiencia más allá de un conjunto clásico bien ajustado.
# ----- 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
Paso 2: Optimiza el problema para la ejecución en hardware cuántico
La tarea de selección de conjuntos se formula como un problema de optimización combinatoria donde cada aprendiz débil es una variable de decisión binaria, y el objetivo equilibra la exactitud con la dispersión a través de un término de regularización. El QuantumEnhancedEnsembleClassifier resuelve esto con QAOA en hardware de IBM, permitiendo al mismo tiempo la exploración basada en simulador. Las optimizer_options controlan el bucle híbrido: simulator=False dirige los circuitos a la QPU seleccionada, num_solutions aumenta la amplitud de búsqueda, y classical_optimizer_options (para el optimizador clásico interno) gobiernan la convergencia; valores alrededor de 60 iteraciones son un buen equilibrio entre calidad y tiempo de ejecución. Las opciones de ejecución — como una profundidad de circuito moderada (reps) y un esfuerzo de transpilación estándar — ayudan a garantizar un rendimiento robusto en todos los dispositivos. La configuración siguiente es el perfil de "mejores resultados" que utilizaremos para las ejecuciones en hardware; también puedes crear una variante puramente simulada activando simulator=True para probar el flujo de trabajo sin consumir tiempo de 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
Paso 3: Ejecuta utilizando primitivas de Qiskit
Ahora ejecutamos el flujo de trabajo completo utilizando la acción create_fit_predict de la función Singularity para entrenar, optimizar y evaluar el QuantumEnhancedEnsembleClassifier de principio a fin en la infraestructura de IBM. La función construye el conjunto, aplica la optimización cuántica a través de las primitivas de Qiskit y devuelve tanto las predicciones como los metadatos del trabajo (incluyendo el tiempo de ejecución y el uso de recursos). La partición de datos clásica del Paso 1 se reutiliza para la reproducibilidad, con los datos de validación pasados a través de fit_params para que la optimización pueda ajustar los hiperparámetros internamente mientras mantiene el conjunto de prueba reservado sin tocar.
En este paso, exploramos varias configuraciones del conjunto cuántico para comprender cómo los parámetros clave — específicamente num_learners y regularization — afectan tanto la calidad de los resultados como el uso de la QPU.
num_learnersdetermina el ancho del conjunto (e implícitamente, el número de qubits), influyendo en la capacidad del modelo y el costo computacional.regularizationcontrola la dispersión y el sobreajuste, determinando cuántos aprendices permanecen activos después de la optimización.
Al variar estos parámetros, podemos ver cómo interactúan el ancho del conjunto y la regularización: aumentar el ancho típicamente mejora el F1 pero cuesta más tiempo de QPU, mientras que una regularización más fuerte o adaptativa puede mejorar la generalización con aproximadamente la misma huella de hardware. Las siguientes subsecciones presentan tres configuraciones representativas para ilustrar estos efectos.