Skip to main content
IBM Quantum Platform

Clasificación híbrida de conjuntos mejorada cuánticamente (flujo de trabajo de estabilidad de la red)

Estimación de uso: 20 minutos en tiempo QPU para cada trabajo en un procesador Eagle r3. (NOTA: Esto es sólo una estimación. Su tiempo de ejecución puede variar)


En segundo plano

Este tutorial muestra un flujo de trabajo híbrido cuántico-clásico que mejora un conjunto clásico mediante una etapa de optimización cuántica. Mediante el uso de «Singularity Machine Learning –Classification» de Multiverse Computing (una función de Qiskit), entrenamos un conjunto de modelos de aprendizaje convencionales (por ejemplo, árboles de decisión, k-NN o regresión logística) y, a continuación, refinamos dicho 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 la estabilidad de la red eléctrica, comparamos una referencia clásica sólida con una alternativa optimizada cuánticamente utilizando las mismas divisiones de datos, para que puedas ver en qué aspectos ayuda el enfoque cuántico y qué costes conlleva.

Por qué 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 eficientemente bibliotecas de modelos grandes y redundantes. La función integra algoritmos cuánticos -concretamente QAOA (y opcionalmente VQE en otras configuraciones)- para buscar en ese espacio de forma más eficaz una vez entrenados los aprendices clásicos, lo que aumenta la probabilidad de encontrar un subconjunto compacto y diverso que generalice mejor.

Lo más importante es que la escala de datos no está limitada por los qubits. El trabajo pesado con los datos -preprocesamiento, formación del conjunto de alumnos y evaluación- sigue siendo clásico y puede manejar millones de ejemplos. Los Qubits sólo 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: se mantienen los flujos de trabajo familiares de scikit-learn para el entrenamiento de datos y modelos, mientras que se llama al 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 sistemáticamente a los miembros más fuertes del conjunto: cuando se suministran aprendices heterogéneos, los modelos más débiles, como los regresores lineales, suelen ser eliminados en favor de los más expresivos, como los árboles de decisión.

Lo que harás aquí: preparar y equilibrar el conjunto de datos de estabilidad de la red; establecer una línea de base clásica AdaBoost; ejecutar varias configuraciones cuánticas que varían el ancho del conjunto y la regularización; ejecutar en simuladores IBM® o QPUs a través de Qiskit Serverless; y comparar la exactitud, precisión, recuperación y F1 a través de todas las ejecuciones. Por el camino, utilizará el patrón de acción de la función (create, fit, predict, fit_predict, create_fit_predict) y los controles de teclas:

  • Tipos de regularización: onsite (λ) para la dispersión directa y alpha para una compensación basada en la proporción entre los términos de interacción y los in situ
  • Autorregularización: establecer regularization="auto" con un ratio de selección objetivo para adaptar la dispersión automáticamente
  • Opciones del optimizador: simulador frente a QPU, repeticiones, optimizador clásico y sus opciones, profundidad de transpilación y configuración del muestreador o estimador de « Qiskit Runtime »

Las pruebas de la documentación muestran que la precisión mejora a medida que aumenta el número de aprendices (qubits) en problemas difíciles, y que el clasificador cuántico iguala o supera a un conjunto clásico comparable. En este tutorial, reproducirá el flujo de trabajo de principio a fin y examinará si el aumento de la amplitud del conjunto o el cambio a la regularización adaptativa produce mejores resultados en F1 con un uso razonable de los recursos. El resultado es una visión fundamentada de cómo un paso de optimización cuántica puede complementar, en lugar de sustituir, el aprendizaje clásico por conjuntos en aplicaciones reales.


Requisitos

Antes de comenzar este tutorial, asegúrese de tener instalados los siguientes paquetes en su entorno 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

Configuración

En esta sección, inicializamos el cliente Qiskit Serverless y cargamos la función Singularity Machine Learning - Classification proporcionada por Multiverse Computing. Con Qiskit Serverless, puede ejecutar flujos de trabajo híbridos cuántico-clásicos en la infraestructura de nube gestionada de IBM sin preocuparse de la gestión de recursos. Necesitará una clave API de IBM Quantum Platform y su nombre de recurso en la nube (CRN) para autenticarse y acceder a Qiskit Functions.

Descargar el conjunto de datos

