Algoritmo PCA con Álgebra Lineal: Guía Completa y Ejemplos en Python
Introducción
El Análisis de Componentes Principales (PCA) es una técnica estadística y de aprendizaje automático utilizada para reducir la dimensionalidad de datos manteniendo la mayor parte de su varianza. Su fundamento se basa en conceptos de álgebra lineal como vectores, matrices, valores propios y vectores propios.
En este artículo exploraremos:
- Los conceptos matemáticos que sustentan PCA.
- El algoritmo paso a paso.
- Implementaciones en
NumPy,PandasyScikit‑learn. - Un caso práctico con el conjunto de datos Iris.
- Comparación con otras técnicas de reducción de dimensionalidad.
- Buenas prácticas, optimización y troubleshooting.
Fundamentos de Álgebra Lineal
Para comprender PCA es esencial dominar los siguientes conceptos:
- Matriz de datos (X): Cada fila representa una observación, cada columna una variable.
- Centralización: Restar la media de cada columna para que el conjunto tenga media cero.
- Matriz de covarianza (Σ): Σ = (1 / (n‑1))·XᵀX, donde
nes el número de observaciones. - Descomposición en valores propios: Σv = λv, donde λ es el valor propio (varianza explicada) y v el vector propio (dirección del componente).
Los vectores propios forman una base ortogonal que permite proyectar los datos originales en un espacio de menor dimensionalidad.
Algoritmo PCA paso a paso
- Construir la matriz de datos
X(n×p). - Centralizar:
X_centered = X - mean(X, axis=0). - Escalar (opcional): dividir por la desviación estándar para datos con distintas unidades.
- Calcular la matriz de covarianza
Σo, en grandes conjuntos, usar la descomposición SVD directamente. - Obtener valores y vectores propios de
Σ.- Ordenar los valores propios de mayor a menor.
- Seleccionar los k vectores propios correspondientes (componentes principales).
- Proyección:
Z = X_centered · W_k, dondeW_kcontiene los k vectores propios seleccionados.
Implementación en Python
A continuación se presentan tres enfoques para ejecutar PCA en Python.
1️⃣ Implementación manual con NumPy
import numpy as np
import pandas as pd
# Cargar datos (ejemplo Iris)
from sklearn.datasets import load_iris
data = load_iris()
X = pd.DataFrame(data=data.data, columns=data.feature_names)
# 1. Centralizar
def center(X):
return X - X.mean(axis=0)
X_centered = center(X)
# 2. Covarianza
cov_matrix = np.cov(X_centered, rowvar=False)
# 3. Valores y vectores propios
eig_vals, eig_vecs = np.linalg.eigh(cov_matrix) # eigh para matrices simétricas
# 4. Ordenar de mayor a menor
desc_idx = np.argsort(eig_vals)[::-1]
eig_vals = eig_vals[desc_idx]
eig_vecs = eig_vecs[:, desc_idx]
# 5. Seleccionar k componentes (p.ej. k=2)
k = 2
W = eig_vecs[:, :k]
# 6. Proyección
Z = np.dot(X_centered, W)
print('Shape of projected data:', Z.shape)
Esta versión muestra cada paso matemático, ideal para aprender y depurar.
2️⃣ Usando scikit‑learn (más rápido y con utilities)
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
# Escalado estándar (recomendado)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
pca = PCA(n_components=2, svd_solver='full')
Z_sklearn = pca.fit_transform(X_scaled)
print('Explained variance ratio:', pca.explained_variance_ratio_)
print('Components shape:', pca.components_.shape)
El atributo explained_variance_ratio_ indica la proporción de varianza retenida por cada componente.
3️⃣ Integración con Pandas para visualizaciones rápidas
import matplotlib.pyplot as plt
import seaborn as sns
# DataFrame con los dos componentes
df_pca = pd.DataFrame(Z_sklearn, columns=['PC1', 'PC2'])
df_pca['target'] = data.target
sns.scatterplot(data=df_pca, x='PC1', y='PC2', hue='target', palette='deep')
plt.title('PCA de Iris (2 componentes)')
plt.show()
Comparativa: PCA vs t‑SNE vs UMAP
PCA
- Lineal, basado en varianza.
- Escalable a millones de filas (SVD distribuido).
- Interpretación directa: cada componente es combinación lineal de variables originales.
- Rápido (O(p³) para p variables, pero con SVD está optimizado).
t‑SNE / UMAP
- No lineales, preservan relaciones locales (t‑SNE) o topología global (UMAP).
- Costosos (O(n²) para t‑SNE, O(n log n) para UMAP).
- Difíciles de interpretar; útiles para visualización, no para extracción de características.
- Requieren ajuste cuidadoso de hiper‑parámetros (perplexity, n_neighbors).
Buenas prácticas, rendimiento y troubleshooting
Escalado y normalización
Si las variables tienen unidades diferentes, el componente principal estará dominado por la variable con mayor varianza. Use StandardScaler o MinMaxScaler antes de aplicar PCA.
Selección del número de componentes
- Criterio de varianza acumulada: mantenga k componentes que expliquen ≥ 90 % de la varianza.
- Codo (elbow) en el gráfico de valores propios.
- Cross‑validation con
PCA + modelopara validar la mejora del rendimiento.
Problemas comunes
| Problema | Causa | Solución |
|---|---|---|
| Componentes NaN | Datos con valores faltantes | Imputar antes de centrar (SimpleImputer) |
| Varianza explicada muy baja | Escala incorrecta o datos muy ruidosos | Normalizar y aplicar filtrado de ruido (PCA robusto) |
| Rendimiento lento con > 10⁶ filas | Descomposición directa de la covarianza | Usar IncrementalPCA o SVD aleatorio (TruncatedSVD) |
Optimización para big data
- IncrementalPCA: procesa bloques de datos en memoria limitada.
- Randomized SVD (
sklearn.utils.extmath.randomized_svd) para acelerar la descomposición. - Implementaciones distribuidas:
spark.ml.feature.PCAodask‑ml.decomposition.PCA.
Conclusión
El PCA sigue siendo la herramienta de referencia para la reducción lineal de dimensionalidad gracias a su solidez matemática, velocidad y facilidad de interpretación. Dominar su base algebraica permite aplicar variantes avanzadas (Kernel‑PCA, Sparse‑PCA) y combinarlo con pipelines de machine learning de forma segura.
Implementar PCA paso a paso con NumPy brinda una visión profunda, mientras que scikit‑learn simplifica la puesta en producción y la integración con procesos de validación cruzada.
Algoritmo PCA con Álgebra Lineal: Guía Completa y Ejemplos en Python