Path: blob/main/translations/es/ch-machine-learning/machine-learning-qiskit-pytorch.ipynb
3861 views
Redes Neuronales Híbridas cuánticas-clásicas con PyTorch y Qiskit
El aprendizaje automático (machine learnng, ML) se ha establecido como un campo interdisciplinario exitoso que busca extraer matemáticamente información generalizable de los datos. Incluirlo en la computación cuántica da lugar a interesantes áreas de investigación que buscan aprovechar los principios de la mecánica cuántica para aumentar el aprendizaje automático o viceversa. Ya sea que su objetivo sea mejorar los algoritmos de ML clásicos dejando los cálculos difíciles a una computadora cuántica u optimizar algoritmos cuánticos usando arquitecturas de ML clásicas, ambos se encuentran bajo el marco diverso del aprendizaje automático cuántico (quantum machine learning, QML).
En este capítulo, exploramos cómo una red neuronal clásica se puede modificar parcialmente para crear una red neuronal cuántica-clásica híbrida. Codificaremos un ejemplo sencillo que integra Qiskit con un paquete de software de código abierto de última generación: PyTorch. El propósito de este ejemplo es demostrar la facilidad de integrar Qiskit con las herramientas de ML existentes y alentar a los profesionales de ML a explorar lo que es posible con la computación cuántica.
Contenido
1. ¿Cómo funciona?

La Figura 1 ilustra el marco que construiremos en este capítulo. En última instancia, crearemos una red neuronal cuántica-clásica híbrida que busca clasificar dígitos dibujados a mano. Ten en cuenta que las conexiones que se muestran en esta imagen están todas dirigidas hacia abajo; sin embargo, la direccionalidad no se indica visualmente.
1.1 Preliminares
Los antecedentes presentados aquí sobre las redes neuronales clásicas se incluyen para establecer ideas relevantes y terminología compartida; sin embargo, siguen siendo de un nivel extremadamente alto. Si deseas profundizar un poco más en las redes neuronales clásicas, mira la serie de videos bien hechos del youtuber 3Blue1Brown. Como alternativa, si ya estás familiarizado con las redes clásicas, puedes pasar a la siguiente sección.
Neuronas y Pesos
Una red neuronal es, en última instancia, solo una función elaborada que se construye al componer bloques de construcción más pequeños llamados neuronas. Una neurona suele ser una función simple, fácil de calcular y no lineal que mapea una o más entradas a un único número real. La salida única de una neurona generalmente se copia y se alimenta como entrada a otras neuronas. Gráficamente, representamos las neuronas como nodos en un grafo y dibujamos conexiones dirigidas entre los nodos para indicar que se usará la salida de una neurona como entrada para otras neuronas. También es importante tener en cuenta que cada arista de nuestro grafo suele estar asociada con un valor escalar llamado peso. La idea aquí es que cada una de las entradas a una neurona se multiplique por un escalar diferente antes de recopilarse y procesarse en un solo valor. El objetivo al entrenar una red neuronal consiste principalmente en elegir nuestros pesos para que la red se comporte de una manera particular.
Redes Neuronales Prealimentadas
También vale la pena señalar que el tipo particular de red neuronal del que nos ocuparemos se denomina red neuronal prealimentada (feed-forward neural network, FFNN). Esto significa que a medida que los datos fluyen a través de nuestra red neuronal, nunca volverán a una neurona que ya visitó. De manera equivalente, podrías decir que el grafo que describe nuestra red neuronal es un grafo acíclico dirigido (directed acyclic graph, DAG). Además, estipularemos que las neuronas dentro de la misma capa de nuestra red neuronal no tendrán conexiones entre ellas.
Estructura de Entrada y Salida de las Capas
La entrada a una red neuronal es un vector clásico (de valor real). Cada componente del vector de entrada se multiplica por un peso diferente y se alimenta a una capa de neuronas de acuerdo con la estructura del grafo de la red. Después de evaluar cada neurona de la capa, los resultados se recopilan en un nuevo vector donde el i-ésimo componente registra la salida de la i-ésima neurona. Este nuevo vector se puede tratar como una entrada para una nueva capa, y así sucesivamente. Usaremos el término estándar capa oculta para describir todas las capas de nuestra red, excepto la primera y la última.
2. Entonces, ¿Cómo entra en Escena lo Cuántico?
Para crear una red neuronal cuántica-clásica, uno puede implementar una capa oculta para nuestra red neuronal utilizando un circuito cuántico parametrizado. Por "circuito cuántico parametrizado", nos referimos a un circuito cuántico donde los ángulos de rotación para cada compuerta están especificados por los componentes de un vector de entrada clásico. Las salidas de la capa anterior de nuestra red neuronal se recopilarán y usarán como entradas para nuestro circuito parametrizado. Las mediciones estadísticas de nuestro circuito cuántico se pueden recopilar y utilizar como entradas para la siguiente capa. A continuación se muestra un simple ejemplo:

