En el tema anterior vimos que PyTorch es la biblioteca que utilizaremos para trabajar con Deep Learning en forma práctica. También mencionamos que la estructura de datos más importante dentro de PyTorch es el tensor.
En este tema vamos a estudiar los tensores en detalle, porque prácticamente todo lo que hagamos más adelante dependerá de ellos. Las entradas de una red, los pesos, los bias, las salidas del modelo, los gradientes y hasta muchas métricas intermedias se representan mediante tensores.
Por eso, entender bien esta estructura no es un detalle menor: es una parte central del aprendizaje de PyTorch.
Un tensor es una estructura que permite almacenar datos numéricos organizados en una o más dimensiones.
Si esta definición suena abstracta, conviene pensarla de forma gradual:
En otras palabras, un tensor es una forma general de representar datos numéricos, sin importar si son simples o muy estructurados.
Los tensores son importantes porque permiten expresar de manera uniforme casi todos los objetos con los que trabaja una red neuronal.
Por ejemplo:
Esto simplifica mucho el trabajo, porque PyTorch puede aplicar un conjunto coherente de operaciones a todos esos elementos.
Muchas veces, al empezar, la palabra tensor parece más complicada de lo que realmente es. En realidad, un tensor puede verse como una ampliación de conceptos que probablemente ya conozcas.
Por eso, cuando hablamos de tensores, no estamos introduciendo un objeto completamente ajeno, sino una forma más general de pensar estructuras numéricas.
Una idea clave para entender tensores es la de dimensión. La dimensión indica cuántos ejes necesitamos para describir la estructura del tensor.
Veamos los casos más comunes:
En Deep Learning aparecen con frecuencia tensores de varias dimensiones, especialmente al trabajar con imágenes, secuencias o lotes de ejemplos.
Para que esta idea resulte más concreta, pensemos en algunos ejemplos típicos:
Estos ejemplos muestran que los tensores no son una rareza exclusiva de inteligencia artificial: son una forma general de organizar datos numéricos.
La forma más directa de crear un tensor en PyTorch es usar torch.tensor().
Aquí hemos creado un tensor de una dimensión que contiene cuatro números enteros.
Este es un buen punto de partida para entender que un tensor puede nacer a partir de datos escritos directamente por nosotros.
Un tensor también puede contener un único valor:
En este caso tenemos un tensor escalar. Aunque sea un solo número, sigue siendo un tensor para PyTorch.
Esto es importante porque muchas operaciones internas del entrenamiento producen valores escalares, por ejemplo una pérdida total.
Si usamos una lista de listas, podemos formar una estructura bidimensional:
El resultado representa una tabla con dos filas y tres columnas.
Este tipo de tensor aparece constantemente en Deep Learning, por ejemplo cuando una capa lineal procesa varias entradas al mismo tiempo.
Otro concepto fundamental es la forma del tensor, conocida habitualmente como shape.
La forma indica cuántos elementos hay en cada dimensión. Por ejemplo, si un tensor tiene dos filas y tres columnas, su forma será algo equivalente a:
Esto no solo nos dice que el tensor es bidimensional, sino también cómo está organizado internamente.
Consultar la forma es una de las operaciones más útiles al trabajar con PyTorch, porque muchos errores provienen de usar tensores con dimensiones incompatibles.
Para conocer la forma de un tensor, usamos la propiedad shape:
La salida nos indicará cuántas filas y columnas tiene el tensor.
Acostumbrarse a inspeccionar shape es una excelente práctica para evitar confusiones al empezar.
Además de la forma, muchas veces queremos saber cuántas dimensiones tiene un tensor. Para eso se puede usar ndim.
En este caso, el resultado será 2 porque el tensor tiene dos dimensiones.
Esto ayuda a distinguir entre un vector, una matriz o estructuras más grandes.
Otra propiedad útil es saber cuántos valores contiene en total un tensor. Para eso se puede usar numel().
El resultado será 6 porque hay seis números almacenados en total.
Este dato puede ser útil para verificar estructuras y comprender el tamaño real del objeto con el que estamos trabajando.
Así como en Python existen enteros, flotantes y booleanos, en PyTorch los tensores también tienen un tipo de dato.
Por ejemplo, un tensor puede almacenar:
Esto importa mucho porque no todas las operaciones funcionan igual con todos los tipos. En Deep Learning, con frecuencia se usan tensores de punto flotante, ya que los pesos y los gradientes suelen necesitar valores decimales.
Para ver el tipo de dato de un tensor, se puede usar dtype:
La salida mostrará el tipo interno que PyTorch asignó a ese tensor.
Conocer esto es útil porque a veces una operación falla o se comporta distinto simplemente porque el tensor no tiene el tipo esperado.
Si queremos representar valores decimales, podemos crear tensores con números flotantes:
Este tipo de tensor es muy común en aprendizaje automático, porque muchas variables y parámetros no son enteros exactos.
Además de escribir los datos manualmente, PyTorch ofrece varias funciones para crear tensores de forma rápida.
Por ejemplo, podemos crear:
Estas funciones son muy útiles cuando queremos inicializar datos, pesos o estructuras temporales.
Dos funciones muy usadas son torch.zeros() y torch.ones().
Esto crea dos tensores de dos filas por tres columnas: uno con ceros y otro con unos.
Son especialmente útiles para inicializaciones, máscaras y pruebas rápidas.
También es muy frecuente generar tensores con valores aleatorios:
Este tensor tendrá forma 2 por 3 y sus valores serán decimales aleatorios.
La generación aleatoria es importante en Deep Learning porque muchas veces los pesos iniciales de una red se crean con métodos de este tipo.
PyTorch también permite crear secuencias numéricas de manera cómoda. Una función típica es torch.arange().
Esto genera un tensor con valores desde 0 hasta 9.
Estas secuencias son útiles para pruebas, índices y construcciones auxiliares.
Un tensor no solo tiene datos, forma y tipo. También está ubicado en un dispositivo.
En la práctica, normalmente ese dispositivo será:
Esto importa porque en PyTorch las operaciones deben realizarse entre tensores que estén en dispositivos compatibles. Más adelante veremos este tema con mayor profundidad.
En muchos casos necesitaremos transformar un tensor: cambiar su tipo, moverlo a otro dispositivo o crear una variante del mismo.
Aunque aún no entraremos en todas esas operaciones, conviene saber desde ahora que los tensores son estructuras muy flexibles y que PyTorch ofrece métodos para adaptarlos a distintas necesidades.
Esta flexibilidad resulta esencial en proyectos reales, donde los datos rara vez llegan exactamente en la forma ideal.
Para entender por qué este tema es tan importante, conviene mirar cómo intervienen los tensores en una red neuronal típica.
Esto significa que aprender PyTorch es, en gran medida, aprender a pensar y trabajar con tensores.
Una propiedad especialmente importante en PyTorch es requires_grad. Cuando está activada, PyTorch entiende que debe seguir las operaciones hechas sobre ese tensor para luego poder calcular derivadas.
Esto es fundamental en Deep Learning porque los parámetros entrenables de una red necesitan gradientes para poder actualizarse.
Por ejemplo, un tensor podría crearse así:
No hace falta dominar aún todos los detalles de esta propiedad, pero sí entender que conecta directamente al tensor con el proceso de aprendizaje del modelo.
Una duda muy frecuente es: si Python ya tiene listas, ¿por qué necesitamos tensores?
La respuesta es que una lista de Python sirve como estructura general de programación, pero no está pensada específicamente para cálculo numérico intensivo.
En cambio, los tensores ofrecen ventajas clave:
En otras palabras, una lista puede servir para almacenar datos, pero un tensor está diseñado para ser procesado matemáticamente dentro del flujo de Deep Learning.
Al principio, muchos errores tienen que ver con no prestar atención a la estructura del tensor. Algunos de los más comunes son:
Estos problemas son muy normales. Por eso, una buena costumbre es inspeccionar frecuentemente shape, dtype y ndim.
Si estás empezando con tensores en PyTorch, algunas recomendaciones útiles son:
Estas prácticas hacen que el aprendizaje posterior sea mucho más sólido.
En este tema nos concentramos en comprender qué es un tensor, cómo se representa y por qué es tan importante en PyTorch.
El siguiente paso natural es aprender a operar con ellos: sumar, multiplicar, transformar formas y realizar otras manipulaciones que aparecen constantemente en modelos de Deep Learning.
Es decir, primero entendemos el objeto; luego aprendemos a trabajar activamente con él.
zeros, ones, rand y arange.Los tensores son el lenguaje básico con el que PyTorch expresa casi todo lo que ocurre en un modelo de Deep Learning. Aunque al principio puedan parecer una idea nueva, en realidad son una extensión natural de conceptos conocidos como números, listas y matrices.
Dominar tensores significa construir una base firme sobre la cual luego será mucho más fácil entender operaciones matemáticas, capas, entrenamiento y evaluación de modelos.
En el próximo tema daremos el siguiente paso: aprenderemos a realizar operaciones básicas con tensores en PyTorch.