Para ejecutar este tutorial, utilizamos un conjunto de datos de clasificación de la estabilidad de la red preprocesado que contiene lecturas de sensores del sistema eléctrico etiquetadas. La siguiente celda crea automáticamente la estructura de carpetas necesaria y descarga los archivos de formación y de prueba directamente en su entorno mediante wget. Si ya tiene estos archivos localmente, este paso los sobrescribirá de forma segura para garantizar la coherencia de la versión.

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

Importar los paquetes necesarios

En esta sección, importamos todos los paquetes Python y módulos Qiskit utilizados a lo largo del tutorial. Entre ellas se incluyen bibliotecas científicas básicas para el tratamiento de datos y la evaluación de modelos -como NumPy, pandas y scikit-learn - junto con herramientas de visualización y componentes Qiskit para ejecutar el modelo cuántico mejorado. También importamos QiskitRuntimeService y QiskitFunctionsCatalog para conectar con los servicios IBM Quantum® y acceder a la función 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")

Establecer 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 cargue la función Singularity

A continuación, nos autenticamos con los servicios de IBM Quantum y cargamos la función Singularity Machine Learning - Classification de Qiskit Functions Catalog. QiskitRuntimeService establece una conexión segura con IBM Quantum Platform utilizando su token de API y su CRN de instancia, lo que permite el acceso a los backends cuánticos. El QiskitFunctionsCatalog se utiliza entonces para recuperar la función Singularidad por su nombre ("multiverse/singularity"), lo que nos permite llamarla más tarde para el cálculo híbrido cuántico-clásico. Si la configuración se realiza correctamente, aparecerá un mensaje de confirmación indicando que la función se ha cargado correctamente.

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)

Definir funciones auxiliares

Antes de ejecutar los experimentos principales, definimos algunas pequeñas funciones de utilidad que agilizan la carga de datos y la evaluación de modelos.

  • load_data() lee los archivos CSV de entrada en matrices NumPy, dividiendo las características y las etiquetas para que sean compatibles con scikit-learn y los flujos de trabajo cuánticos.
  • evaluate_predictions() calcula las principales métricas de rendimiento (exactitud, precisión, recuperación y F1-score ) y, opcionalmente, informa del tiempo de ejecución si se proporciona información sobre los tiempos.

Estas funciones de ayuda simplifican las operaciones repetidas más adelante en el cuaderno y garantizan un informe métrico coherente en los clasificadores clásicos y 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: Asignar entradas clásicas a un problema cuántico

Comenzamos preparando el conjunto de datos para la experimentación híbrida cuántica-clásica. El objetivo de este paso es convertir los datos brutos de estabilidad de la red en divisiones equilibradas de entrenamiento, validación y prueba que puedan ser utilizadas de forma coherente tanto por los flujos de trabajo clásicos como por los cuánticos. Mantener divisiones idénticas garantiza 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 división de validación y equilibramos el conjunto de datos mediante sobremuestreo aleatorio. El equilibrio evita el sesgo hacia la clase mayoritaria y proporciona una señal de aprendizaje más estable tanto para los modelos de conjuntos clásicos como para los 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)

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

Referencia clásica: AdaBoost reference

Antes de ejecutar cualquier optimización cuántica, entrenamos una línea de base clásica fuerte -un clasificador estándar AdaBoost - en los mismos datos equilibrados. Esto proporciona un punto de referencia reproducible para posteriores comparaciones, 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 afinado.

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

Paso 2: Optimizar el problema para la ejecución en hardware cuántico

La tarea de selección de conjuntos se plantea como un problema de optimización combinatoria en el que cada clasificador débil es una variable de decisión binaria, y el objetivo busca el equilibrio entre la precisión y la dispersión mediante un término de regularización. El sistema resuelve QuantumEnhancedEnsembleClassifier este problema mediante QAOA en hardware de tipo « IBM », sin dejar de permitir la exploración basada en simuladores. El control optimizer_options del bucle híbrido: simulator=False dirige los circuitos hacia la QPU seleccionada, num_solutions aumenta la amplitud de búsqueda y ( classical_optimizer_options en el caso del optimizador clásico interno) regula la convergencia; unos valores en torno a las 60 iteraciones ofrecen un buen equilibrio entre calidad y tiempo de ejecución. Las opciones de tiempo de ejecución —como una profundidad de circuito moderada (reps) y un esfuerzo de transpilación estándar— contribuyen a garantizar un rendimiento sólido en todos los dispositivos. La configuración que se muestra a continuación es el perfil «best-results» que utilizaremos para las ejecuciones en hardware; también puedes crear una variante puramente simulada activando la opción simulator=True para ejecutar el flujo de trabajo en modo de simulación sin consumir tiempo de la 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

