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.
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.
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 (clave para clasificación: "¿qué clase ganó?"):
t.argmax() # índice del valor más grande (aplanado)
+ - * / operan elemento a elemento; broadcasting estira formas
compatibles (así se suma el bias); @ es la multiplicación de matrices (el corazón de
las capas); las reducciones (sum, mean,
argmax) con dim resumen a lo largo de un eje. Con esto ya puedes calcular
el forward de una red a mano en PyTorch. En la próxima lección llega la magia: autograd
calculará el backward por ti.