Capítulo 5 de 21 11 secciones 7 min

Compartir

Multiplicar matrices, y qué está calculando de verdad

Por qué la multiplicación de matrices es esa y no la obvia, cómo leer las formas de un vistazo, y por qué el orden sí importa.

Multiplicar dos matrices no es multiplicar casilla con casilla: cada casilla del resultado es el producto punto de una fila del primero con una columna del segundo. Por eso (n×d) por (d×k) da (n×k), y por eso el orden importa: AB casi nunca es BA.

La operación que parece rara hasta que ves para qué sirve 🌸

Multiplicar matrices es lo que más gente abandona en el colegio, porque te lo enseñan como un procedimiento sin decirte para qué. Así que empecemos al revés: primero para qué sirve, y después cómo.

Volvemos a abrir el archivo

Cada capítulo arranca de cero, así que estas líneas se repiten. Son las mismas del capítulo 1 y las vas a ver en todos.

import pandas as pd
import numpy as np

df = pd.read_csv('ventas-miss-yera.csv')
for c in ('unidades', 'monto', 'satisfaccion'):
    df[c] = pd.to_numeric(df[c], errors='coerce')
X = df[['unidades', 'monto', 'satisfaccion']].dropna().to_numpy()
print('X.shape:', X.shape)
X.shape: (2238, 3)

Para qué sirve: dos escenarios a la vez

En el capítulo 4 pusiste un juego de pesos y sacaste una predicción por venta. Ahora quieres dos juegos: el tuyo, y otro donde solo importan las unidades y la satisfacción.

W = np.array([[12.0,   1.0],
              [ 0.35,  0.0],
              [40.0, 100.0]])
print('W.shape:', W.shape)

S = X @ W
print('S.shape:', S.shape)
print(np.round(S[:3], 2))
W.shape: (3, 2)
S.shape: (2238, 2)
[[448.13 410.  ]
 [423.72 310.  ]
 [250.19 113.  ]]

2.238 filas por 2 escenarios. La primera columna es el escenario de siempre y la segunda es el nuevo, y salieron los dos en una línea.

Eso es multiplicar matrices: muchos productos punto de golpe. Cada columna de W es un juego de pesos, cada fila de X es una venta, y cada casilla del resultado es el producto punto de una con otra.

(AB)ij=k=1naikbkj

cada casilla del resultado es el producto punto de una fila del primero con una columna del segundo, y por eso el número de columnas del primero tiene que ser el de filas del segundo

SímboloQué es
(AB)ijla casilla del resultado en la fila i, columna j
aikla fila i del primero, recorrida entera
bkjla columna j del segundo, recorrida entera
kel índice que barre las dos a la vez y después desaparece

La regla de las formas, que es lo único que hay que memorizar

(n×d)·(d×k)=(n×k)

la d del medio se gasta en la suma y no aparece en el resultado, así que si las dos des no coinciden la multiplicación no existe

Tapa con el dedo los dos números del medio. Lo que te queda es la forma del resultado. Si los dos que tapaste no son iguales, la operación no existe.

Con nuestro caso: (2238, 3) por (3, 2) da (2238, 2). El 3 se gastó.

No es elemento a elemento, y aquí se ve

A = X[:2][:, [0, 2]]
B = X[2:4][:, [0, 2]]
print('A ='); print(A)
print('B ='); print(B)
print('A * B ='); print(A * B)
print('A @ B ='); print(A @ B)
A =
[[10.  4.]
 [10.  3.]]
B =
[[13.  1.]
 [ 3.  4.]]
A * B =
[[130.   4.]
 [ 30.  12.]]
A @ B =
[[142.  26.]
 [139.  22.]]

Mira la primera casilla de cada uno. Con * sale 130, que es 10 por 13 y nada más. Con @ sale 142, que es 10 por 13 más 4 por 3.

El * es elemento a elemento y pide que las dos tengan la misma forma. El @ es el producto de matrices y pide que encajen. Confundirlos es el error número uno, y el peor de todos es cuando las dos formas resultan compatibles con las dos operaciones: ahí no hay error, hay un número equivocado.

El orden importa

W @ X
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2238 is different from 2)

X @ W funciona y W @ X no. Con vectores el orden daba igual; acá no.

Y cuando las dos direcciones sí funcionan, tampoco dan lo mismo. Es la diferencia entre "aplica estos pesos a estos datos" y "aplica estos datos a esos pesos", que ni siquiera significa nada.

Por qué esta operación y no otra

La pregunta honesta es: si multiplicar casilla con casilla es más fácil, ¿por qué la de verdad es esta?