Paso 3: Ejecutar utilizando Qiskit primitives

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 extremo a extremo en la infraestructura IBM. La función construye el conjunto, aplica la optimización cuántica a través de Qiskit primitives, y devuelve tanto las predicciones como los metadatos del trabajo (incluido el tiempo de ejecución y el uso de recursos). La divisió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 se mantiene intacto el conjunto de prueba retenido.

En este paso, exploramos varias configuraciones del conjunto cuántico para comprender cómo afectan los parámetros clave -específicamente num_learners y regularization - tanto a la calidad de los resultados como al uso de la QPU.

  • num_learners determina la anchura del conjunto (e implícitamente, el número de qubits), lo que influye en la capacidad y el coste computacional del modelo.
  • regularization controla la dispersión y el sobreajuste, determinando cuántos aprendices permanecen activos tras la optimización.

Variando estos parámetros, podemos ver cómo interactúan la anchura del conjunto y la regularización: aumentar la anchura suele mejorar 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 recorren tres configuraciones representativas para ilustrar estos efectos.

Línea base

Esta configuración utiliza num_learners = 10 y regularization = 7.

  • num_learners controla la anchura del conjunto, es decir, el número de aprendices débiles combinados y, en el hardware cuántico, el número de qubits necesarios. Un valor mayor amplía el espacio de búsqueda combinatoria y puede mejorar la precisión y la recuperación, pero también aumenta la anchura del circuito, el tiempo de compilación y el uso general de la QPU.
  • regularization establece la intensidad de la penalización por incluir alumnos adicionales. Con la regularización "in situ" por defecto, los valores más altos imponen una mayor dispersión (se mantienen menos aprendices), mientras que los valores más bajos permiten conjuntos más complejos.

Esta configuración proporciona una línea de base de bajo coste, mostrando cómo se comporta un conjunto pequeño antes de escalar la anchura o ajustar la dispersión.

# 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

Aumentar el número de alumnos

Aquí aumentamos num_learners de 10 → 30 manteniendo regularization = 7.

  • Un mayor número de aprendices amplía el espacio de hipótesis, lo que permite al modelo captar patrones más sutiles, que pueden elevar modestamente F1.
  • En la mayoría de los casos, la diferencia de tiempo de ejecución entre 10 y 30 aprendices no es sustancial, lo que indica que la anchura de circuito añadida no aumenta significativamente el coste de ejecución.
  • La mejora de la calidad sigue una curva de rendimiento decreciente : las primeras ganancias aparecen a medida que crece el conjunto, pero se estabilizan a medida que los alumnos adicionales aportan menos información nueva.

Este experimento pone de relieve la relación entre calidad y eficiencia: aumentar la anchura del conjunto puede ofrecer pequeñas mejoras de precisión sin una penalización importante en el tiempo de ejecución, dependiendo de las condiciones del backend y de la transpilación.

# 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

Regularización

En esta configuración, aumentamos a num_learners = 60 e introducimos la regularización adaptativa para gestionar la dispersión de forma más intuitiva.

  • Con regularization = "auto", el optimizador encuentra automáticamente una fuerza de regularización adecuada que selecciona aproximadamente regularization_ratio * num_learners aprendices débiles para el conjunto final, en lugar de fijar la penalización manualmente. Esto proporciona una interfaz más cómoda para gestionar el equilibrio entre la dispersión y el tamaño del conjunto.
  • regularization_type = "alpha" define cómo se aplica la sanción. A diferencia de onsite, que no está acotado [0, ∞], alpha está acotado entre [0, 1], lo que facilita su ajuste e interpretación. El parámetro controla el equilibrio entre las penalizaciones individuales y por pareja, ofreciendo un rango de configuración más suave.
  • regularization_desired_ratio ≈ 0.82 especifica la proporción objetivo de alumnos que se mantendrán activos después de la regularización; en este caso, se retiene alrededor del 82% de los alumnos, recortando automáticamente el 18% más débil.

