Saltar a contenido

Extracción de características

1 Extracción vs. selección

Mientras la selección elige un subconjunto de las variables originales sin modificarlas, la extracción crea representaciones completamente nuevas a partir de los datos crudos. Es el paso que convierte texto, imágenes o series temporales en vectores numéricos que un modelo puede procesar.

Nota

¿Cuándo necesitas extracción? Cuando tus datos no están en formato tabular (una fila por observación, una columna por variable). El texto, las imágenes y el audio necesitan un paso de transformación antes de poder alimentar un modelo.

2 Para texto: TF-IDF

El TF-IDF (Term Frequency - Inverse Document Frequency) es la técnica más clásica para convertir documentos de texto en vectores numéricos. Mide cuán importante es una palabra para un documento específico dentro de un corpus completo.

Nota

Antes de TF-IDF. El texto necesita un paso de limpieza y normalización (stop words, stemming, tokenización). Consulta el capítulo de preprocesamiento de texto para el pipeline completo.

2.1 El punto de partida: matriz palabra-documento

El paso previo es contar: se construye una matriz donde cada fila es una palabra del vocabulario, cada columna es un documento y cada celda es la frecuencia de esa palabra en ese documento. Cada fila describe el perfil de una palabra en el corpus; cada columna es ya el vector numérico de un documento. Esta matriz de conteos es lo que calcula CountVectorizer antes de ponderar.

Mini-ejemplo con tres documentos cortos y vocabulario \([\text{datos}, \text{película}]\):

Palabra Entretenimiento Economía Aprendizaje automático
datos \(1\) \(12\) \(18\)
película \(3\) \(8\) \(2\)

Así, \(v_{\text{datos}}=[1,12,18]\) y \(v_{\text{película}}=[3,8,2]\); por columnas, \(v_{\text{economía}}=[12,8]\) y \(v_{\text{ML}}=[18,2]\). El problema de quedarse aquí es que la frecuencia cruda premia documentos largos y palabras genéricas. TF-IDF corrige eso multiplicando la frecuencia en el documento por la rareza del término en el corpus.

2.2 Fórmula

\[ \text{TF-IDF}(t, d) = \text{TF}(t, d) \times \log\left(\frac{N}{\text{DF}(t)}\right) \]
  • TF (Term Frequency): frecuencia del término \(t\) en el documento \(d\).
  • DF (Document Frequency): número de documentos que contienen el término \(t\).
  • N: total de documentos en el corpus.

Intuición: una palabra aparece mucho en un documento particular (TF alto) pero rara vez en otros documentos (DF bajo) → es una palabra importante y discriminativa para ese documento.

2.3 Ejemplo completo

from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd

docs = [
    "el gato duerme en el sofá",
    "el perro ladra en el jardín",
    "el gato ladra en el jardín",
    "el perro duerme en la cama"
]

vectorizer = TfidfVectorizer()
X_tfidf = vectorizer.fit_transform(docs)

# Visualizar como DataFrame
df_tfidf = pd.DataFrame(
    X_tfidf.toarray(),
    columns=vectorizer.get_feature_names_out(),
    labels=[f"Doc {i}" for i in range(len(docs))]
)
print(df_tfidf.round(3))

2.4 Parámetros importantes

vectorizer = TfidfVectorizer(
    max_features=1000,     # Máximo 1000 palabras
    min_df=2,              # Aparecer en al menos 2 documentos
    max_df=0.95,           # No aparecer en más del 95% de documentos
    ngram_range=(1, 2),    # Unigramas + bigramas ("machine learning")
    stop_words='spanish'   # Eliminar palabras vacías
)

Tip

TF-IDF vs. CountVectorizer: CountVectorizer cuenta ocurrencias crudas. TF-IDF pondera por rareza. Para la mayoría de tareas de clasificación de texto, TF-IDF funciona mejor que conteo simple.

2.5 Limitaciones

  • Saca del vocabulario: palabras fuera del vocabulario conocido se ignoran.
  • No captura semántica: “coche” y “automóvil” se tratan como palabras completamente distintas.
  • Alta dimensionalidad: un vocabulario de 50.000 palabras genera vectores de 50.000 dimensiones.

Para superar estas limitaciones, existen los embeddings de palabras (Word2Vec, GloVe, BERT), que representan palabras como vectores densos de baja dimensionalidad donde palabras similares están cerca.

3 Para imágenes: puntos clave

En visión por computadora, los puntos clave (keypoints) son regiones interesantes de una imagen (esquinas, bordes, texturas) que se pueden describir de forma compacta y robusta.

3.1 SIFT (Scale-Invariant Feature Transform)

SIFT detecta puntos clave invariantes a escala, rotación e iluminación:

import cv2
import numpy as np

