Algoritmos de Reducción de Dimensionalidad
Descubre cuándo y cómo aplicar cada técnica, compara sus características y ejecuta ejemplos listos para producción en Python.
¿Por qué reducir la dimensionalidad?
Los conjuntos de datos modernos pueden contener cientos o miles de variables. Esto genera problemas como:
- Curse of dimensionality – escasez de datos representativos en espacios de alta dimensión.
- Sobre‑ajuste de modelos de Machine Learning.
- Alto coste computacional y de memoria.
- Dificultad para visualizar patrones.
Reducir la dimensionalidad permite compactar la información relevante preservando la estructura subyacente, facilitando la visualización, acelerando entrenamientos y mejorando la generalización.
Comparativa rápida de los algoritmos más usados
Algoritmo
- PCA (Análisis de Componentes Principales)
- t‑SNE (t‑Distributed Stochastic Neighbor Embedding)
- UMAP (Uniform Manifold Approximation and Projection)
- LDA (Linear Discriminant Analysis)
- Autoencoders (Redes Neuronales)
Características clave
- Linealidad: Solo PCA y LDA son lineales.
- Escalabilidad: PCA, LDA y Autoencoders escalan bien con
n_samplesyn_features. t‑SNE y UMAP son más costosos pero manejables conapprox‑knn. - Preservación de la topología: t‑SNE y UMAP sobresalen en mantener relaciones locales.
- Uso para clasificación: LDA incorpora etiquetas; Autoencoders pueden ser semi‑supervisados.
- Interpretabilidad: PCA y LDA ofrecen componentes interpretables; los demás son “cajas negras”.
1. PCA – Análisis de Componentes Principales
Reduce la dimensionalidad proyectando los datos sobre los vectores propios de la matriz de covarianza. Es rápido, determinista y útil para pre‑procesado.
Implementación en Python (scikit‑learn)
import numpy as np
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
# Cargar y escalar datos
X, y = load_iris(return_X_y=True)
X_std = StandardScaler().fit_transform(X)
# PCA a 2 componentes
pca = PCA(n_components=2, random_state=42)
X_pca = pca.fit_transform(X_std)
print('Explained variance ratio:', pca.explained_variance_ratio_)
Mejores prácticas:
- Escalar siempre los datos antes de aplicar PCA.
- Inspeccionar
explained_variance_ratio_para decidir cuántas componentes conservar. - Para datasets muy grandes, usar
IncrementalPCAoTruncatedSVD(para matrices dispersas).
2. t‑SNE – Visualización no lineal
Mapea datos de alta dimensión a 2‑3 dimensiones preservando relaciones locales mediante una distribución de probabilidad basada en distancias.
Implementación en Python (scikit‑learn)
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
# Usar los datos escalados del ejemplo anterior
tsne = TSNE(n_components=2, perplexity=30, learning_rate=200, n_iter=1000, random_state=42)
X_tsne = tsne.fit_transform(X_std)
plt.figure(figsize=(8,6))
scatter = plt.scatter(X_tsne[:,0], X_tsne[:,1], c=y, cmap='viridis', s=60)
plt.legend(*scatter.legend_elements(), title='Clases')
plt.title('t‑SNE de Iris')
plt.show()
Tips de rendimiento:
- Reducir dimensionalidad preliminarmente con PCA a ~50 componentes antes de t‑SNE para acelerar el proceso.
- Ajustar
perplexityentre 5‑50 según el número de muestras. - Para >100k puntos, considerar
openTSNEoMulticore‑TSNEque aprovechan paralelismo.
3. UMAP – Alternativa moderna a t‑SNE
Construye un grafo de vecinos aproximado y optimiza una función de pérdida que preserva tanto la topología local como la global. Generalmente más rápido y con mejor preservación de la estructura global.
Implementación en Python (umap‑learn)
import umap
# Opcional: pre‑reducir con PCA a 50 dimensiones
pca_50 = PCA(n_components=50, random_state=42).fit_transform(X_std)
reducer = umap.UMAP(n_neighbors=15, min_dist=0.1, n_components=2, random_state=42)
X_umap = reducer.fit_transform(pca_50)
plt.scatter(X_umap[:,0], X_umap[:,1], c=y, cmap='plasma', s=50)
plt.title('UMAP de Iris (post‑PCA)')
plt.show()
Comparación clave con t‑SNE:
- UMAP suele ser 3‑5× más rápido.
- Mantiene mejor la estructura global, útil para clustering posterior.
- Permite usar
transform()en nuevos datos sin volver a entrenar.
4. LDA – Reducción supervisada
Busca maximizar la separación entre clases mediante proyecciones lineales. Ideal cuando se dispone de etiquetas y se necesita una representación discriminativa.
Implementación en Python (scikit‑learn)
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
lda = LDA(n_components=2)
X_lda = lda.fit_transform(X_std, y)
plt.scatter(X_lda[:,0], X_lda[:,1], c=y, cmap='coolwarm', s=60)
plt.title('LDA de Iris')
plt.show()
Ventajas: Reduce dimensionalidad y mejora la clasificación simultáneamente. Limitación: El número máximo de componentes es n_classes - 1.
5. Autoencoders – Reducción no lineal basada en redes neuronales
Arquitectura de codificador‑decodificador que aprende una representación latente compacta. Muy potente para datos complejos como imágenes o series temporales.
Implementación con TensorFlow/Keras
import tensorflow as tf
from tensorflow.keras import layers, models
# Dataset de ejemplo: MNIST (784 dimensiones)
(x_train, _), (x_test, _) = tf.keras.datasets.mnist.load_data()
X = np.concatenate([x_train, x_test]) / 255.0
X = X.reshape((X.shape[0], -1)) # flatten
input_dim = X.shape[1]
latent_dim = 32
# Encoder
inputs = layers.Input(shape=(input_dim,))
encoded = layers.Dense(128, activation='relu')(inputs)
encoded = layers.Dense(64, activation='relu')(encoded)
latent = layers.Dense(latent_dim, activation='relu')(encoded)
# Decoder
decoded = layers.Dense(64, activation='relu')(latent)
decoded = layers.Dense(128, activation='relu')(decoded)
outputs = layers.Dense(input_dim, activation='sigmoid')(decoded)
autoencoder = models.Model(inputs, outputs)
autoencoder.compile(optimizer='adam', loss='mse')
autoencoder.fit(X, X, epochs=30, batch_size=256, shuffle=True, validation_split=0.1)
# Extraer la representación latente
encoder = models.Model(inputs, latent)
X_latent = encoder.predict(X)
print('Latent shape:', X_latent.shape)
Consejos de producción:
- Normalizar los datos a [0,1] o [-1,1] según la activación de salida.
- Usar regularización L1/L2 o dropout para evitar sobre‑ajuste.
- Para datasets muy grandes, entrenar con
tf.datapipelines y GPU.
Resolución de Problemas y Buenas Prácticas
Problema: "Componentes con varianza casi nula" (PCA)
Si la suma acumulada de explained_variance_ratio_ se estabiliza antes de alcanzar el número deseado de componentes, reduzca n_components o aplique StandardScaler nuevamente.
Problema: "t‑SNE se queda colgado"
Esto ocurre por perplexity demasiado alta o número de iteraciones insuficiente. Reduzca perplexity y aumente n_iter. Verifique que los datos no tengan valores NaN.
Problema: "UMAP produce clusters erróneos"
Puede deberse a un n_neighbors muy bajo (sobre‑ajuste local) o a datos sin escalar. Normalice y experimente con min_dist entre 0.0‑0.5.
Seguridad y privacidad
Al aplicar reducción de dimensionalidad a datos sensibles, recuerde que los componentes pueden revelar información estadística. Considere técnicas de differential privacy como añadir ruido gaussiano a la matriz de covarianza antes de PCA.
Escalabilidad
Para millones de filas:
- PCA →
IncrementalPCA(batch‑wise) oRandomizedPCA. - t‑SNE →
openTSNEcon backend multihilo. - UMAP →
n_jobs=-1ydensmap=Truepara acelerar. - Autoencoders → entrenar en GPU/TPU.
Conclusión
La reducción de dimensionalidad es una herramienta esencial en el flujo de trabajo de datos. Elegir el algoritmo correcto depende de la naturaleza del problema (lineal vs no lineal, supervisado vs no supervisado), la escala del dataset y los requisitos de interpretabilidad.
Con los fragmentos de código presentados, puedes integrar rápidamente estas técnicas en pipelines de scikit‑learn, TensorFlow o PyTorch, y optimizarlas para producción con buenas prácticas de pre‑procesado, paralelismo y control de calidad.
Algoritmos de Reducción de Dimensionalidad: Conceptos, Comparativas y Ejemplos Prácticos en Python