Hasta este punto del curso hemos trabajado muchos conceptos fundamentales de Deep Learning: neuronas artificiales, funciones de activación, arquitectura de redes, propagación hacia adelante, función de pérdida, descenso del gradiente y backpropagation.
Todo eso forma la base teórica que necesitamos para entender cómo aprende una red neuronal. Sin embargo, para construir modelos reales no alcanza solo con conocer la teoría: también necesitamos una herramienta práctica que nos permita programar redes, entrenarlas y evaluarlas.
Esa herramienta será PyTorch. A partir de este tema comenzamos a entrar en la biblioteca que usaremos durante el resto del curso para implementar los modelos de Deep Learning de manera concreta.
PyTorch es una biblioteca de programación para Python orientada a cálculo numérico, aprendizaje automático y Deep Learning.
En términos simples, PyTorch nos da herramientas para trabajar con datos numéricos de forma eficiente y para construir redes neuronales sin tener que programar desde cero todos los detalles matemáticos del entrenamiento.
Con PyTorch podemos:
Por eso PyTorch se ha convertido en una de las bibliotecas más utilizadas en educación, investigación y desarrollo profesional de inteligencia artificial.
PyTorch es muy popular porque logra un equilibrio muy bueno entre potencia y claridad. Permite construir modelos complejos, pero al mismo tiempo su estilo de programación resulta bastante natural para quien ya conoce Python.
Entre sus ventajas principales se suelen mencionar:
Esto es muy valioso porque facilita pasar de la idea teórica al código real sin una barrera técnica excesiva.
PyTorch no reemplaza a Python, sino que funciona dentro de Python. Es decir, escribimos programas normales en Python e importamos PyTorch como una biblioteca más.
Por ejemplo, para empezar a usarla normalmente escribimos:
import torch
Desde ese momento, el programa puede acceder a clases, funciones y estructuras que ofrece PyTorch.
Esto significa que al trabajar con PyTorch seguiremos usando variables, funciones, clases, bucles, condiciones y todas las herramientas habituales del lenguaje Python.
Si quisiéramos implementar una red neuronal completamente a mano, tendríamos que encargarnos de muchas tareas difíciles y repetitivas:
PyTorch simplifica enormemente estas tareas. En lugar de programar todo desde cero, usamos una base sólida que ya resuelve la parte técnica pesada y nos deja concentrarnos en el modelo y en los datos.
La estructura de datos más importante en PyTorch es el tensor. Un tensor puede verse como una generalización de números, vectores y matrices.
Por ejemplo:
En PyTorch casi todo gira alrededor de los tensores. Más adelante dedicaremos temas completos a estudiarlos en profundidad, pero desde ahora conviene entender que son el “contenedor” principal de los datos con los que trabajaremos.
Un ejemplo muy básico de uso de PyTorch puede ser crear un tensor manualmente:
import torch
x = torch.tensor([1, 2, 3, 4])
print(x)
En este caso, PyTorch crea un tensor que contiene cuatro valores. Aunque parece algo pequeño, ya estamos usando la estructura fundamental sobre la cual se construyen los modelos de Deep Learning.
La salida será algo similar a una representación interna del tensor con sus datos numéricos.
Aunque en este curso lo utilizaremos principalmente para Deep Learning, PyTorch no se limita exclusivamente a redes neuronales.
También puede usarse para:
Sin embargo, su mayor fama viene de su aplicación en Machine Learning y Deep Learning.
Uno de los puntos más poderosos de PyTorch es que puede calcular derivadas automáticamente mediante un sistema llamado autograd.
Recordemos que en entrenamiento necesitamos gradientes para saber cómo ajustar pesos y bias. Hacer esto manualmente para redes grandes sería incómodo, propenso a errores y muy poco práctico.
PyTorch puede seguir las operaciones matemáticas realizadas y luego obtener de forma automática las derivadas necesarias para el aprendizaje.
Esto es una de las razones por las cuales bibliotecas como PyTorch hacen posible entrenar modelos complejos de manera razonable.
PyTorch se hizo muy conocido, entre otras cosas, por ofrecer una forma de trabajo que se siente bastante directa. Muchas operaciones se ejecutan en el momento en que las escribimos.
Esto suele describirse como un estilo de programación imperativo o dinámico. Eso significa que el código se comporta de un modo bastante natural: se ejecuta línea por línea y podemos inspeccionar valores intermedios con facilidad.
En la práctica, esto ayuda mucho al depurar, experimentar y entender qué está haciendo el modelo en cada paso.
PyTorch es una biblioteca amplia. No se reduce a una sola herramienta, sino que incluye varios componentes importantes. Entre los más relevantes para este curso están:
En este tema solo las presentaremos de manera general. Más adelante iremos entrando en cada una con más detalle.
Cuando trabajamos con redes neuronales, una parte muy importante de PyTorch es torch.nn.
Este módulo contiene clases y herramientas para definir capas, funciones de activación, funciones de pérdida y modelos completos.
Por ejemplo, muchas capas comunes ya vienen implementadas, como:
Gracias a esto, no hace falta programar cada componente desde cero.
Otro módulo muy importante es torch.optim, que contiene optimizadores listos para usar.
Recordemos que después de calcular gradientes necesitamos un mecanismo para actualizar parámetros. Ese mecanismo lo lleva adelante el optimizador.
Algunos optimizadores conocidos que suelen aparecer en PyTorch son:
La idea importante aquí es que PyTorch ya incluye estas estrategias, por lo que entrenar un modelo es mucho más directo.
En Deep Learning no solo importa el modelo; también importa cómo organizamos y entregamos los datos durante el entrenamiento.
PyTorch incluye utilidades para:
Esto será especialmente útil cuando pasemos de ejemplos pequeños a conjuntos de datos más realistas.
Una de las fortalezas de PyTorch es que puede trabajar tanto en CPU como en GPU.
La CPU es suficiente para ejemplos pequeños, ejercicios didácticos y muchas pruebas iniciales. Pero cuando los modelos y los datos crecen, la GPU puede acelerar mucho el entrenamiento.
Lo importante para un estudiante es comprender que el código general suele ser muy parecido; lo que cambia es el dispositivo donde colocamos tensores y modelos.
Más adelante veremos cómo mover datos y redes a la GPU cuando sea necesario.
En PyTorch, un flujo de trabajo típico de Deep Learning suele tener una secuencia parecida a esta:
Si observas con atención, este flujo coincide bastante con toda la teoría que ya estudiamos. PyTorch no cambia la lógica del aprendizaje; simplemente nos da las herramientas para implementarla.
Sin entrar todavía en todos los detalles, un entrenamiento en PyTorch suele tener una estructura general como esta:
import torch
import torch.nn as nn
import torch.optim as optim
modelo = ...
criterio = ...
optimizador = ...
for epoca in range(cantidad_de_epocas):
prediccion = modelo(entradas)
perdida = criterio(prediccion, salidas_reales)
optimizador.zero_grad()
perdida.backward()
optimizador.step()
Aunque todavía no conozcamos todos los objetos utilizados, este esquema ya nos deja ver algo muy importante: PyTorch convierte la teoría del entrenamiento en una secuencia concreta de instrucciones.
En PyTorch, con mucha frecuencia los modelos se definen como clases de Python que heredan de nn.Module.
Esto puede sonar técnico al principio, pero la idea general es bastante razonable: una red neuronal se trata como un objeto que contiene capas, parámetros y una forma específica de procesar entradas.
De esta manera, el modelo queda organizado y es más fácil reutilizarlo, entrenarlo y evaluarlo.
Más adelante construiremos modelos propios con este enfoque paso a paso.
Aunque PyTorch facilita enormemente el trabajo, no resuelve automáticamente todos los problemas.
Por ejemplo, PyTorch no decide por sí solo:
Es decir, la biblioteca nos da herramientas muy poderosas, pero sigue siendo necesario comprender los conceptos de fondo para usarla bien.
Cuando un estudiante empieza a trabajar con PyTorch, es habitual encontrarse con algunas dificultades iniciales. Por ejemplo:
Estos errores son completamente normales. De hecho, forman parte del aprendizaje. Lo importante es que PyTorch permite inspeccionar objetos y probar operaciones de manera bastante directa, lo que ayuda mucho a corregirlos.
Es importante que no veas PyTorch como algo separado de la teoría. En realidad, PyTorch es una herramienta para expresar en código lo que ya venimos estudiando conceptualmente.
Por ejemplo:
En otras palabras, PyTorch nos permite llevar al terreno práctico lo que ya entendimos en forma teórica.
Este tema tiene un objetivo panorámico: presentar la biblioteca y su lógica general. A partir del siguiente tema empezaremos a profundizar paso a paso.
En particular, lo próximo será estudiar:
Es decir, ahora estamos abriendo la puerta de PyTorch; enseguida comenzaremos a recorrer sus partes más importantes.
PyTorch será la herramienta central de la parte práctica de este curso. Gracias a ella podremos construir redes neuronales, entrenarlas, medir su desempeño y experimentar con diferentes modelos sin tener que implementar desde cero todos los aspectos matemáticos y computacionales del proceso.
La clave en esta etapa no es memorizar todas las funciones de la biblioteca, sino comprender qué papel cumple PyTorch dentro del flujo general del Deep Learning. Si esa idea queda clara, el resto del aprendizaje se vuelve mucho más natural.
En el próximo tema comenzaremos con una de las piezas más importantes de todo PyTorch: los tensores.