Aunque la regularización adaptativa simplifica la configuración y ayuda a mantener un conjunto equilibrado, no garantiza necesariamente un rendimiento mejor o más estable. La calidad real depende de la selección de un parámetro de regularización adecuado, y su ajuste mediante validación cruzada puede ser costoso desde el punto de vista informático. La principal ventaja reside en una mayor facilidad de uso e interpretación, más que en un aumento directo de la precisión.

# 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

Paso 4: Procesamiento posterior y devolución del resultado en el formato clásico deseado

A continuación, postprocesamos los resultados de las ejecuciones clásica y cuántica, convirtiéndolos a un formato coherente para su evaluación posterior. Este paso compara la calidad predictiva utilizando métricas estándar -exactitud, precisión, recuperación y F1 - y analiza cómo la amplitud del conjunto (num_learners) y el control de la dispersión (regularization) influyen tanto en el rendimiento como en el comportamiento computacional.

La línea de base clásica AdaBoost proporciona una referencia compacta y estable para el aprendizaje a pequeña escala. Funciona bien con conjuntos limitados y una sobrecarga computacional insignificante, lo que refleja la fuerza del boosting tradicional cuando el espacio de hipótesis sigue siendo manejable. Las configuraciones cuánticas (qeec_pred_job_1, qeec_pred_job_2, y qeec_pred_job_3) amplían esta línea de base incrustando el proceso de selección de conjuntos dentro de un bucle de optimización cuántica variacional. Esto permite al sistema explorar simultáneamente subconjuntos exponencialmente grandes de alumnos en superposición, abordando la naturaleza combinatoria de la selección de conjuntos de forma más eficiente a medida que aumenta la escala.

Los resultados muestran que aumentar num_learners de 10 a 30 mejora la recuperación y F1, lo que confirma que un conjunto más amplio capta interacciones más ricas entre aprendices débiles. La ganancia es sublineal en el hardware actual -cada aprendiz adicional produce incrementos de precisión más pequeños-, pero el comportamiento de escalado subyacente sigue siendo favorable porque el optimizador cuántico puede buscar espacios de configuración más amplios sin la explosión exponencial típica de la selección clásica de subconjuntos. La regularización introduce un matiz adicional: una λ=7 fija impone una dispersión consistente y estabiliza la convergencia, mientras que la regularización α adaptativa ajusta automáticamente la dispersión basándose en las correlaciones entre los alumnos. Esta poda dinámica a menudo consigue una F1 ligeramente superior para la misma anchura de qubit, equilibrando la complejidad del modelo y la generalización.

Cuando se compara directamente con la línea de base AdaBoost, la configuración cuántica más pequeña ( L=10 ) reproduce una precisión similar, validando la corrección de la tubería híbrida. Con anchuras mayores, las variantes cuánticas -especialmente con autorregularización- empiezan a superar modestamente la línea de base clásica, mostrando una mejora de la recuperación y F1 sin un crecimiento lineal del coste computacional. Estas mejoras no indican una "ventaja cuántica" inmediata, sino más bien una eficacia de escalado : el optimizador cuántico mantiene un rendimiento manejable a medida que se amplía el conjunto, mientras que un enfoque clásico se enfrentaría a un crecimiento exponencial de la complejidad de la selección de subconjuntos.

En la práctica:

  • Utilice la línea de base clásica para la validación rápida y la evaluación comparativa en pequeños conjuntos de datos.
  • Aplique conjuntos cuánticos cuando aumente la amplitud del modelo o la complejidad de las características: la búsqueda basada en QAOA se adapta mejor a esos regímenes.
  • Emplear la α-regularización adaptativa para mantener la dispersión y la generalización sin aumentar la anchura del circuito.
  • Supervise el tiempo y la profundidad de la QPU para equilibrar las mejoras de calidad con las limitaciones de hardware a corto plazo.

En conjunto, estos experimentos demuestran que los conjuntos optimizados cuánticamente complementan a los métodos clásicos: reproducen la precisión de referencia a escalas pequeñas y, al mismo tiempo, ofrecen una vía hacia el escalado eficiente en problemas de aprendizaje combinatorio de mayor envergadura. A medida que mejore el hardware, se espera que estas ventajas de escalado se agraven, ampliando el tamaño y la profundidad factibles de los modelos basados en conjuntos más allá de lo que resulta práctico clásicamente.