# Cargar imagen y detectar puntos clave
image = cv2.imread('foto.jpg', cv2.IMREAD_GRAYSCALE)
sift = cv2.SIFT_create()

keypoints, descriptors = sift.detectAndCompute(image, None)

print(f"Puntos clave detectados: {len(keypoints)}")
print(f"Dimensiones del descriptor: {descriptors.shape}")  # (N, 128)

Cada punto clave se describe con un vector de 128 dimensiones que captura la distribución de gradientes en su entorno.

3.2 ORB (Oriented FAST and Rotated BRIEF)

ORB es una alternativa gratuita a SIFT y SURF (que tienen restricciones de patente). Es más rápido y funciona bien en la práctica:

orb = cv2.ORB_create(nfeatures=500)

keypoints, descriptors = orb.detectAndCompute(image, None)
print(f"Puntos clave: {len(keypoints)}")
print(f"Descriptor shape: {descriptors.shape}")  # (N, 32)

3.3 Comparación de descriptores

Descriptor Dimensiones Velocidad Patente
SIFT 128 Lento Sí (expirada)
SURF 64 Rápido Sí
ORB 32 Muy rápido No

Nota

Uso moderno: Los puntos clave son la base de la retrieval de imágenes (buscar imágenes similares), el stitching (unir fotos panorámicas) y el SLAM (mapeo en robots). Aunque las CNN han superado a SIFT en muchas tareas, los puntos clave siguen siendo fundamentales en aplicaciones con recursos limitados.

4 Para datos categóricos: embeddings

Los datos categóricos con alta cardinalidad (miles de categorías) no se pueden codificar con one-hot sin crear miles de columnas. Los embeddings categóricos aprenden una representación densa de baja dimensionalidad para cada categoría.

4.1 El problema de la alta cardinalidad

Variable Categorías One-Hot columns
Color 5 5 ✅
Ciudad 500 500 ❌
ID de producto 100.000 100.000 ❌❌

4.2 Solución: embeddings aprendidos

En redes neuronales, las capas de embedding aprenden un vector denso (por ejemplo, 16 dimensiones) para cada categoría:

from sklearn.preprocessing import LabelEncoder
import numpy as np

# Simular embedding aprendido
categories = ['Madrid', 'Barcelona', 'Valencia', 'Sevilla', 'Bilbao']
le = LabelEncoder()
encoded = le.fit_transform(categories)  # [3, 1, 4, 0, 2]

# En una red neuronal, la capa Embedding aprende estos vectores
embedding_dim = 4
np.random.seed(42)
embeddings = np.random.randn(len(categories), embedding_dim)

for cat, emb in zip(categories, embeddings):
    print(f"{cat:12s} → {emb.round(3)}")

En la práctica, esta capa se entrena junto con el resto de la red neuronal, y los embeddings resultantes capturan relaciones semánticas entre categorías (por ejemplo, ciudades cercanas geográficamente tendrán vectores similares).

5 Para series temporales: ventanas y lag features

Las series temporales necesitan transformarse en features tabulares para la mayoría de algoritmos de ML:

import pandas as pd
import numpy as np

# Datos de ventas diarias
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=365)
ventas = np.cumsum(np.random.randn(365)) + 100
df = pd.DataFrame({'fecha': dates, 'ventas': ventas})

# Lag features: valores pasados
for lag in [1, 7, 14, 30]:
    df[f'ventas_lag_{lag}'] = df['ventas'].shift(lag)

# Rolling features: estadísticas móviles
df['media_7d'] = df['ventas'].rolling(7).mean()
df['std_7d'] = df['ventas'].rolling(7).std()
df['min_7d'] = df['ventas'].rolling(7).min()
df['max_7d'] = df['ventas'].rolling(7).max()

# Diferencias: tendencia
df['diff_1'] = df['ventas'].diff(1)
df['diff_7'] = df['ventas'].diff(7)

# Estacionalidad: día de la semana, mes
df['dia_semana'] = df['fecha'].dt.dayofweek
df['mes'] = df['fecha'].dt.month
df['es_fin_de_semana'] = df['dia_semana'].isin([5, 6]).astype(int)

print(df.dropna().head())

Tip

Regla de oro en series temporales: Nunca uses información del futuro para crear features. Los shift() y rolling() deben usar solo datos pasados, nunca futuros.

6 Resumen

Tipo de datos Técnica Salida
Texto TF-IDF Vector disperso de alta dimensión
Imágenes Puntos clave (SIFT, ORB) Descriptores locales
Categóricos (baja cardinalidad) One-hot, label encoding Vector binario o entero
Categóricos (alta cardinalidad) Embeddings Vector denso de baja dimensión
Series temporales Lag features, rolling Variables tabulares

La extracción de características es el puente entre los datos crudos y el modelo. Elegir la técnica correcta depende del tipo de datos y del algoritmo que vayas a usar.