38 · Álgebra lineal con np.linalg
Resuelve sistemas lineales, descompón matrices y calcula normas — las operaciones fundamentales de álgebra lineal detrás de la regresión lineal, PCA y todo optimizador basado en gradientes.
`np.linalg` es la puerta de NumPy a LAPACK — una biblioteca Fortran probada en batalla que ha sido el motor del álgebra lineal numérica durante 50 años. Tres operaciones cubren casi todos los casos de uso de ML: **`solve(A, b)`** para sistemas lineales (ecuaciones normales de regresión, cualquier `Ax = b`), **`eig(A)`** para eigendescomposición (análisis de covarianza, algoritmos de grafos), y **`svd(A)`** para descomposición en valores singulares (PCA, aproximación de bajo rango, pseudo-inversa).
Sin esto:
Sin `np.linalg`, implementar regresión lineal desde cero requiere o bien un descenso de gradiente con bucle, o derivar la forma cerrada de la ecuación normal a mano e implementar `inv(X.T @ X) @ X.T @ y` — lo cual es numéricamente frágil. `np.linalg.solve` y `np.linalg.lstsq` manejan los casos extremos numéricos (matrices casi singulares, sistemas sobredeterminados) que el enfoque manual con inversa silenciosamente falla.
El módulo np.linalg de Python es un wrapper delgado sobre rutinas LAPACK. Las funciones clave y cuándo usar cada una:
np.linalg.solve(A, b)— resuelveAx = bparaAcuadrada. Prefiere esto sobrenp.linalg.inv(A) @ b:solveusa factorización LU internamente, lo que es más rápido y evita la amplificación numérica de errores que viene con calcular explícitamenteA⁻¹.np.linalg.lstsq(A, b)— solución de mínimos cuadrados cuandoAno es cuadrada (sistemas sobredeterminados). Esto es lo quesklearn.LinearRegressionusa internamente.np.linalg.eig(A)— devuelve(eigenvalores, eigenvectores). Para matrices simétricas, prefierenp.linalg.eighque explota la simetría para mayor velocidad y garantiza salida real.np.linalg.svd(A)— devuelve(U, s, Vt)dondeA = U @ np.diag(s) @ Vt. SVD existe para cualquier matriz (a diferencia de la eigendescomposición que requiere matrices cuadradas).np.linalg.norm(v)— por defecto la norma euclídea (L2). Pasaord=1para L1,ord=np.infpara la norma máx.np.linalg.det(A)— determinante; distinto de cero significa rango completo.np.linalg.matrix_rank(A)— rango numérico (usa SVD internamente).
Python (in browser)
`np.linalg.solve` es preferible a `inv(A) @ b` porque calcular la inversa amplifica los errores de punto flotante — para un sistema 2×2 bien condicionado la diferencia es despreciable, pero para sistemas grandes o mal condicionados `solve` puede ser órdenes de magnitud más preciso. El residual `norm(Ax - b)` es la forma estándar de verificar una solución.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
La propiedad definitoria de un eigenvector: `A @ v == lambda * v` — la matriz solo escala el vector, nunca lo rota. Para una matriz de covarianza, los eigenvectores son los componentes principales (direcciones de máxima varianza) y los eigenvalores te dicen cuánta varianza explica cada componente. Este es el núcleo matemático de PCA.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
`full_matrices=False` devuelve la SVD 'delgada' o 'económica' — `U` tiene shape `(m, k)` en lugar de `(m, m)` donde `k = min(m, n)`. Los valores singulares en `s` están en orden descendente; truncar a los `k` superiores da la mejor aproximación de rango `k` a `A` en la norma de Frobenius. PCA de una matriz de datos centrada es exactamente esto: los vectores singulares derechos `Vt` son los componentes principales.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
`np.linalg.lstsq` usa SVD internamente para manejar matrices de diseño singulares o casi singulares de forma elegante. Cuando usas `sklearn.LinearRegression`, llama a `dgelsd` de LAPACK — el mismo algoritmo. Entender esta conexión significa que puedes diagnosticar advertencias de deficiencia de rango ('La matriz está cerca de ser singular'), elegir regularización (`Ridge` añade `lambda * I` para hacer `X.T @ X` invertible) e interpretar `rcond` (el umbral numérico por debajo del cual los valores singulares se tratan como cero).
¿Qué devuelve `np.linalg.norm(v)` por defecto para un vector 1D `v`?
La lección 19 de MML cubre eigenvalores y eigenvectores — los objetos matemáticos que `np.linalg.eig` y `np.linalg.eigh` calculan. La ecuación definitoria `Av = λv` (una matriz escala ciertos vectores sin rotarlos) es la base de PCA (eigenvectores de la matriz de covarianza), la teoría espectral de grafos y el análisis de cadenas de Markov. La lección 22 cubre SVD — la generalización de la eigendescomposición a matrices no cuadradas que impulsa PCA, la pseudo-inversa y la aproximación de bajo rango.
- `np.linalg.solve(A, b)` resuelve `Ax = b` y siempre es preferible a `inv(A) @ b` — es más rápido y numéricamente más estable.
- `np.linalg.eigh(A)` devuelve `(eigenvalores, eigenvectores)` para matrices simétricas. Cada eigenvector satisface `A @ v == lambda * v`.
- `np.linalg.svd(A, full_matrices=False)` devuelve `(U, s, Vt)`. Los valores singulares en `s` están en orden descendente; truncar a los `k` superiores da la mejor aproximación de rango `k`.
- `np.linalg.lstsq(A, b)` resuelve el problema de mínimos cuadrados sobredeterminado — la matemática detrás de `sklearn.LinearRegression`.
- `np.linalg.norm(v)` por defecto calcula la norma L2 (euclídea). Pasa `ord=1` para L1 y `ord=np.inf` para la norma máx.
PCA es `np.linalg.svd` (o `np.linalg.eigh`) sobre una matriz de datos centrada — los `k` vectores singulares derechos superiores son los componentes principales. Los mínimos cuadrados ordinarios (regresión lineal) son `np.linalg.lstsq`. El recorte de gradientes es `np.linalg.norm(grad)`. La similitud coseno es `(a @ b) / (norm(a) * norm(b))`. Toda factorización matricial de sistemas de recomendación es SVD. El proceso de Gram–Schmidt (factorización QR, accesible a través de `np.linalg.qr`) sustenta las implementaciones numéricamente estables tanto del descenso de gradientes como de los mínimos cuadrados.
Si lo quitas: Sin `np.linalg`, implementar PCA desde cero requeriría codificar la ortogonalización de Gram–Schmidt, el algoritmo QR para eigenvalores y Golub–Reinsch para SVD — todos los cuales tardaron décadas de investigación en estabilizarse numéricamente. `np.linalg` te da implementaciones de calidad de producción de todos estos en una importación, permitiéndote enfocarte en el problema de ML en lugar del análisis numérico.