LECCIÓN 2 · FUNDAMENTOS

Tensores

El tensor es la pieza fundamental de PyTorch: todo son tensores (los datos, los pesos, los gradientes). Aprende a crearlos, conocer su forma y tipo, y manipularlos.

1. ¿Qué es un tensor?

Un tensor es un array de números de cualquier número de dimensiones. Es el mismo concepto que un array de NumPy, generalizado:

DimensionesNombreEjemplo
0escalar3.14
1vector[1, 2, 3]
2matriz[[1, 2], [3, 4]]
3+tensorimágenes, lotes de datos, etc.

2. Formas de crear tensores

Además de torch.tensor(...) (a partir de una lista), hay constructores muy usados:

torch.zeros(2, 3)        # matriz 2x3 de ceros
torch.ones(2, 3)         # matriz 2x3 de unos
torch.arange(0, 10, 2)   # de 0 a 10 (sin incluir) de 2 en 2
torch.linspace(0, 1, 5)  # 5 valores equiespaciados de 0 a 1
torch.eye(3)            # matriz identidad 3x3
salida realzeros(2,3): tensor([[0., 0., 0.], [0., 0., 0.]]) arange(0,10,2): tensor([0, 2, 4, 6, 8]) linspace(0,1,5): tensor([0.0000, 0.2500, 0.5000, 0.7500, 1.0000]) eye(3): tensor([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])

Tensores aleatorios (clave para inicializar pesos de una red):

torch.manual_seed(0)            # para reproducir los mismos números
torch.rand(2, 2)             # uniforme en [0, 1)
torch.randn(2, 2)            # normal (media 0, desviación 1)
salida realrand: tensor([[0.4963, 0.7682], [0.0885, 0.1320]]) randn: tensor([[ 1.5410, -0.2934], [-2.1788, 0.5684]])
🎲 manual_seed fija el generador aleatorio. Sin él, cada ejecución da números distintos. Con él, reproduces resultados exactos — esencial para depurar y comparar.

3. Las propiedades que siempre mirarás: shape y dtype

t = torch.tensor([[1, 2, 3],
                  [4, 5, 6]])
print(t.shape)   # forma
print(t.dtype)   # tipo de dato
print(t.ndim)    # nº de dimensiones
print(t.numel())  # nº total de elementos
salida realshape: torch.Size([2, 3]) dtype: torch.int64 ndim: 2 numel: 6
🔑 El error #1 de un principiante en PyTorch son las formas (shapes) que no encajan. Acostúmbrate a imprimir .shape constantemente. El 90% de los bugs se resuelven mirando qué forma tiene cada tensor.

Nota: como los números eran enteros, el dtype es int64. Las redes necesitan decimales, así que se convierten a float32:

f = t.float()   # convierte a float32
print(f.dtype)
salida realtorch.float32

4. Cambiar la forma: reshape y view

Reorganizar los mismos datos en otra forma (sin cambiar los valores):

a = torch.arange(12)        # [0, 1, 2, ..., 11]
a.reshape(3, 4)            # 3 filas x 4 columnas
a.view(2, 6)               # 2 filas x 6 columnas
a.reshape(-1, 4)           # -1 = "calcula tú esta dimensión"
salida realreshape(3,4): tensor([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) view(2,6): tensor([[ 0, 1, 2, 3, 4, 5], [ 6, 7, 8, 9, 10, 11]]) reshape(-1,4).shape: torch.Size([3, 4])

El truco del -1 es muy útil: le dices a PyTorch "déjame 4 columnas y averigua tú cuántas filas hacen falta". Con 12 elementos, deduce 3 filas. reshape y view hacen casi lo mismo; reshape es la opción segura por defecto.

5. Indexar y rebanar (slicing)

Igual que en NumPy/listas de Python, con [fila, columna]:

m = torch.tensor([[10, 20, 30],
                  [40, 50, 60]])
m[0]        # primera fila completa
m[1, 2]     # fila 1, columna 2 → un solo valor
m[:, 1]     # TODAS las filas, columna 1
m[0, :2]    # fila 0, columnas 0 y 1
salida realm[0] → tensor([10, 20, 30]) m[1, 2] → 60 m[:, 1] → tensor([20, 50]) m[0, :2] → tensor([10, 20])

El : significa "todo en esta dimensión". m[:, 1] = "todas las filas, solo la columna 1". Es la forma de extraer una columna entera.

6. Resumen

Un tensor es un array N-dimensional. Lo creas con tensor, zeros, ones, arange, rand/randn. Sus dos propiedades clave son .shape (forma) y .dtype (tipo). Lo reorganizas con reshape/view y accedes a sus partes con indexado [fila, col]. En la próxima lección haremos operaciones entre tensores: aritmética, broadcasting y la multiplicación de matrices (el corazón de toda red).