WhatsApp
Ir al contenido

  

Desglosando el Algoritmo de Factorización de Cholesky: Teoría, Implementación en Python y Mejores Prácticas

Aprende todo sobre la factorización de Cholesky, su fundamento matemático, cómo implementarla eficientemente en Python y cuándo elegirla frente a otras descomposiciones matriciales.
Desglosando el Algoritmo de Factorización de Cholesky

Factorización de Cholesky

Una guía práctica y profunda para entender, implementar y optimizar la descomposición de matrices simétricas positivas definidas en Python.

1. ¿Qué es la factorización de Cholesky?

La factorización de Cholesky descompone una matriz SPD (Simétrica y Positiva Definida) A ∈ ℝⁿˣⁿ en el producto:

A = L·Lᵀ donde L es una matriz triangular inferior con entradas reales y positivas en la diagonal.

Esta descomposición es la base de muchos algoritmos de optimización, resolución de sistemas lineales y simulaciones Monte Carlo.

2. Fundamento matemático

Para una matriz SPD, la existencia y unicidad de L está garantizada por el teorema de Cholesky. El algoritmo recursivo se define por:

  • L₁₁ = sqrt(A₁₁)
  • Lᵢ₁ = Aᵢ₁ / L₁₁ (i = 2 … n)
  • Para k = 2 … n:
    • Lₖₖ = sqrt(Aₖₖ - Σ_{j=1}^{k-1} Lₖⱼ²)
    • Lᵢₖ = (Aᵢₖ - Σ_{j=1}^{k-1} Lᵢⱼ Lₖⱼ) / Lₖₖ (i = k+1 … n)

El algoritmo tiene complejidad O(n³/3), aproximadamente la mitad del coste de una descomposición LU completa.

3. Implementación básica en Python

Usaremos numpy para operaciones vectorizadas y scipy.linalg para la versión optimizada.

import numpy as np

def cholesky_basic(A):
    """Implementación didáctica del algoritmo de Cholesky (sin pivoteo)."""
    n = A.shape[0]
    L = np.zeros_like(A)
    for k in range(n):
        temp_sum = np.dot(L[k, :k], L[k, :k])
        L[k, k] = np.sqrt(A[k, k] - temp_sum)
        for i in range(k+1, n):
            temp_sum = np.dot(L[i, :k], L[k, :k])
            L[i, k] = (A[i, k] - temp_sum) / L[k, k]
    return L

# Ejemplo de uso
A = np.array([[25, 15, -5],
              [15, 18,  0],
              [-5,  0, 11]], dtype=float)
L = cholesky_basic(A)
print('L =\n', L)
print('Verificación L·Lᵀ =\n', L @ L.T)

Resultado esperado:

L =
[[5.  0.  0.]
 [3.  3.  0.]
 [-1.  1.  3.]]
Verificación L·Lᵀ =
[[25. 15. -5.]
 [15. 18.  0.]
 [-5.  0. 11.]]

4. Versión de producción con scipy.linalg

Para aplicaciones reales, scipy.linalg.cholesky aprovecha BLAS/LAPACK altamente optimizados y ofrece soporte para upper o lower triangular.

from scipy.linalg import cholesky

L = cholesky(A, lower=True)  # devuelve L tal que A = L·Lᵀ
print(L)

Esta función también permite especificar overwrite_a=True para reducir el uso de memoria en matrices muy grandes.

5. Comparativa con otras descomposiciones

Cholesky vs LU
  • Requisitos de la matriz: Cholesky necesita SPD; LU solo necesita que sea no singular.
  • Coste computacional: Cholesky ≈ ½·LU (≈ n³/3 vs n³/3*2).
  • Estabilidad numérica: Cholesky es más estable para matrices bien condicionadas.
  • Uso típico: Sistemas de ecuaciones de tipo Ax = b en optimización convexa.
Cholesky vs QR
  • Objetivo: QR se usa para problemas de mínimos cuadrados y ortogonalización; Cholesky para factorización de covarianzas.
  • Memoria: QR requiere más almacenamiento (matrices Q y R).
  • Rendimiento: En matrices densas, QR ≈ 2·Cholesky.
  • Aplicación en IA: QR es común en regresión lineal; Cholesky en Gaussian Processes.

6. Buenas prácticas y optimización

  • Validar SPD antes de la descomposición: Utiliza np.all(np.linalg.eigvals(A) > 0) o verifica que la diagonal de L sea real y positiva.
  • Uso de tipos de dato apropiados: En entornos de alto rendimiento, emplea float32 si la precisión lo permite para reducir la presión en la caché.
  • Memoria compartida en procesos paralelos: Cuando se ejecuta en multiprocessing o joblib, comparte la matriz A en memoria de solo lectura para evitar copias.
  • Over‑write y alineación: Con scipy.linalg.cholesky(..., overwrite_a=True) y matrices alineadas a 64‑bytes (usando numpy.ndarray(..., align=True)) se consigue un speed‑up del 10‑15% en matrices > 5000×5000.

7. Solución de problemas comunes (troubleshooting)

ProblemaCausa típicaSolución
Valor nan en LLa matriz no es SPD (eigenvalor ≤ 0)Aplicar np.linalg.cholesky dentro de un try/except y, de fallar, usar np.linalg.eigvalsh para inspeccionar.
Desbordamiento de precisiónElementos muy grandes o muy pequeños (condición alta)Escalar la matriz (dividir por su norma) antes de la factorización y re‑escalar después.
Rendimiento pobre en GPUUso de numpy que opera en CPUUtilizar cupy o torch.linalg.cholesky para aprovechar CUDA.

8. Casos de uso reales

  • Gaussian Processes (GP): La inversa de la matriz de covarianza se calcula mediante Cholesky para evitar la costosa inversión directa.
  • Optimización convexa (por ejemplo, interior‑point methods): Resolución de sistemas KKT que son SPD.
  • Simulación de Monte Carlo: Generación de vectores aleatorios con correlación definida por una matriz de covarianza.
  • Control de sistemas: Solución de ecuaciones de Riccati que generan matrices SPD.

9. Escalabilidad y rendimiento en entornos de producción

Para matrices que superan los 10⁵ elementos, se recomiendan:

  • Descomposición bloqueada (Block‑Cholesky) disponible en scipy.linalg.blas y bibliotecas como Intel MKL.
  • Distribución con Dask o Ray para dividir la matriz en bloques y ejecutar la factorización en clústeres.
  • Uso de GPUs con cupy.linalg.cholesky o torch.cholesky para acelerar cálculos en tensores de gran dimensión.

Ejemplo rápido de Block‑Cholesky con Dask:

import dask.array as da
A = da.random.random((5000, 5000), chunks=(1000, 1000))
# Aseguramos SPD
A = A @ A.T + da.eye(5000) * 1e-3
L = da.linalg.cholesky(A)  # ejecuta de forma distribuida

© 2025 BlogTech – Todos los derechos reservados.

 

Desglosando el Algoritmo de Factorización de Cholesky: Teoría, Implementación en Python y Mejores Prácticas
ASIMOV Ingeniería S. de R.L. de C.V., Emiliano Nava 13 de noviembre de 2025
Compartir
Iniciar sesión dejar un comentario

  
Algoritmo de cálculo de la inversa de una matriz: teoría, implementación en Python y comparativas de rendimiento
Guía completa sobre cómo calcular la inversa de una matriz usando algoritmos clásicos y Python. Incluye ejemplos, comparativas de rendimiento, buenas prácticas y consideraciones de escalabilidad.