Evaluar las métricas para cada configuración

A continuación, evaluamos todas las configuraciones (la base clásica AdaBoost y los tres conjuntos cuánticos) con la ayuda de evaluate_predictions para calcular la exactitud, la precisión, la recuperación y F1 en el mismo conjunto de pruebas. Esta comparación aclara cómo se escala la optimización cuántica en relación con el enfoque clásico: con anchuras pequeñas, ambos funcionan de forma similar; a medida que los conjuntos crecen, el método cuántico puede explorar espacios de hipótesis más grandes de forma más eficiente. El cuadro resultante recoge estas tendencias de forma coherente y cuantitativa.

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 ,

Visualice las tendencias de calidad en todas las configuraciones

El gráfico de barras agrupadas que aparece a continuación compara la precisión y la F1 entre la línea de base clásica y los conjuntos cuánticos (L=10, L=30, y L=60 auto-α). Ilustra cómo la precisión se estabiliza mientras que F1 mejora gradualmente a medida que aumenta la anchura del conjunto cuántico, lo que demuestra que el método híbrido mantiene el escalado del rendimiento sin el crecimiento exponencial de los costes típico de la selección clásica de subconjuntos.

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

Interpretación

El gráfico confirma el patrón de escala esperado. El método clásico AdaBoost funciona muy bien con conjuntos pequeños, pero su escala es cada vez más costosa a medida que aumenta el número de aprendices débiles, porque su problema de selección de subconjuntos se expande combinatoriamente. Los modelos mejorados cuánticamente replican la precisión clásica a anchuras bajas y comienzan a superarla a medida que aumenta el tamaño del conjunto, especialmente bajo α-regularización adaptativa. Esto refleja la capacidad del optimizador cuántico para muestrear y evaluar muchos subconjuntos candidatos en paralelo mediante superposición, manteniendo una búsqueda manejable incluso con anchuras mayores. Aunque la sobrecarga actual del hardware compensa algunas de las ganancias teóricas, la tendencia ilustra la ventaja de eficiencia de escalado de la formulación cuántica. En términos prácticos, el método clásico sigue siendo preferible para los puntos de referencia ligeros, mientras que los conjuntos mejorados cuánticamente se vuelven ventajosos a medida que la dimensionalidad del modelo y el tamaño del conjunto aumentan, ofreciendo mejores compensaciones entre precisión, generalización y crecimiento computacional.


Apéndice: Beneficios y mejoras de escalabilidad

La ventaja de la escalabilidad de QuantumEnhancedEnsembleClassifier se debe a cómo el proceso de selección de conjuntos se corresponde con la optimización cuántica. Los métodos clásicos de aprendizaje por conjuntos, como AdaBoost o los bosques aleatorios, resultan costosos desde el punto de vista informático a medida que aumenta el número de aprendices débiles, ya que la selección del subconjunto óptimo es un problema combinatorio que se escala exponencialmente.

En cambio, la formulación cuántica -aplicada aquí mediante el Algoritmo de Optimización Cuántica Aproximada (QAOA)- puede explorar estos espacios de búsqueda exponencialmente grandes de forma más eficiente evaluando múltiples configuraciones en superposición. Como resultado, el tiempo de entrenamiento no crece significativamente con el número de aprendices, lo que permite que el modelo siga siendo eficiente aunque aumente la amplitud del conjunto.

Aunque el hardware actual introduce algunas limitaciones de ruido y profundidad, este flujo de trabajo demuestra un enfoque híbrido a corto plazo en el que los componentes clásicos y cuánticos cooperan: el optimizador cuántico proporciona un mejor paisaje de inicialización para el bucle clásico, mejorando la convergencia y la calidad del modelo final. A medida que evolucionen los procesadores cuánticos, se espera que estas ventajas de escalabilidad se extiendan a conjuntos de datos más grandes, conjuntos más amplios y circuitos más profundos.


Referencias

  1. Introducción a la Qiskit Functions
  2. Singularidad informática multiversal Machine Learning

Encuesta tutorial

Tómese un minuto para comentar este tutorial. Su opinión nos ayudará a mejorar nuestra oferta de contenidos y la experiencia de los usuarios.

Enlace a la encuesta

¿Le ha resultado útil esta página?
Informe de un error, de una errata o solicite contenido en GitHub.