Porque esta es la que encadena transformaciones. Si A convierte tus datos en otra cosa y B convierte esa otra cosa en una tercera, entonces A @ B es la que hace las dos de una vez.

Eso es exactamente lo que es una red neuronal: una capa multiplica por una matriz, la siguiente multiplica por otra, y la red entera es esa cadena. Cuando llegues a deep learning y veas W1 @ W2 @ W3, esto es lo que significa 🐣

Lo que te llevas

  • Cada casilla del resultado es un producto punto de una fila con una columna.
  • La regla de las formas: tapa los dos del medio, lee lo que queda.
  • * es elemento a elemento y @ es matricial. No son lo mismo ni por casualidad.
  • El orden importa: AB casi nunca es BA.
  • Multiplicar matrices es encadenar transformaciones, y eso es una red por dentro.

Comprueba que se entendió

Comprueba que lo tienes

Multiplicas A de forma (2238, 3) por B de forma (3, 5). ¿Qué forma tiene el resultado?

  • (2238, 5)
  • (3, 3)
  • (2238, 3), la misma que A
  • Da error, porque las formas son distintas

Ejercicios

1. Una casilla a mano

Saca la casilla de arriba a la izquierda tú mismo.

A = X[:2][:, [0, 2]]
B = X[2:4][:, [0, 2]]

a_mano = A[0, 0] * B[0, 0] + A[0, 1] * B[1, 0]
print('a mano :', a_mano)
print('numpy  :', (A @ B)[0, 0])
a mano : 142.0
numpy  : 142.0

Fila 0 de A contra columna 0 de B. Si haces esto una vez con papel, la fórmula de la sigma deja de dar miedo para siempre.

2. Comprueba que la fila 0 del resultado es lo de siempre

El producto de matrices no inventó nada nuevo.

W = np.array([[12.0,   1.0],
              [ 0.35,  0.0],
              [40.0, 100.0]])
S = X @ W
print('con matrices :', np.round(S[0], 2))
print('a mano col 0 :', round(float(X[0] @ W[:, 0]), 2))
print('a mano col 1 :', round(float(X[0] @ W[:, 1]), 2))
con matrices : [448.13 410.  ]
a mano col 0 : 448.13
a mano col 1 : 410.0

Cada casilla es el producto punto que ya sabías hacer. La multiplicación de matrices solo los organiza.

3. El error de forma, provócalo tú

Antes de correrlo, di en voz alta si va a funcionar.

W = np.array([[12.0,   1.0],
              [ 0.35,  0.0],
              [40.0, 100.0]])
print('X.shape', X.shape, ' W.shape', W.shape)
print('X @ W ->', (X @ W).shape)
X.shape (2238, 3)  W.shape (3, 2)
X @ W -> (2238, 2)

Y ahora al revés:

W @ X
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2238 is different from 2)

Cuando este error te salga en un proyecto, no adivines: imprime las dos formas y tapa los del medio con el dedo. En treinta segundos sabes cuál de las dos hay que trasponer, y trasponer es el capítulo que viene.

Preguntas frecuentes

¿Cómo se multiplican dos matrices?

Cada número del resultado es el producto punto de una fila de la primera con una columna de la segunda. Solo se puede si las columnas de la primera son tantas como las filas de la segunda.

¿Qué es el producto de matrices?

La operación de arriba, y no es multiplicar número a número. Esa otra existe, se llama producto elemento a elemento, y confundirlas es de los errores que no dan error.

¿Qué es el álgebra lineal?

La parte de la matemática que trabaja con vectores y matrices. Es la que hay debajo de casi todo el machine learning, y hace falta bastante menos de la que se enseña en la universidad.

¿La multiplicación de matrices es conmutativa?

No. A por B casi nunca es igual a B por A, y muchas veces una de las dos ni siquiera se puede calcular.

Practica este capítulo 📓

Todo el código de arriba en un cuaderno que corre de principio a fin, y los ejercicios con una celda vacía para que los hagas tú. Se abre en Google Colab de un clic y no hay que instalar nada. Donde veas %%revisa, escribe tu respuesta y el cuaderno te dice si te salió.

¿Prefieres trabajar en tu máquina? Bájate el cuaderno de práctica o el de soluciones. Todos están también en github.com/soymissyera/MissYeraEjercicios.

¿Le sirve a alguien que conoces?

Pásale el libro. Es gratis, está entero y no pide registro 🐣

Instagram y TikTok no dejan compartir enlaces desde la web: esos dos copian la URL para que la pegues en tu historia.

¿Tienes alguna duda o consulta?