Aquí está la maquinaria de cálculo. La aritmética elemento a elemento, el "broadcasting" (que ahorra mucho código) y la multiplicación de matrices — la operación que define a las redes neuronales.
.shape (forma) y .dtype (tipo). Lo creas con torch.tensor(), zeros, randn, etc., y lo reorganizas con reshape. Hoy usamos esos tensores para calcular.
Las operaciones + - * / se aplican posición por posición:
a = torch.tensor([1., 2., 3.])
b = torch.tensor([10., 20., 30.])
a + b # suma posición a posición
a * b # producto posición a posición (NO es matricial)
b / a
a * b es producto elemento a elemento, NO multiplicación de
matrices. Para la matricial se usa @ (lo vemos abajo). Confundirlos es un error
clásico.
El broadcasting permite operar tensores de formas diferentes "estirando" automáticamente el más pequeño. Sumar un vector a cada fila de una matriz:
M = torch.tensor([[1., 2., 3.],
[4., 5., 6.]]) # forma (2, 3)
v = torch.tensor([10., 20., 30.]) # forma (3,)
M + v # v se suma a CADA fila de M
M * 2 # un escalar se aplica a todo
z = x @ W + b): el vector de bias b se suma automáticamente a cada fila del resultado. Lo usarás todo el tiempo sin darte cuenta.
.shape de cada tensor. El broadcasting puede ser confuso al principio — es normal.
Esta es la operación de las redes neuronales (la suma ponderada de tu curso, en
forma matricial). Se usa @ o torch.matmul:
A = torch.tensor([[1., 2.],
[3., 4.]])
B = torch.tensor([[5., 6.],
[7., 8.]])
A @ B # multiplicación de matrices
[0,0] = fila0·col0 = (1·5)+(2·7) = 5 + 14 = 19 [0,1] = fila0·col1 = (1·6)+(2·8) = 6 + 16 = 22 [1,0] = fila1·col0 = (3·5)+(4·7) = 15 + 28 = 43 [1,1] = fila1·col1 = (3·6)+(4·8) = 18 + 32 = 50
Matriz por vector (una capa procesando una entrada):
x = torch.tensor([1., 2.])
A @ x
resultado[0] = fila0·x = (1·1)+(2·2) = 1 + 4 = 5 resultado[1] = fila1·x = (3·1)+(4·2) = 3 + 8 = 11
(m × n) @ (n × p), el
n del medio debe coincidir; el resultado es (m × p). Si no coinciden,
PyTorch lanza un error de forma — el más común al construir redes.
Operaciones que "colapsan" valores: suma, media, máximo…
t = torch.tensor([[1., 2., 3.],
[4., 5., 6.]])
t.sum() # suma de TODO
t.mean() # promedio de todo
t.max() # máximo de todo
Lo poderoso es el argumento dim: reducir solo a lo largo de un eje.
t.sum(dim=0) # suma por COLUMNAS (colapsa las filas)
t.sum(dim=1) # suma por FILAS (colapsa las columnas)
dim=0 (sumar bajando las FILAS, una suma por columna): columna 0: 1 + 4 = 5 columna 1: 2 + 5 = 7 columna 2: 3 + 6 = 9 → [5, 7, 9] dim=1 (sumar a lo ancho de las COLUMNAS, una suma por fila): fila 0: 1 + 2 + 3 = 6 fila 1: 4 + 5 + 6 = 15 → [6, 15]
dim indica qué dimensión desaparece. dim=0 elimina las
filas (queda un resultado por columna); dim=1 elimina las columnas (un resultado por
fila). Esto confunde al principio — la regla "dim = la que se colapsa" te salva.
argmax devuelve la posición del máximo, no el valor. Es clave para clasificación: si la red da puntuaciones [0.1, 0.8, 0.1] para [perro, gato, pájaro], argmax devuelve 1 → "la red dice que es un gato".
t.argmax() # índice del valor más grande (aplanado)
+ - * / operan elemento a elemento; * NO es multiplicación de matrices. Broadcasting estira automáticamente formas compatibles (así funciona el bias z = x @ W + b). @ es multiplicación de matrices — el corazón de cada capa de red. Las reducciones (sum, mean, argmax) con dim resumen un eje específico.
En la próxima lección: autograd — PyTorch calculará el backward por ti automáticamente.