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.
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ímbolo | Qué es |
|---|---|
| (AB)ij | la casilla del resultado en la fila i, columna j |
| aik | la fila i del primero, recorrida entera |
| bkj | la columna j del segundo, recorrida entera |
| k | el í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
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.