Aquí, es una función no lineal y es el valor de la neurona en cada capa oculta. representa cualquier compuerta de rotación sobre un ángulo igual a e es el valor de predicción final generado a partir de la red híbrida.
¿Qué pasa con la retropropagación?
Si estás familiarizado con el ML clásico, es posible que te preguntes de inmediato ¿cómo calculamos los gradientes cuando se trata de circuitos cuánticos? Esto sería necesario para incorporar potentes técnicas de optimización como el descenso de gradiente. Se vuelve un poco técnico, pero en resumen, podemos ver un circuito cuántico como una caja negra y el gradiente de esta caja negra con respecto a sus parámetros se puede calcular de la siguiente manera:

donde representa los parámetros del circuito cuántico y es un cambio macroscópico. El gradiente es entonces simplemente la diferencia entre nuestro circuito cuántico evaluado en y . Por lo tanto, podemos diferenciar sistemáticamente nuestro circuito cuántico como parte de una rutina de retropropagación más grande. Esta regla de forma cerrada para calcular el gradiente de los parámetros del circuito cuántico se conoce como regla de cambio de parámetros.
3.2 Crea una "Clase Cuántica" con Qiskit
Convenientemente, podemos poner nuestras funciones cuánticas de Qiskit en una clase. Primero, especificamos cuántos parámetros cuánticos entrenables y cuántas iteraciones deseamos usar en nuestro circuito cuántico. En este ejemplo, lo mantendremos simple y utilizaremos un circuito de 1 qubit con un parámetro cuántico entrenable . Codificamos de forma fija el circuito por simplicidad y empleamos una rotación con el ángulo para entrenar la salida de nuestro circuito. El circuito se ve así:

Para medir la salida en la base , calculamos el valor esperado de . Más adelante veremos cómo todo esto se relaciona con la red neuronal híbrida.
Probemos la implementación
3.3 Crea una "Clase Cuántica-Clásica" con PyTorch
Ahora, que nuestro circuito cuántico está definido, podemos crear las funciones necesarias para la retropropagación usando PyTorch. Los pases hacia adelante y hacia atrás contienen elementos de nuestra clase Qiskit. El pase hacia atrás calcula directamente los gradientes utilizando la fórmula de diferencia finita que presentamos anteriormente.
3.4 Carga y Preprocesamiento de Datos
Uniendo todo:
Crearemos una red neuronal híbrida simple para clasificar imágenes de dos tipos de dígitos (0 o 1) del conjunto de datos MNIST. Primero cargamos la base de datos MNIST y filtramos las imágenes que contienen 0 y 1. Estos servirán como entradas para que nuestra red neuronal los clasifique.
Datos de entrenamiento
Datos de prueba
Hasta ahora, hemos cargado los datos y codificado una clase que crea nuestro circuito cuántico que contiene 1 parámetro entrenable. Este parámetro cuántico se insertará en una red neuronal clásica junto con los otros parámetros clásicos para formar la red neuronal híbrida. También creamos funciones de pase hacia atrás y hacia adelante que nos permiten hacer retropropagación y optimizar nuestra red neuronal. Por último, debemos especificar nuestra arquitectura de red neuronal, de modo que podamos comenzar a entrenar nuestros parámetros utilizando técnicas de optimización proporcionadas por PyTorch.
3.5 Creación de la Red Neuronal Híbrida
Podemos usar una canalización (pipeline) ordenada de PyTorch para crear una arquitectura de red neuronal. La red deberá ser compatible en términos de su dimensionalidad cuando insertemos la capa cuántica (es decir, nuestro circuito cuántico). Dado que lo cuántico en este ejemplo contiene 1 parámetro, debemos asegurarnos de que la red condense las neuronas reduciendo al tamaño 1. Creamos una red neuronal convolucional típica con dos capas completamente conectadas al final. El valor de la última neurona de la capa totalmente conectada se introduce como parámetro en nuestro circuito cuántico. La medición del circuito luego sirve como la predicción final para 0 o 1 según lo proporcionado por una medición .
3.6 Entrenamiento de la Red
¡Ya tenemos todos los ingredientes para entrenar nuestra red híbrida! Podemos especificar cualquier optimizador de PyTorch, tasa de aprendizaje y función de costo/pérdida para entrenar con múltiples épocas. En este caso, usamos el optimizador Adam, una tasa de aprendizaje de 0.001 y la función de pérdida de verosimilitud logarítmica negativa.
Mostrar el grafo de entrenamiento
4. ¿Qué Sigue?
Si bien es totalmente posible crear redes neuronales híbridas, ¿realmente tiene algún beneficio?
De hecho, las capas clásicas de esta red se entrenan perfectamente bien (de hecho, mejor) sin la capa cuántica. Además, es posible que hayas notado que la capa cuántica que entrenamos aquí no genera entrelazamiento y, por lo tanto, seguirá siendo clásicamente simulable a medida que ampliemos esta arquitectura en particular. Esto significa que si esperas lograr una ventaja cuántica utilizando redes neuronales híbridas, deberás comenzar extendiendo este código para incluir una capa cuántica más sofisticada.
El objetivo de este ejercicio era hacerte pensar en la integración de técnicas de ML y computación cuántica para investigar si realmente hay algún elemento de interés, y gracias a PyTorch y Qiskit, esto se vuelve un poco más fácil.