Capítulo 7: Ingeniería de características para el aprendizaje profundo
7.1 Preparación de Datos para Redes Neuronales
El aprendizaje profundo ha revolucionado el campo de la ciencia de datos, ofreciendo herramientas sofisticadas capaces de manejar grandes cantidades de datos y descubrir patrones complejos. Estas redes neuronales avanzadas han demostrado capacidades notables en diversos dominios, desde el reconocimiento de imágenes y voz hasta el procesamiento de lenguaje natural y los sistemas autónomos. El poder del aprendizaje profundo radica en su capacidad para aprender automáticamente representaciones jerárquicas de los datos, permitiéndole capturar relaciones intrincadas y patrones que pueden ser difíciles de discernir para los humanos.
Sin embargo, la efectividad de los modelos de aprendizaje profundo depende en gran medida de la calidad y preparación de los datos de entrada. Esta dependencia resalta la importancia continua de la ingeniería de características, incluso en la era de las redes neuronales. Aunque los algoritmos de aprendizaje profundo pueden a menudo extraer características significativas a partir de datos en bruto, el proceso de preparar y estructurar estos datos sigue siendo crucial para un rendimiento óptimo.
A diferencia de los modelos tradicionales de aprendizaje automático que a menudo requieren una amplia ingeniería de características manual, las redes de aprendizaje profundo están diseñadas para aprender representaciones de alto nivel directamente de datos en bruto. Esta capacidad ha reducido significativamente la necesidad de características diseñadas a mano en muchas aplicaciones. Por ejemplo, en tareas de visión por computadora, las redes neuronales convolucionales pueden aprender automáticamente a detectar bordes, formas y objetos complejos a partir de datos de píxeles en bruto, eliminando la necesidad de extracción manual de características.
No obstante, garantizar que los datos de entrada estén bien estructurados, normalizados y sean relevantes es fundamental para mejorar el rendimiento y la estabilidad del modelo. Una preparación adecuada de los datos puede impactar significativamente en el proceso de aprendizaje, afectando factores como la velocidad de convergencia, la capacidad de generalización y la precisión general. Por ejemplo, en tareas de procesamiento de lenguaje natural, pasos de preprocesamiento como la tokenización, la eliminación de palabras vacías y el manejo de palabras fuera del vocabulario pueden influir enormemente en la capacidad del modelo para comprender y generar texto.
En este capítulo, profundizaremos en los aspectos esenciales de la ingeniería de características para aprendizaje profundo, cubriendo una amplia gama de técnicas para preparar datos, gestionar escalas de características y optimizar datos para redes neuronales. Exploraremos cómo estas metodologías pueden aplicarse a diferentes tipos de datos y dominios de problemas para maximizar el potencial de los modelos de aprendizaje profundo.
Comenzando con la preparación de datos, discutiremos las mejores prácticas para limpiar y transformar los datos para que sean compatibles con las redes neuronales. Esta sección cubrirá técnicas como el manejo de valores faltantes, el tratamiento de valores atípicos y el abordaje de desequilibrios en las clases. También exploraremos consideraciones específicas para preparar datos estructurados (por ejemplo, conjuntos de datos tabulares), datos de imágenes (por ejemplo, redimensionamiento, aumento) y datos de texto (por ejemplo, tokenización, incrustaciones).
Además, examinaremos técnicas avanzadas de ingeniería de características que pueden mejorar los modelos de aprendizaje profundo, tales como:
- Métodos de escalado y normalización de características para garantizar que todas las entradas contribuyan de manera equitativa al proceso de aprendizaje.
- Técnicas de reducción de dimensionalidad como Análisis de Componentes Principales (PCA) y t-SNE para datos de alta dimensión.
- Ingeniería de características específica de series temporales, incluyendo características de retraso y estadísticas rodantes.
- Métodos para manejar variables categóricas, como capas de incrustación para características de alta cardinalidad.
- Incorporación de conocimiento del dominio en la ingeniería de características para guiar el proceso de aprendizaje.
Dominando estas técnicas de ingeniería de características, los científicos de datos y practicantes de aprendizaje automático pueden mejorar significativamente el rendimiento y la robustez de sus modelos de aprendizaje profundo en una amplia gama de aplicaciones y dominios.
Preparar datos para redes neuronales es un proceso crítico que exige una meticulosa atención a los detalles. Esta preparación implica estructurar, escalar y formatear cuidadosamente los datos para optimizar el rendimiento de los modelos de aprendizaje profundo. Las redes neuronales están diseñadas fundamentalmente para procesar información en forma de matrices numéricas, lo que exige la conversión de todos los datos de entrada a un formato numérico consistente.
La importancia del preprocesamiento de datos en aprendizaje profundo no puede subestimarse. A diferencia de los algoritmos tradicionales de aprendizaje automático, las redes neuronales muestran una sensibilidad elevada a las variaciones en la distribución de los datos. Esta sensibilidad hace que los pasos de preprocesamiento, como el escalado y la codificación, no solo sean beneficiosos, sino esenciales para lograr un rendimiento óptimo. Estas medidas preparatorias garantizan que la red neuronal pueda aprender eficazmente de todas las características disponibles sin verse influenciada desproporcionadamente por una única entrada.
Para abordar este proceso de manera sistemática, podemos descomponer la preparación de datos para redes neuronales en tres pasos principales:
- Limpieza y Transformación de Datos: Este paso inicial implica identificar y abordar problemas como valores faltantes, valores atípicos e inconsistencias en el conjunto de datos. También puede incluir la selección o creación de características para garantizar que los datos de entrada sean relevantes e informativos para la tarea.
- Escalado y Normalización: Este paso asegura que todas las características numéricas estén en una escala similar, evitando que las características con magnitudes mayores dominen el proceso de aprendizaje. Las técnicas comunes incluyen escalado min-max, estandarización y escalado robusto.
- Codificación de Variables Categóricas: Dado que las redes neuronales operan sobre datos numéricos, las variables categóricas deben convertirse a un formato numérico. Esto a menudo implica técnicas como la codificación one-hot, la codificación ordinal o métodos más avanzados como las incrustaciones de entidades para variables categóricas de alta cardinalidad.
Al ejecutar meticulosamente estos pasos preparatorios, los científicos de datos pueden mejorar significativamente la eficiencia y efectividad de sus modelos de aprendizaje profundo, allanando el camino para predicciones e insights más precisos.
7.1.1 Paso 1: Limpieza y Transformación de Datos
El primer paso en la preparación de datos para una red neuronal es un proceso crítico que implica garantizar que todas las características estén bien definidas, libres de ruido y sean relevantes para la tarea. Esta etapa inicial establece la base para un entrenamiento y rendimiento exitosos del modelo. Incluye un examen exhaustivo del conjunto de datos para identificar y abordar posibles problemas que puedan obstaculizar el proceso de aprendizaje.
Las características bien definidas son aquellas que tienen significados claros e interpretaciones dentro del contexto del problema. Esto a menudo requiere experiencia en el dominio para comprender qué atributos son más propensos a contribuir al poder predictivo del modelo. Las características deben seleccionarse o diseñarse para capturar la esencia del problema que se está resolviendo.
Eliminar el ruido de los datos es crucial, ya que las redes neuronales pueden ser sensibles a variaciones irrelevantes. El ruido puede presentarse en diversas formas, como errores de medición, valores atípicos o información irrelevante. Las técnicas como el suavizado, la detección de valores atípicos y la selección de características pueden emplearse para reducir el ruido y mejorar la relación señal-ruido en el conjunto de datos.
Asegurar la relevancia de las características implica centrarse en los atributos que tienen más probabilidades de contribuir al poder predictivo del modelo. Esto puede involucrar técnicas de selección de características, la aplicación de conocimiento del dominio o incluso la creación de nuevas características mediante ingeniería de características. Las características relevantes ayudan al modelo a aprender patrones y relaciones significativas, lo que lleva a una mejor generalización y rendimiento en datos no vistos.
Al abordar meticulosamente estos aspectos en el paso inicial de la preparación de datos, establecemos una base sólida para las etapas posteriores de escalado, normalización y codificación, mejorando finalmente la capacidad de la red neuronal para aprender eficazmente de los datos.
Transformaciones Comunes
- Manejo de Valores Faltantes:
- Las redes neuronales requieren conjuntos de datos completos para un rendimiento óptimo. Los valores faltantes pueden llevar a predicciones sesgadas o inexactas, haciendo que su manejo sea crucial.
- Estrategias comunes para abordar datos faltantes incluyen:
- Imputación: Rellenar valores faltantes con estimaciones. Los métodos varían desde simples (imputación de media, mediana o moda) hasta más complejos (imputación por regresión o imputación múltiple).
- Eliminación: Remover filas o columnas con valores faltantes. Este enfoque es sencillo, pero puede llevar a una pérdida significativa de datos si la falta es prevalente.
- Uso de algoritmos que manejen valores faltantes: Algunos métodos avanzados, como ciertos árboles de decisión, pueden trabajar directamente con datos faltantes.
- Específicamente para aprendizaje profundo:
- Datos numéricos: La imputación por media es frecuentemente utilizada debido a su simplicidad y efectividad, aunque métodos más sofisticados como imputación k-NN o el uso de autoencoders pueden dar mejores resultados.
- Datos categóricos: Crear una nueva categoría para valores faltantes es común, permitiendo al modelo aprender patrones relacionados con la falta de datos.
- En modelos secuenciales, una capa de enmascaramiento puede ignorar valores faltantes durante el entrenamiento y la predicción.
- Eliminación de Valores Atípicos:
- Los valores atípicos pueden impactar significativamente el rendimiento de las redes neuronales, llevando a un aprendizaje inestable y a una generalización deficiente. Identificar y abordar valores atípicos es crucial para mantener la consistencia de los datos y mejorar la robustez del modelo.
- Estrategias para manejar valores atípicos incluyen:
- Eliminación: En algunos casos, eliminar completamente puntos de datos identificados como valores atípicos puede ser apropiado, aunque debe hacerse con precaución para evitar perder información valiosa.
- Transformación: Aplicar transformaciones matemáticas como logaritmos o raíces cuadradas puede ayudar a reducir el impacto de valores extremos mientras se preserva el punto de datos.
- Winsorización: Esta técnica consiste en limitar valores extremos a un percentil específico de los datos, reduciendo efectivamente su impacto sin eliminarlos por completo.
- Para características numéricas, implementar una estrategia de límites puede ser particularmente efectiva:
- Establecer límites superiores e inferiores basados en conocimiento del dominio o medidas estadísticas (p. ej., 3 desviaciones estándar de la media).
- Reemplazar valores que excedan estos límites con los valores límite respectivos.
- Esta aproximación preserva la distribución general mientras mitiga el efecto de valores atípicos extremos.
- Es importante destacar que la elección del método para manejar valores atípicos puede impactar significativamente el rendimiento del modelo. Por lo tanto, es beneficioso experimentar con diferentes enfoques y evaluar sus efectos en los resultados del modelo.
- Transformando características para compatibilidad con redes neuronales
Las redes neuronales requieren características de entrada numéricas para un procesamiento óptimo. Esto hace necesario transformar varios tipos de datos:
- Características categóricas: Estas deben codificarse en representaciones numéricas para ser compatibles con las redes neuronales. Métodos comunes incluyen:
- Codificación one-hot: Crea columnas binarias para cada categoría. Este método es particularmente útil para datos nominales sin un orden inherente. Por ejemplo, si tenemos una característica "color" con categorías "rojo", "azul" y "verde", la codificación one-hot crearía tres columnas binarias separadas, una para cada color.
- Codificación por etiquetas: Asigna un número entero único a cada categoría. Este enfoque es más adecuado para datos ordinales donde existe un orden significativo en las categorías. Por ejemplo, niveles educativos como "secundaria", "licenciatura" y "maestría" podrían codificarse como 1, 2 y 3, respectivamente.
- Capas de embeddings: Se utilizan para variables categóricas de alta cardinalidad, que son características con un gran número de categorías únicas. Los embeddings aprenden una representación vectorial densa para cada categoría, capturando relaciones semánticas entre ellas. Esto es particularmente efectivo en tareas de procesamiento de lenguaje natural o al trabajar con características como IDs de productos en sistemas de recomendación.
- Codificación por objetivo: Esta técnica avanzada reemplaza las categorías con el promedio de la variable objetivo para esa categoría. Es útil cuando existe una relación fuerte entre la categoría y la variable objetivo, pero debe usarse con precaución para evitar el sobreajuste.
La elección del método de codificación depende de la naturaleza de la variable categórica, los requisitos específicos de la arquitectura de la red neuronal y las características del problema que se desea resolver. Es beneficioso experimentar con diferentes técnicas de codificación para determinar cuál ofrece el mejor rendimiento para una tarea dada.
- Datos de texto: Requieren tokenización y embeddings, lo que implica:
- Dividir el texto en palabras o subpalabras individuales (tokens). Este proceso puede variar según el idioma y los requisitos específicos de la tarea. Por ejemplo, en inglés, una tokenización basada en espacios puede ser suficiente para muchas aplicaciones, mientras que idiomas más complejos pueden requerir tokenizadores especializados.
- Convertir los tokens en índices numéricos. Este paso crea un vocabulario donde a cada token único se le asigna un ID entero único. Esta conversión es necesaria porque las redes neuronales operan con datos numéricos.
- Aplicar embeddings de palabras para representaciones semánticas. Este paso crucial transforma los tokens en representaciones vectoriales densas que capturan relaciones semánticas entre palabras. Hay varios enfoques:
- Embeddings preentrenados: Utilizar modelos como Word2Vec, GloVe o FastText, entrenados en grandes corpus para capturar patrones generales del lenguaje.
- Embeddings específicos de la tarea: Entrenar embeddings desde cero en un conjunto de datos específico, lo que permite capturar relaciones semánticas específicas del dominio.
- Embeddings contextualizados: Usar modelos como BERT o GPT, que generan embeddings dinámicos basados en el contexto en el que aparece una palabra.
- Manejar palabras fuera del vocabulario (OOV): Implementar estrategias como usar un token especial "desconocido", emplear tokenización por subpalabras (e.g., WordPiece, Byte-Pair Encoding) o usar modelos a nivel de caracteres.
- Datos de series temporales: Requieren transformaciones especializadas para capturar patrones y dependencias temporales:
- Creación de características de desfase: Representan valores pasados de la variable objetivo u otras características relevantes. Por ejemplo, al predecir precios de acciones, se pueden incluir los precios del día, semana o mes anteriores como características.
- Aplicación de promedios móviles u otras estadísticas rodantes: Estas suavizan las fluctuaciones a corto plazo y destacan las tendencias a largo plazo. Las técnicas comunes incluyen promedios móviles simples, promedios móviles exponenciales y desviaciones estándar rodantes.
- Codificación de características cíclicas: Muchas series temporales tienen patrones cíclicos basados en períodos de tiempo. Por ejemplo:
- Día de la semana: Se puede codificar usando transformaciones seno y coseno para capturar la naturaleza circular de los patrones semanales.
- Mes del año: Codificado de manera similar para representar ciclos anuales.
- Hora del día: Útil para capturar patrones diarios en datos de alta frecuencia.
- Diferenciación: Tomar la diferencia entre pasos consecutivos puede ayudar a hacer estacionaria una serie temporal, lo cual es un requisito común para muchos modelos de series temporales.
- Descomposición: Separar una serie temporal en sus componentes de tendencia, estacionalidad y residuales puede proporcionar características valiosas para que el modelo aprenda.
- Datos de imágenes: Requieren preprocesamiento específico para garantizar un rendimiento óptimo en redes neuronales:
- Redimensionamiento a dimensiones consistentes: Este paso es crucial ya que las redes neuronales, particularmente las redes neuronales convolucionales (CNNs), requieren imágenes de entrada de tamaño uniforme. El redimensionamiento ayuda a estandarizar la entrada, permitiendo que la red procese imágenes de manera eficiente sin importar sus dimensiones originales.
- Normalización de valores de píxeles: Normalmente, esto implica escalar las intensidades de los píxeles a un rango de 0-1 o -1 a 1. La normalización es esencial porque:
- Ayuda a una convergencia más rápida durante el entrenamiento al asegurar que todas las características estén en una escala similar.
- Mitiga el impacto de condiciones de iluminación o configuraciones de cámara variables.
- Permite que el modelo trate las características de manera más equitativa, evitando que los píxeles de alta intensidad dominen.
- Aplicación de técnicas de aumento de datos: Esto es fundamental para aumentar la robustez del modelo y mejorar su capacidad de generalización. El aumento de datos amplía artificialmente el conjunto de entrenamiento creando versiones modificadas de imágenes existentes. Técnicas comunes incluyen:
- Transformaciones geométricas: Rotaciones, volteos, escalado y traslaciones.
- Aumentaciones del espacio de color: Ajustes de brillo, contraste o aplicación de modificaciones en el color.
- Adición de ruido o aplicación de filtros: Ruido gaussiano, desenfoque o efectos de nitidez.
- Mezcla de imágenes: Técnicas como mixup o CutMix que combinan múltiples imágenes de entrenamiento.
- Estandarización por canal: Para imágenes multicanal (e.g., RGB), a menudo es beneficioso estandarizar cada canal por separado.
- Manejo de datos faltantes o corruptos: Implementar estrategias para manejar imágenes incompletas o dañadas, como descartar, interpolar o usar modelos generativos para reconstruir partes faltantes.
Ejemplo: Limpieza y transformación de un conjunto de datos de muestra
Exploremos un ejemplo práctico utilizando Pandas para limpiar y preparar datos con valores faltantes y atípicos. Este proceso es crucial en la preprocesamiento de datos para modelos de aprendizaje profundo, ya que asegura la calidad y consistencia de los datos. Abordaremos paso a paso cómo manejar problemas comunes de datos:
- Valores faltantes: Demostraremos técnicas para imputar o eliminar puntos de datos faltantes, que pueden impactar significativamente el rendimiento del modelo si no se abordan.
- Atípicos: Exploraremos métodos para identificar y tratar valores atípicos, que pueden distorsionar distribuciones y afectar el entrenamiento del modelo.
- Transformación de datos: Mostraremos cómo convertir variables categóricas en un formato adecuado para redes neuronales.
Al final de este ejemplo, tendrás una comprensión clara de cómo aplicar estas técnicas esenciales de limpieza de datos utilizando Python y Pandas, sentando las bases para pasos más avanzados de ingeniería de características.
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
# Sample dataset
data = {
'age': [25, 30, np.nan, 35, 40, 100, 28, 45, np.nan, 50],
'income': [50000, 60000, 45000, 70000, np.nan, 200000, 55000, np.nan, 65000, 75000],
'category': ['A', 'B', np.nan, 'A', 'B', 'C', 'A', 'C', 'B', np.nan],
'education': ['High School', 'Bachelor', 'Master', np.nan, 'PhD', 'Bachelor', 'Master', 'High School', 'PhD', 'Bachelor']
}
df = pd.DataFrame(data)
# Display original data
print("Original Data:")
print(df)
print("\n")
# Define preprocessing steps for numerical and categorical columns
numeric_features = ['age', 'income']
categorical_features = ['category', 'education']
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='constant', fill_value='Unknown')),
('onehot', OneHotEncoder(handle_unknown='ignore'))
])
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
])
# Fit and transform the data
X_processed = preprocessor.fit_transform(df)
# Convert to DataFrame for better visualization
feature_names = (numeric_features +
preprocessor.named_transformers_['cat'].named_steps['onehot'].get_feature_names(categorical_features).tolist())
df_processed = pd.DataFrame(X_processed, columns=feature_names)
# Handle outliers (e.g., cap age at 99th percentile)
age_cap = np.percentile(df['age'].dropna(), 99)
df['age'] = np.where(df['age'] > age_cap, age_cap, df['age'])
print("Processed Data:")
print(df_processed)
# Additional statistics
print("\nData Statistics:")
print(df_processed.describe())
print("\nMissing Values After Processing:")
print(df_processed.isnull().sum())
print("\nUnique Values in Categorical Columns:")
for col in categorical_features:
print(f"{col}: {df[col].nunique()}")
Explicación del desglose del código:
- Importación de bibliotecas:
Importamos las bibliotecas necesarias:
pandas
para la manipulación de datos,numpy
para operaciones numéricas y varios módulos descikit-learn
para tareas de preprocesamiento. - Creación de un conjunto de datos de muestra:
Creamos un conjunto de datos más diverso con 10 entradas, incluyendo valores faltantes (
np.nan
) en diferentes columnas. Este conjunto de datos incluye una columna adicional llamadaeducation
para demostrar cómo manejar múltiples variables categóricas. - Visualización de los datos originales:
Imprimimos el conjunto de datos original para mostrar el estado inicial, incluidos los valores faltantes y posibles valores atípicos.
- Definición de los pasos de preprocesamiento:
Separamos nuestras características en columnas numéricas y categóricas. Luego, creamos pipelines de preprocesamiento para cada tipo:
- Para características numéricas: Usamos
SimpleImputer
para llenar valores faltantes con la mediana, y luego aplicamosStandardScaler
para normalizar los datos. - Para características categóricas: Usamos
SimpleImputer
para llenar valores faltantes con "Unknown", y luego aplicamosOneHotEncoder
para convertir las categorías en columnas binarias.
- Para características numéricas: Usamos
- Creación de un ColumnTransformer:
Usamos
ColumnTransformer
para aplicar diferentes pasos de preprocesamiento a distintas columnas, lo que nos permite manejar datos numéricos y categóricos simultáneamente. - Ajuste y transformación de datos:
Aplicamos nuestros pasos de preprocesamiento a todo el conjunto de datos usando
fit_transform()
. - Conversión a DataFrame:
Convertimos los datos procesados nuevamente en un
DataFrame
de pandas para facilitar su visualización y análisis. También creamos nombres de columnas apropiados para las variables categóricas codificadas con one-hot. - Manejo de valores atípicos:
En lugar de usar un valor fijo, limitamos la columna
age
al percentil 99. Este enfoque es más dinámico, ya que se adapta a la distribución de los datos. - Visualización de los datos procesados:
Imprimimos el conjunto de datos procesado para mostrar los resultados de los pasos de preprocesamiento.
- Estadísticas adicionales:
Proporcionamos más información sobre los datos procesados:
- Estadísticas básicas de los datos procesados utilizando
describe()
- Verificación de valores faltantes restantes
- Conteo de valores únicos en las columnas categóricas originales
Este ejemplo demuestra un enfoque robusto y completo para el preprocesamiento de datos para aprendizaje profundo. Maneja adecuadamente los valores faltantes, escala las características numéricas, codifica variables categóricas y aborda valores atípicos, mientras mantiene visibilidad clara de los datos en cada paso. Este enfoque es especialmente adecuado para escenarios del mundo real, donde los conjuntos de datos suelen incluir múltiples tipos de características y presentan varios desafíos de calidad de datos.
7.1.2 Paso 2: Escalado y Normalización
Las redes neuronales son altamente sensibles a la escala de los datos de entrada, lo que puede impactar significativamente su rendimiento y eficiencia. Las características con rangos muy diferentes pueden dominar el proceso de aprendizaje, lo que podría llevar a resultados sesgados o subóptimos. Para abordar este problema, los científicos de datos emplean técnicas de escalado y normalización, asegurando que todas las características de entrada contribuyan de manera equitativa al proceso de aprendizaje.
Existen dos métodos principales para este propósito:
Normalización
Esta técnica escala los datos a un rango específico, típicamente entre 0 y 1. La normalización es particularmente útil cuando se trabaja con características que tienen límites naturales, como valores de píxeles en imágenes (0-255) o métricas basadas en porcentajes (0-100%). Al mapear estos valores a un rango consistente, evitamos que las características con valores absolutos mayores eclipsen a aquellas con rangos más pequeños.
El proceso de normalización implica transformar los valores originales utilizando una fórmula matemática que mantiene las relaciones relativas entre los puntos de datos mientras los restringe dentro de un rango predeterminado. Esta transformación es especialmente beneficiosa en modelos de aprendizaje profundo por varias razones:
- Mejora de la convergencia del modelo: Las características normalizadas a menudo conducen a una convergencia más rápida y estable durante el entrenamiento, ya que el modelo no necesita aprender escalas muy diferentes para distintas características.
- Mayor interpretabilidad de las características: Cuando todas las características están en la misma escala, es más fácil interpretar su importancia relativa y su impacto en las predicciones del modelo.
- Mitigación de inestabilidad numérica: Los valores grandes pueden, en ocasiones, causar inestabilidad numérica en las redes neuronales, particularmente al usar funciones de activación como sigmoide o tangente hiperbólica. La normalización ayuda a prevenir estos problemas.
Las técnicas comunes de normalización incluyen el escalado Min-Max, que mapea el valor mínimo a 0 y el máximo a 1, y el escalado decimal, que mueve el punto decimal de los valores para crear un rango deseado. La elección del método de normalización a menudo depende de los requisitos específicos del modelo y la naturaleza de los datos que se están procesando.
Estandarización Este método reescala los datos para tener una media de cero y una desviación estándar de uno. La estandarización es especialmente beneficiosa al trabajar con conjuntos de datos que contienen características con escalas y distribuciones variables. Al centrar los datos alrededor de cero y escalarlos a una varianza unitaria, la estandarización garantiza que cada característica contribuya proporcionalmente al proceso de aprendizaje del modelo, independientemente de su escala original.
El proceso de estandarización implica restar el valor medio de cada característica de los puntos de datos y luego dividir por la desviación estándar. Esta transformación resulta en una distribución donde aproximadamente el 68% de los valores caen dentro de una desviación estándar de la media, el 95% dentro de dos desviaciones estándar y el 99.7% dentro de tres desviaciones estándar.
La estandarización ofrece varias ventajas en el contexto del aprendizaje profundo:
- Mejora del descenso del gradiente: Las características estandarizadas a menudo conducen a una convergencia más rápida durante la optimización, ya que el algoritmo de descenso del gradiente puede navegar más fácilmente por el espacio de características.
- Importancia de las características: Cuando las características están estandarizadas, sus coeficientes en el modelo pueden compararse directamente para evaluar su importancia relativa.
- Manejo de valores atípicos: La estandarización puede ayudar a mitigar el impacto de los valores atípicos al escalarlos en relación con la desviación estándar de la característica.
Sin embargo, es importante tener en cuenta que la estandarización no limita los valores a un rango específico, lo que puede ser una consideración para ciertas arquitecturas de redes neuronales o al trabajar con características que tienen límites naturales.
La elección entre normalización y estandarización a menudo depende de las características específicas del conjunto de datos y los requisitos de la arquitectura de la red neuronal. Por ejemplo:
- Las redes neuronales convolucionales (CNNs) para el procesamiento de imágenes suelen funcionar bien con datos normalizados, ya que los valores de píxeles naturalmente caen dentro de un rango fijo.
- Las redes neuronales recurrentes (RNNs) y otras arquitecturas que trabajan con series temporales o datos tabulares suelen beneficiarse de la estandarización, especialmente cuando las características tienen diferentes unidades o escalas.
Es importante destacar que el escalado debe aplicarse de manera consistente en los conjuntos de entrenamiento, validación y prueba para mantener la integridad de la evaluación del rendimiento del modelo. Además, al trabajar con datos nuevos y no vistos durante la inferencia, es crucial aplicar los mismos parámetros de escalado utilizados durante el entrenamiento para garantizar la consistencia en las predicciones del modelo.
Ejemplo: Escalado y normalización de características Profundicemos en el escalado de características numéricas utilizando dos métodos populares de Scikit-Learn: StandardScaler
y MinMaxScaler
. Estas técnicas son cruciales para preparar los datos para redes neuronales, ya que ayudan a garantizar que todas las características contribuyan de manera equitativa al proceso de aprendizaje del modelo.
StandardScaler
transforma los datos para tener una media de 0 y una desviación estándar de 1. Esto es particularmente útil cuando tus características tienen diferentes unidades o escalas. Por ejemplo, si tienes características como edad (0-100) e ingresos (de miles a millones), StandardScaler
las llevará a una escala comparable.
Por otro lado, MinMaxScaler
escala los datos a un rango fijo, típicamente entre 0 y 1. Esto es beneficioso cuando necesitas que tus características tengan un rango específico y delimitado, lo cual puede ser importante para ciertos algoritmos o cuando deseas preservar valores cero en datos dispersos.
La elección entre estos escaladores a menudo depende de la naturaleza de tus datos y los requisitos de tu red neuronal. En el siguiente ejemplo, demostraremos cómo aplicar ambas técnicas de escalado a un conjunto de datos de muestra.
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
import matplotlib.pyplot as plt
# Sample data
X = np.array([[25, 50000], [30, 60000], [35, 70000], [40, 80000], [45, 90000], [50, 100000], [55, 110000], [60, 120000]])
df = pd.DataFrame(X, columns=['Age', 'Income'])
# Standardization
scaler = StandardScaler()
X_standardized = scaler.fit_transform(X)
df_standardized = pd.DataFrame(X_standardized, columns=['Age_std', 'Income_std'])
# Normalization (Min-Max Scaling)
normalizer = MinMaxScaler()
X_normalized = normalizer.fit_transform(X)
df_normalized = pd.DataFrame(X_normalized, columns=['Age_norm', 'Income_norm'])
# Robust Scaling
robust_scaler = RobustScaler()
X_robust = robust_scaler.fit_transform(X)
df_robust = pd.DataFrame(X_robust, columns=['Age_robust', 'Income_robust'])
# Combine all scaled data
df_combined = pd.concat([df, df_standardized, df_normalized, df_robust], axis=1)
# Display results
print("Combined Data:")
print(df_combined)
# Visualize the scaling effects
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
fig.suptitle('Comparison of Scaling Techniques')
axes[0, 0].scatter(df['Age'], df['Income'])
axes[0, 0].set_title('Original Data')
axes[0, 1].scatter(df_standardized['Age_std'], df_standardized['Income_std'])
axes[0, 1].set_title('Standardized Data')
axes[1, 0].scatter(df_normalized['Age_norm'], df_normalized['Income_norm'])
axes[1, 0].set_title('Normalized Data')
axes[1, 1].scatter(df_robust['Age_robust'], df_robust['Income_robust'])
axes[1, 1].set_title('Robust Scaled Data')
for ax in axes.flat:
ax.set(xlabel='Age', ylabel='Income')
plt.tight_layout()
plt.show()
Explicación del desglose del código
- Importación de bibliotecas:
Se importan
numpy
para operaciones numéricas,pandas
para manipulación de datos,sklearn
para herramientas de preprocesamiento ymatplotlib
para visualización. - Creación de datos de muestra:
Se crea un conjunto de datos más amplio con 8 entradas, incluyendo datos de edad e ingresos. Esto proporciona un conjunto de datos más completo para demostrar los efectos del escalado.
- Estandarización (
StandardScaler
):- Transforma las características para tener una media de 0 y una desviación estándar de 1.
- Es útil cuando las características tienen diferentes escalas o unidades.
- Fórmula: z = (x - μ) / σ, donde μ es la media y σ es la desviación estándar.
- Normalización (
MinMaxScaler
):- Escala las características a un rango fijo, típicamente entre 0 y 1.
- Preserva valores cero y no centra los datos.
- Fórmula: x_scaled = (x - x_min) / (x_max - x_min).
- Escalado robusto (
RobustScaler
):- Escala las características utilizando estadísticas robustas a valores atípicos.
- Utiliza la mediana y el rango intercuartil en lugar de la media y la desviación estándar.
- Es útil cuando los datos contienen muchos valores atípicos.
- Combinación de datos:
Se combinan los conjuntos de datos originales y escalados en un único
DataFrame
para facilitar la comparación. - Visualización:
- Se crea una cuadrícula de gráficos de dispersión 2x2 para visualizar los efectos de las diferentes técnicas de escalado.
- Esto permite una comparación directa de cómo cada método transforma los datos.
Puntos clave:
StandardScaler
centra los datos y los escala a una varianza unitaria, como se observa en el gráfico estandarizado donde los datos están centrados alrededor de (0,0).MinMaxScaler
comprime todos los puntos de datos a un rango fijo [0,1], manteniendo la forma de la distribución original.RobustScaler
produce un resultado similar aStandardScaler
, pero es menos influenciado por valores atípicos.
Este ejemplo ofrece un examen exhaustivo de varias técnicas de escalado, su impacto en los datos y métodos para visualizar estas transformaciones. Es especialmente valioso para comprender cómo los enfoques de escalado afectan tu conjunto de datos antes de ingresarlo en una red neuronal.
7.1.3 Paso 3: Codificación de variables categóricas
Los datos categóricos requieren codificación antes de ser introducidos en una red neuronal. Este proceso transforma datos no numéricos en un formato que las redes neuronales pueden procesar eficazmente. Existen varias técnicas de codificación, cada una con sus fortalezas y casos de uso:
Codificación One-Hot
Este método transforma variables categóricas en un formato que las redes neuronales pueden procesar de manera efectiva. Crea un vector binario para cada categoría, donde cada valor único de la categoría se representa mediante una columna separada. Por ejemplo, considera una categoría "color" con valores "rojo", "azul" y "verde". La codificación one-hot generaría tres nuevas columnas: "color_rojo", "color_azul" y "color_verde". En cada fila, la columna correspondiente al color presente contendría un 1, mientras que las otras serían 0.
Esta técnica de codificación es particularmente valiosa para categorías nominales que carecen de un orden inherente. Al crear columnas binarias separadas para cada categoría, la codificación one-hot evita imponer relaciones numéricas artificiales entre las categorías. Esto es crucial porque las redes neuronales podrían interpretar las codificaciones numéricas como si tuvieran un orden o magnitud significativos.
Sin embargo, la codificación one-hot presenta algunas consideraciones importantes:
- Dimensionalidad: Para categorías con muchos valores únicos, la codificación one-hot puede aumentar significativamente el número de características de entrada, lo que podría conducir a la "maldición de la dimensionalidad".
- Esparcimiento: Los datos codificados resultantes pueden ser dispersos, con muchos valores 0, lo que podría afectar la eficiencia de algunos algoritmos.
- Manejo de nuevas categorías: La codificación one-hot puede enfrentar problemas con categorías nuevas y no vistas en datos de prueba o de producción que no estaban presentes durante el entrenamiento.
A pesar de estos desafíos, la codificación one-hot sigue siendo un método popular y efectivo para preparar datos categóricos para redes neuronales, especialmente al trabajar con categorías nominales de baja a moderada cardinalidad.
Aquí tienes un ejemplo de cómo implementar la codificación one-hot utilizando Python y la biblioteca pandas
.
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green'],
'size': ['small', 'medium', 'large', 'medium', 'small']
})
# Initialize the OneHotEncoder
encoder = OneHotEncoder(sparse=False)
# Fit and transform the data
encoded_data = encoder.fit_transform(data)
# Get feature names
feature_names = encoder.get_feature_names_out(['color', 'size'])
# Create a new DataFrame with encoded data
encoded_df = pd.DataFrame(encoded_data, columns=feature_names)
print("Original data:")
print(data)
print("\nOne-hot encoded data:")
print(encoded_df)
Explicación del desglose del código
- Importar las bibliotecas necesarias: Importamos
pandas
para la manipulación de datos yOneHotEncoder
desklearn
para la codificación one-hot. - Crear datos de muestra: Creamos un DataFrame simple con dos columnas categóricas: "color" y "size".
- Inicializar
OneHotEncoder
: Creamos una instancia deOneHotEncoder
consparse=False
para obtener una salida en forma de matriz densa en lugar de una matriz dispersa. - Ajustar y transformar los datos: Usamos el método
fit_transform
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Obtener nombres de características: Usamos
get_feature_names_out
para obtener los nombres de las nuevas columnas codificadas. - Crear un nuevo DataFrame: Creamos un nuevo DataFrame con los datos codificados, utilizando los nombres de las características como etiquetas de las columnas.
- Imprimir resultados: Mostramos tanto los datos originales como los codificados para comparación.
Este código demuestra cómo la codificación one-hot transforma las variables categóricas en un formato adecuado para modelos de aprendizaje automático, incluidas las redes neuronales. Cada valor único de categoría se convierte en una columna separada, con valores binarios que indican la presencia (1) o ausencia (0) de esa categoría en cada fila.
Cuando ejecutas este código, puedes observar cómo los datos categóricos originales se transforman en un formato codificado one-hot, donde cada valor único de categoría tiene su propia columna con indicadores binarios.
Codificación por etiquetas
Esta técnica asigna a cada categoría un número entero único. Por ejemplo, "rojo" podría codificarse como 0, "azul" como 1 y "verde" como 2. Aunque es eficiente en términos de uso de memoria, la codificación por etiquetas es más adecuada para datos ordinales (categorías con un orden significativo). Es importante tener en cuenta que las redes neuronales podrían interpretar el orden de las etiquetas como significativo, lo que puede llevar a suposiciones incorrectas en categorías nominales.
La codificación por etiquetas es particularmente útil al trabajar con variables ordinales, donde el orden de las categorías importa. Por ejemplo, al codificar niveles educativos (e.g., "Secundaria", "Licenciatura", "Maestría", "Doctorado"), la codificación por etiquetas preserva el orden inherente, lo cual puede ser significativo para el modelo.
Sin embargo, la codificación por etiquetas tiene limitaciones cuando se aplica a categorías nominales (aquellas sin un orden inherente). Por ejemplo, codificar razas de perros como números (e.g., Labrador = 0, Poodle = 1, Beagle = 2) podría llevar al modelo a inferir incorrectamente que la diferencia numérica entre razas tiene un significado.
La implementación de la codificación por etiquetas es sencilla utilizando bibliotecas como scikit-learn
.
import pandas as pd
from sklearn.preprocessing import LabelEncoder
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green', 'blue', 'yellow'],
'size': ['small', 'medium', 'large', 'medium', 'small', 'large', 'medium']
})
# Initialize LabelEncoder
le_color = LabelEncoder()
le_size = LabelEncoder()
# Fit and transform the data
data['color_encoded'] = le_color.fit_transform(data['color'])
data['size_encoded'] = le_size.fit_transform(data['size'])
print("Original and encoded data:")
print(data)
print("\nUnique categories and their encoded values:")
print("Colors:", dict(zip(le_color.classes_, le_color.transform(le_color.classes_))))
print("Sizes:", dict(zip(le_size.classes_, le_size.transform(le_size.classes_))))
# Demonstrate inverse transform
color_codes = [0, 1, 2, 3]
size_codes = [0, 1, 2]
print("\nDecoding back to original categories:")
print("Colors:", le_color.inverse_transform(color_codes))
print("Sizes:", le_size.inverse_transform(size_codes))
Explicación del desglose del código
- Importación de bibliotecas:
- Importamos
pandas
para la manipulación de datos yLabelEncoder
desklearn
para codificar variables categóricas.
- Importamos
- Creación de datos de muestra:
- Creamos un DataFrame con dos columnas categóricas: "color" y "size".
- Este ejemplo incluye datos más diversos para demostrar mejor el proceso de codificación.
- Inicialización de
LabelEncoder
:- Creamos dos instancias separadas de
LabelEncoder
, una para "color" y otra para "size". - Esto nos permite codificar cada categoría de forma independiente.
- Creamos dos instancias separadas de
- Ajuste y transformación de datos:
- Usamos
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Los valores codificados se añaden como nuevas columnas en el DataFrame.
- Usamos
- Visualización de resultados:
- Imprimimos los datos originales junto con los datos codificados para facilitar la comparación.
- Mostrar los mapeos de codificación:
- Creamos diccionarios para mostrar cómo cada categoría única se mapea a su valor codificado.
- Esto ayuda a comprender e interpretar los datos codificados.
- Demostración de transformación inversa:
- Mostramos cómo decodificar los valores numéricos de nuevo a sus categorías originales.
- Esto es útil cuando necesitas convertir predicciones o datos codificados a un formato comprensible para los humanos.
Este ejemplo proporciona una visión completa de la codificación por etiquetas. Demuestra cómo manejar múltiples variables categóricas, muestra el mapeo entre las categorías originales y los valores codificados, e incluye el proceso de transformación inversa. Este enfoque ofrece una comprensión más profunda de cómo funciona la codificación por etiquetas y cómo puede aplicarse en escenarios del mundo real.
Al utilizar la codificación por etiquetas, es crucial documentar el esquema de codificación y garantizar una aplicación consistente en los conjuntos de datos de entrenamiento, validación y prueba. Además, para modelos sensibles a la magnitud de las características de entrada (como redes neuronales), puede ser necesario escalar los valores codificados para evitar que el modelo atribuya una importancia indebida a las categorías con representaciones numéricas mayores.
Codificación Binaria
Este método combina aspectos tanto de la codificación one-hot como de la codificación por etiquetas, ofreciendo un equilibrio entre eficiencia e información preservada. Opera en dos pasos:
- Asignación de enteros: A cada categoría única se le asigna un entero, similar a la codificación por etiquetas.
- Conversión a binario: El entero asignado se convierte en su representación binaria.
Por ejemplo, si tenemos las categorías A, B, C y D, podrían asignarse los enteros 0, 1, 2 y 3 respectivamente. En binario, estos se representarían como 00, 01, 10 y 11.
Las ventajas de la codificación binaria incluyen:
- Eficiencia de memoria: Requiere menos columnas que la codificación one-hot, especialmente para categorías con muchos valores únicos. Para n categorías, la codificación binaria utiliza log2(n) columnas, mientras que la codificación one-hot utiliza n columnas.
- Preservación de información: A diferencia de la codificación por etiquetas, no impone una relación ordinal arbitraria entre categorías.
- Reducción de dimensionalidad: Crea menos características nuevas en comparación con la codificación one-hot, lo que puede ser beneficioso para el entrenamiento del modelo y la reducción del sobreajuste.
Sin embargo, la codificación binaria también tiene algunas consideraciones:
- Interpretación: Las características binarias resultantes pueden ser menos interpretables que las características codificadas one-hot.
- Compatibilidad con modelos: No todos los modelos pueden manejar características codificadas binariamente de manera óptima, por lo que es importante considerar los requisitos específicos de tu algoritmo elegido.
La codificación binaria es particularmente útil en escenarios donde se manejan variables categóricas de alta cardinalidad y la eficiencia de memoria es una preocupación, como en aplicaciones de aprendizaje automático a gran escala o cuando se trabaja con recursos computacionales limitados.
Aquí tienes un ejemplo de cómo implementar la codificación binaria utilizando Python y la biblioteca category_encoders
.
import pandas as pd
import category_encoders as ce
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green', 'blue', 'yellow'],
'size': ['small', 'medium', 'large', 'medium', 'small', 'large', 'medium']
})
# Initialize BinaryEncoder
encoder = ce.BinaryEncoder(cols=['color', 'size'])
# Fit and transform the data
encoded_data = encoder.fit_transform(data)
print("Original data:")
print(data)
print("\nBinary encoded data:")
print(encoded_data)
# Display mapping
print("\nEncoding mapping:")
print(encoder.mapping)
Explicación del desglose del código
- Importar bibliotecas:
- Importamos
pandas
para la manipulación de datos ycategory_encoders
para la codificación binaria.
- Importamos
- Crear datos de muestra:
- Creamos un DataFrame con dos columnas categóricas: "color" y "size".
- Inicializar
BinaryEncoder
:- Creamos una instancia de
BinaryEncoder
, especificando qué columnas codificar.
- Creamos una instancia de
- Ajustar y transformar datos:
- Usamos
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso.
- Usamos
- Visualizar resultados:
- Imprimimos los datos originales y los datos codificados binariamente para comparación.
- Mostrar mapeo de codificación:
- Mostramos el mapeo para ver cómo cada categoría se codifica en binario.
Cuando ejecutas este código, puedes observar cómo cada categoría única en "color" y "size" se transforma en un conjunto de columnas binarias. El número de columnas binarias para cada característica depende del número de categorías únicas en esa característica.
La codificación binaria proporciona una representación compacta de variables categóricas, especialmente útil para características de alta cardinalidad. Encuentra un equilibrio entre la explosión dimensional de la codificación one-hot y las suposiciones ordinales de la codificación por etiquetas, lo que la convierte en una herramienta valiosa en la ingeniería de características para aprendizaje profundo.
Embeddings
Para variables categóricas con alta cardinalidad (muchos valores únicos), los embeddings pueden ser una solución efectiva. Esta técnica aprende una representación vectorial de baja dimensión para cada categoría durante el proceso de entrenamiento de la red neuronal. Los embeddings pueden capturar relaciones complejas entre categorías y se utilizan comúnmente en tareas de procesamiento de lenguaje natural.
Los embeddings funcionan mapeando cada categoría a un vector denso en un espacio vectorial continuo. A diferencia de la codificación one-hot, que trata cada categoría como completamente distinta, los embeddings permiten comparaciones significativas entre categorías basadas en sus representaciones vectoriales aprendidas. Esto es particularmente útil al trabajar con grandes vocabularios en datos de texto o con variables categóricas que tienen similitudes o jerarquías inherentes.
La dimensionalidad del espacio de embeddings es un hiperparámetro que puede ajustarse. Por lo general, es mucho menor que el número de categorías únicas, lo que ayuda a reducir la complejidad del modelo y mitigar la maldición de la dimensionalidad. Por ejemplo, una variable categórica con 10,000 valores únicos podría incrustarse en un espacio de 50 o 100 dimensiones.
Una de las principales ventajas de los embeddings es su capacidad de generalización. Pueden capturar relaciones semánticas entre categorías, permitiendo que el modelo realice predicciones inteligentes incluso para categorías que no ha visto durante el entrenamiento. Esto es especialmente valioso en sistemas de recomendación, donde los embeddings pueden representar usuarios y elementos en un espacio compartido, facilitando el descubrimiento de preferencias y similitudes latentes.
En el contexto del aprendizaje profundo para datos tabulares, los embeddings pueden aprenderse como parte de la arquitectura de la red neuronal. Esto permite que el modelo descubra automáticamente representaciones óptimas para variables categóricas, adaptadas a la tarea específica. Los embeddings aprendidos también pueden visualizarse o analizarse por separado, proporcionando potencialmente ideas sobre las relaciones entre categorías que podrían no ser evidentes en los datos originales.
Aquí tienes un ejemplo de cómo implementar embeddings para variables categóricas utilizando TensorFlow/Keras.
import tensorflow as tf
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
# Sample data
data = pd.DataFrame({
'user_id': np.random.randint(1, 1001, 10000),
'product_id': np.random.randint(1, 501, 10000),
'purchase': np.random.randint(0, 2, 10000)
})
# Prepare features and target
X = data[['user_id', 'product_id']]
y = data['purchase']
# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Define the model
user_input = tf.keras.layers.Input(shape=(1,))
product_input = tf.keras.layers.Input(shape=(1,))
user_embedding = tf.keras.layers.Embedding(input_dim=1001, output_dim=50)(user_input)
product_embedding = tf.keras.layers.Embedding(input_dim=501, output_dim=50)(product_input)
user_vec = tf.keras.layers.Flatten()(user_embedding)
product_vec = tf.keras.layers.Flatten()(product_embedding)
concat = tf.keras.layers.Concatenate()([user_vec, product_vec])
dense = tf.keras.layers.Dense(64, activation='relu')(concat)
output = tf.keras.layers.Dense(1, activation='sigmoid')(dense)
model = tf.keras.Model(inputs=[user_input, product_input], outputs=output)
# Compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# Train the model
model.fit([X_train['user_id'], X_train['product_id']], y_train,
epochs=5, batch_size=32, validation_split=0.2)
# Evaluate the model
loss, accuracy = model.evaluate([X_test['user_id'], X_test['product_id']], y_test)
print(f"Test Accuracy: {accuracy:.4f}")
Explicación del desglose del código
- Preparación de datos:
- Creamos un conjunto de datos de muestra con IDs de usuarios, IDs de productos e información de compras.
- Los datos se dividen en conjuntos de entrenamiento y prueba.
- Arquitectura del modelo:
- Definimos capas de entrada separadas para
user_id
yproduct_id
. - Se crean capas de embeddings para los IDs de usuarios y productos. El
input_dim
se establece como el número de categorías únicas más uno (para considerar el posible indexado en cero), y eloutput_dim
se fija en 50 (la dimensión del embedding). - Los vectores embebidos se aplanan y concatenan.
- Se añaden capas densas para un procesamiento adicional, con una activación final sigmoide para clasificación binaria.
- Definimos capas de entrada separadas para
- Compilación y entrenamiento del modelo:
- El modelo se compila utilizando la pérdida de entropía cruzada binaria y el optimizador Adam.
- El modelo se entrena con los datos preparados.
- Evaluación:
- Se evalúa el rendimiento del modelo en el conjunto de prueba.
Este ejemplo demuestra cómo se pueden usar embeddings para representar variables categóricas de alta cardinalidad (IDs de usuarios y productos) en un espacio de menor dimensión. Las capas de embeddings aprenden a mapear cada ID único a un vector de 50 dimensiones durante el proceso de entrenamiento. Estos embeddings capturan relaciones significativas entre usuarios y productos, lo que permite al modelo realizar predicciones basadas en estas representaciones latentes.
Las principales ventajas de usar embeddings en este escenario incluyen:
- Reducción de dimensionalidad: En lugar de usar codificación one-hot, que resultaría en vectores dispersos de alta dimensionalidad, los embeddings proporcionan una representación densa y de menor dimensión.
- Captura de relaciones semánticas: El espacio de embeddings puede capturar similitudes entre usuarios o productos, incluso si no han sido vistos juntos en los datos de entrenamiento.
- Escalabilidad: Este enfoque se adapta bien a un gran número de categorías, lo que lo hace adecuado para aplicaciones del mundo real con muchos usuarios y productos.
Al usar embeddings, permitimos que la red neuronal aprenda representaciones óptimas de nuestras variables categóricas, específicamente adaptadas a la tarea de predecir compras. Esto puede conducir a un mejor rendimiento del modelo y una mejor generalización a datos no vistos.
La elección del método de codificación depende de la naturaleza de tus datos categóricos, los requisitos específicos de la arquitectura de tu red neuronal y el problema que estás tratando de resolver. Es beneficioso experimentar con diferentes técnicas de codificación para determinar cuál ofrece el mejor rendimiento para tu caso particular.
Preparar datos para redes neuronales es un proceso intrincado pero crucial que incluye limpieza, escalado y codificación de datos. Los datos correctamente transformados y escalados mejoran el proceso de aprendizaje, permitiendo que las redes neuronales converjan más rápido y ofrezcan resultados más precisos. Al garantizar que cada característica se maneje adecuadamente, ya sea escalando valores numéricos o codificando categorías, creamos una base sólida para un modelo de aprendizaje profundo exitoso.
7.1 Preparación de Datos para Redes Neuronales
El aprendizaje profundo ha revolucionado el campo de la ciencia de datos, ofreciendo herramientas sofisticadas capaces de manejar grandes cantidades de datos y descubrir patrones complejos. Estas redes neuronales avanzadas han demostrado capacidades notables en diversos dominios, desde el reconocimiento de imágenes y voz hasta el procesamiento de lenguaje natural y los sistemas autónomos. El poder del aprendizaje profundo radica en su capacidad para aprender automáticamente representaciones jerárquicas de los datos, permitiéndole capturar relaciones intrincadas y patrones que pueden ser difíciles de discernir para los humanos.
Sin embargo, la efectividad de los modelos de aprendizaje profundo depende en gran medida de la calidad y preparación de los datos de entrada. Esta dependencia resalta la importancia continua de la ingeniería de características, incluso en la era de las redes neuronales. Aunque los algoritmos de aprendizaje profundo pueden a menudo extraer características significativas a partir de datos en bruto, el proceso de preparar y estructurar estos datos sigue siendo crucial para un rendimiento óptimo.
A diferencia de los modelos tradicionales de aprendizaje automático que a menudo requieren una amplia ingeniería de características manual, las redes de aprendizaje profundo están diseñadas para aprender representaciones de alto nivel directamente de datos en bruto. Esta capacidad ha reducido significativamente la necesidad de características diseñadas a mano en muchas aplicaciones. Por ejemplo, en tareas de visión por computadora, las redes neuronales convolucionales pueden aprender automáticamente a detectar bordes, formas y objetos complejos a partir de datos de píxeles en bruto, eliminando la necesidad de extracción manual de características.
No obstante, garantizar que los datos de entrada estén bien estructurados, normalizados y sean relevantes es fundamental para mejorar el rendimiento y la estabilidad del modelo. Una preparación adecuada de los datos puede impactar significativamente en el proceso de aprendizaje, afectando factores como la velocidad de convergencia, la capacidad de generalización y la precisión general. Por ejemplo, en tareas de procesamiento de lenguaje natural, pasos de preprocesamiento como la tokenización, la eliminación de palabras vacías y el manejo de palabras fuera del vocabulario pueden influir enormemente en la capacidad del modelo para comprender y generar texto.
En este capítulo, profundizaremos en los aspectos esenciales de la ingeniería de características para aprendizaje profundo, cubriendo una amplia gama de técnicas para preparar datos, gestionar escalas de características y optimizar datos para redes neuronales. Exploraremos cómo estas metodologías pueden aplicarse a diferentes tipos de datos y dominios de problemas para maximizar el potencial de los modelos de aprendizaje profundo.
Comenzando con la preparación de datos, discutiremos las mejores prácticas para limpiar y transformar los datos para que sean compatibles con las redes neuronales. Esta sección cubrirá técnicas como el manejo de valores faltantes, el tratamiento de valores atípicos y el abordaje de desequilibrios en las clases. También exploraremos consideraciones específicas para preparar datos estructurados (por ejemplo, conjuntos de datos tabulares), datos de imágenes (por ejemplo, redimensionamiento, aumento) y datos de texto (por ejemplo, tokenización, incrustaciones).
Además, examinaremos técnicas avanzadas de ingeniería de características que pueden mejorar los modelos de aprendizaje profundo, tales como:
- Métodos de escalado y normalización de características para garantizar que todas las entradas contribuyan de manera equitativa al proceso de aprendizaje.
- Técnicas de reducción de dimensionalidad como Análisis de Componentes Principales (PCA) y t-SNE para datos de alta dimensión.
- Ingeniería de características específica de series temporales, incluyendo características de retraso y estadísticas rodantes.
- Métodos para manejar variables categóricas, como capas de incrustación para características de alta cardinalidad.
- Incorporación de conocimiento del dominio en la ingeniería de características para guiar el proceso de aprendizaje.
Dominando estas técnicas de ingeniería de características, los científicos de datos y practicantes de aprendizaje automático pueden mejorar significativamente el rendimiento y la robustez de sus modelos de aprendizaje profundo en una amplia gama de aplicaciones y dominios.
Preparar datos para redes neuronales es un proceso crítico que exige una meticulosa atención a los detalles. Esta preparación implica estructurar, escalar y formatear cuidadosamente los datos para optimizar el rendimiento de los modelos de aprendizaje profundo. Las redes neuronales están diseñadas fundamentalmente para procesar información en forma de matrices numéricas, lo que exige la conversión de todos los datos de entrada a un formato numérico consistente.
La importancia del preprocesamiento de datos en aprendizaje profundo no puede subestimarse. A diferencia de los algoritmos tradicionales de aprendizaje automático, las redes neuronales muestran una sensibilidad elevada a las variaciones en la distribución de los datos. Esta sensibilidad hace que los pasos de preprocesamiento, como el escalado y la codificación, no solo sean beneficiosos, sino esenciales para lograr un rendimiento óptimo. Estas medidas preparatorias garantizan que la red neuronal pueda aprender eficazmente de todas las características disponibles sin verse influenciada desproporcionadamente por una única entrada.
Para abordar este proceso de manera sistemática, podemos descomponer la preparación de datos para redes neuronales en tres pasos principales:
- Limpieza y Transformación de Datos: Este paso inicial implica identificar y abordar problemas como valores faltantes, valores atípicos e inconsistencias en el conjunto de datos. También puede incluir la selección o creación de características para garantizar que los datos de entrada sean relevantes e informativos para la tarea.
- Escalado y Normalización: Este paso asegura que todas las características numéricas estén en una escala similar, evitando que las características con magnitudes mayores dominen el proceso de aprendizaje. Las técnicas comunes incluyen escalado min-max, estandarización y escalado robusto.
- Codificación de Variables Categóricas: Dado que las redes neuronales operan sobre datos numéricos, las variables categóricas deben convertirse a un formato numérico. Esto a menudo implica técnicas como la codificación one-hot, la codificación ordinal o métodos más avanzados como las incrustaciones de entidades para variables categóricas de alta cardinalidad.
Al ejecutar meticulosamente estos pasos preparatorios, los científicos de datos pueden mejorar significativamente la eficiencia y efectividad de sus modelos de aprendizaje profundo, allanando el camino para predicciones e insights más precisos.
7.1.1 Paso 1: Limpieza y Transformación de Datos
El primer paso en la preparación de datos para una red neuronal es un proceso crítico que implica garantizar que todas las características estén bien definidas, libres de ruido y sean relevantes para la tarea. Esta etapa inicial establece la base para un entrenamiento y rendimiento exitosos del modelo. Incluye un examen exhaustivo del conjunto de datos para identificar y abordar posibles problemas que puedan obstaculizar el proceso de aprendizaje.
Las características bien definidas son aquellas que tienen significados claros e interpretaciones dentro del contexto del problema. Esto a menudo requiere experiencia en el dominio para comprender qué atributos son más propensos a contribuir al poder predictivo del modelo. Las características deben seleccionarse o diseñarse para capturar la esencia del problema que se está resolviendo.
Eliminar el ruido de los datos es crucial, ya que las redes neuronales pueden ser sensibles a variaciones irrelevantes. El ruido puede presentarse en diversas formas, como errores de medición, valores atípicos o información irrelevante. Las técnicas como el suavizado, la detección de valores atípicos y la selección de características pueden emplearse para reducir el ruido y mejorar la relación señal-ruido en el conjunto de datos.
Asegurar la relevancia de las características implica centrarse en los atributos que tienen más probabilidades de contribuir al poder predictivo del modelo. Esto puede involucrar técnicas de selección de características, la aplicación de conocimiento del dominio o incluso la creación de nuevas características mediante ingeniería de características. Las características relevantes ayudan al modelo a aprender patrones y relaciones significativas, lo que lleva a una mejor generalización y rendimiento en datos no vistos.
Al abordar meticulosamente estos aspectos en el paso inicial de la preparación de datos, establecemos una base sólida para las etapas posteriores de escalado, normalización y codificación, mejorando finalmente la capacidad de la red neuronal para aprender eficazmente de los datos.
Transformaciones Comunes
- Manejo de Valores Faltantes:
- Las redes neuronales requieren conjuntos de datos completos para un rendimiento óptimo. Los valores faltantes pueden llevar a predicciones sesgadas o inexactas, haciendo que su manejo sea crucial.
- Estrategias comunes para abordar datos faltantes incluyen:
- Imputación: Rellenar valores faltantes con estimaciones. Los métodos varían desde simples (imputación de media, mediana o moda) hasta más complejos (imputación por regresión o imputación múltiple).
- Eliminación: Remover filas o columnas con valores faltantes. Este enfoque es sencillo, pero puede llevar a una pérdida significativa de datos si la falta es prevalente.
- Uso de algoritmos que manejen valores faltantes: Algunos métodos avanzados, como ciertos árboles de decisión, pueden trabajar directamente con datos faltantes.
- Específicamente para aprendizaje profundo:
- Datos numéricos: La imputación por media es frecuentemente utilizada debido a su simplicidad y efectividad, aunque métodos más sofisticados como imputación k-NN o el uso de autoencoders pueden dar mejores resultados.
- Datos categóricos: Crear una nueva categoría para valores faltantes es común, permitiendo al modelo aprender patrones relacionados con la falta de datos.
- En modelos secuenciales, una capa de enmascaramiento puede ignorar valores faltantes durante el entrenamiento y la predicción.
- Eliminación de Valores Atípicos:
- Los valores atípicos pueden impactar significativamente el rendimiento de las redes neuronales, llevando a un aprendizaje inestable y a una generalización deficiente. Identificar y abordar valores atípicos es crucial para mantener la consistencia de los datos y mejorar la robustez del modelo.
- Estrategias para manejar valores atípicos incluyen:
- Eliminación: En algunos casos, eliminar completamente puntos de datos identificados como valores atípicos puede ser apropiado, aunque debe hacerse con precaución para evitar perder información valiosa.
- Transformación: Aplicar transformaciones matemáticas como logaritmos o raíces cuadradas puede ayudar a reducir el impacto de valores extremos mientras se preserva el punto de datos.
- Winsorización: Esta técnica consiste en limitar valores extremos a un percentil específico de los datos, reduciendo efectivamente su impacto sin eliminarlos por completo.
- Para características numéricas, implementar una estrategia de límites puede ser particularmente efectiva:
- Establecer límites superiores e inferiores basados en conocimiento del dominio o medidas estadísticas (p. ej., 3 desviaciones estándar de la media).
- Reemplazar valores que excedan estos límites con los valores límite respectivos.
- Esta aproximación preserva la distribución general mientras mitiga el efecto de valores atípicos extremos.
- Es importante destacar que la elección del método para manejar valores atípicos puede impactar significativamente el rendimiento del modelo. Por lo tanto, es beneficioso experimentar con diferentes enfoques y evaluar sus efectos en los resultados del modelo.
- Transformando características para compatibilidad con redes neuronales
Las redes neuronales requieren características de entrada numéricas para un procesamiento óptimo. Esto hace necesario transformar varios tipos de datos:
- Características categóricas: Estas deben codificarse en representaciones numéricas para ser compatibles con las redes neuronales. Métodos comunes incluyen:
- Codificación one-hot: Crea columnas binarias para cada categoría. Este método es particularmente útil para datos nominales sin un orden inherente. Por ejemplo, si tenemos una característica "color" con categorías "rojo", "azul" y "verde", la codificación one-hot crearía tres columnas binarias separadas, una para cada color.
- Codificación por etiquetas: Asigna un número entero único a cada categoría. Este enfoque es más adecuado para datos ordinales donde existe un orden significativo en las categorías. Por ejemplo, niveles educativos como "secundaria", "licenciatura" y "maestría" podrían codificarse como 1, 2 y 3, respectivamente.
- Capas de embeddings: Se utilizan para variables categóricas de alta cardinalidad, que son características con un gran número de categorías únicas. Los embeddings aprenden una representación vectorial densa para cada categoría, capturando relaciones semánticas entre ellas. Esto es particularmente efectivo en tareas de procesamiento de lenguaje natural o al trabajar con características como IDs de productos en sistemas de recomendación.
- Codificación por objetivo: Esta técnica avanzada reemplaza las categorías con el promedio de la variable objetivo para esa categoría. Es útil cuando existe una relación fuerte entre la categoría y la variable objetivo, pero debe usarse con precaución para evitar el sobreajuste.
La elección del método de codificación depende de la naturaleza de la variable categórica, los requisitos específicos de la arquitectura de la red neuronal y las características del problema que se desea resolver. Es beneficioso experimentar con diferentes técnicas de codificación para determinar cuál ofrece el mejor rendimiento para una tarea dada.
- Datos de texto: Requieren tokenización y embeddings, lo que implica:
- Dividir el texto en palabras o subpalabras individuales (tokens). Este proceso puede variar según el idioma y los requisitos específicos de la tarea. Por ejemplo, en inglés, una tokenización basada en espacios puede ser suficiente para muchas aplicaciones, mientras que idiomas más complejos pueden requerir tokenizadores especializados.
- Convertir los tokens en índices numéricos. Este paso crea un vocabulario donde a cada token único se le asigna un ID entero único. Esta conversión es necesaria porque las redes neuronales operan con datos numéricos.
- Aplicar embeddings de palabras para representaciones semánticas. Este paso crucial transforma los tokens en representaciones vectoriales densas que capturan relaciones semánticas entre palabras. Hay varios enfoques:
- Embeddings preentrenados: Utilizar modelos como Word2Vec, GloVe o FastText, entrenados en grandes corpus para capturar patrones generales del lenguaje.
- Embeddings específicos de la tarea: Entrenar embeddings desde cero en un conjunto de datos específico, lo que permite capturar relaciones semánticas específicas del dominio.
- Embeddings contextualizados: Usar modelos como BERT o GPT, que generan embeddings dinámicos basados en el contexto en el que aparece una palabra.
- Manejar palabras fuera del vocabulario (OOV): Implementar estrategias como usar un token especial "desconocido", emplear tokenización por subpalabras (e.g., WordPiece, Byte-Pair Encoding) o usar modelos a nivel de caracteres.
- Datos de series temporales: Requieren transformaciones especializadas para capturar patrones y dependencias temporales:
- Creación de características de desfase: Representan valores pasados de la variable objetivo u otras características relevantes. Por ejemplo, al predecir precios de acciones, se pueden incluir los precios del día, semana o mes anteriores como características.
- Aplicación de promedios móviles u otras estadísticas rodantes: Estas suavizan las fluctuaciones a corto plazo y destacan las tendencias a largo plazo. Las técnicas comunes incluyen promedios móviles simples, promedios móviles exponenciales y desviaciones estándar rodantes.
- Codificación de características cíclicas: Muchas series temporales tienen patrones cíclicos basados en períodos de tiempo. Por ejemplo:
- Día de la semana: Se puede codificar usando transformaciones seno y coseno para capturar la naturaleza circular de los patrones semanales.
- Mes del año: Codificado de manera similar para representar ciclos anuales.
- Hora del día: Útil para capturar patrones diarios en datos de alta frecuencia.
- Diferenciación: Tomar la diferencia entre pasos consecutivos puede ayudar a hacer estacionaria una serie temporal, lo cual es un requisito común para muchos modelos de series temporales.
- Descomposición: Separar una serie temporal en sus componentes de tendencia, estacionalidad y residuales puede proporcionar características valiosas para que el modelo aprenda.
- Datos de imágenes: Requieren preprocesamiento específico para garantizar un rendimiento óptimo en redes neuronales:
- Redimensionamiento a dimensiones consistentes: Este paso es crucial ya que las redes neuronales, particularmente las redes neuronales convolucionales (CNNs), requieren imágenes de entrada de tamaño uniforme. El redimensionamiento ayuda a estandarizar la entrada, permitiendo que la red procese imágenes de manera eficiente sin importar sus dimensiones originales.
- Normalización de valores de píxeles: Normalmente, esto implica escalar las intensidades de los píxeles a un rango de 0-1 o -1 a 1. La normalización es esencial porque:
- Ayuda a una convergencia más rápida durante el entrenamiento al asegurar que todas las características estén en una escala similar.
- Mitiga el impacto de condiciones de iluminación o configuraciones de cámara variables.
- Permite que el modelo trate las características de manera más equitativa, evitando que los píxeles de alta intensidad dominen.
- Aplicación de técnicas de aumento de datos: Esto es fundamental para aumentar la robustez del modelo y mejorar su capacidad de generalización. El aumento de datos amplía artificialmente el conjunto de entrenamiento creando versiones modificadas de imágenes existentes. Técnicas comunes incluyen:
- Transformaciones geométricas: Rotaciones, volteos, escalado y traslaciones.
- Aumentaciones del espacio de color: Ajustes de brillo, contraste o aplicación de modificaciones en el color.
- Adición de ruido o aplicación de filtros: Ruido gaussiano, desenfoque o efectos de nitidez.
- Mezcla de imágenes: Técnicas como mixup o CutMix que combinan múltiples imágenes de entrenamiento.
- Estandarización por canal: Para imágenes multicanal (e.g., RGB), a menudo es beneficioso estandarizar cada canal por separado.
- Manejo de datos faltantes o corruptos: Implementar estrategias para manejar imágenes incompletas o dañadas, como descartar, interpolar o usar modelos generativos para reconstruir partes faltantes.
Ejemplo: Limpieza y transformación de un conjunto de datos de muestra
Exploremos un ejemplo práctico utilizando Pandas para limpiar y preparar datos con valores faltantes y atípicos. Este proceso es crucial en la preprocesamiento de datos para modelos de aprendizaje profundo, ya que asegura la calidad y consistencia de los datos. Abordaremos paso a paso cómo manejar problemas comunes de datos:
- Valores faltantes: Demostraremos técnicas para imputar o eliminar puntos de datos faltantes, que pueden impactar significativamente el rendimiento del modelo si no se abordan.
- Atípicos: Exploraremos métodos para identificar y tratar valores atípicos, que pueden distorsionar distribuciones y afectar el entrenamiento del modelo.
- Transformación de datos: Mostraremos cómo convertir variables categóricas en un formato adecuado para redes neuronales.
Al final de este ejemplo, tendrás una comprensión clara de cómo aplicar estas técnicas esenciales de limpieza de datos utilizando Python y Pandas, sentando las bases para pasos más avanzados de ingeniería de características.
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
# Sample dataset
data = {
'age': [25, 30, np.nan, 35, 40, 100, 28, 45, np.nan, 50],
'income': [50000, 60000, 45000, 70000, np.nan, 200000, 55000, np.nan, 65000, 75000],
'category': ['A', 'B', np.nan, 'A', 'B', 'C', 'A', 'C', 'B', np.nan],
'education': ['High School', 'Bachelor', 'Master', np.nan, 'PhD', 'Bachelor', 'Master', 'High School', 'PhD', 'Bachelor']
}
df = pd.DataFrame(data)
# Display original data
print("Original Data:")
print(df)
print("\n")
# Define preprocessing steps for numerical and categorical columns
numeric_features = ['age', 'income']
categorical_features = ['category', 'education']
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='constant', fill_value='Unknown')),
('onehot', OneHotEncoder(handle_unknown='ignore'))
])
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
])
# Fit and transform the data
X_processed = preprocessor.fit_transform(df)
# Convert to DataFrame for better visualization
feature_names = (numeric_features +
preprocessor.named_transformers_['cat'].named_steps['onehot'].get_feature_names(categorical_features).tolist())
df_processed = pd.DataFrame(X_processed, columns=feature_names)
# Handle outliers (e.g., cap age at 99th percentile)
age_cap = np.percentile(df['age'].dropna(), 99)
df['age'] = np.where(df['age'] > age_cap, age_cap, df['age'])
print("Processed Data:")
print(df_processed)
# Additional statistics
print("\nData Statistics:")
print(df_processed.describe())
print("\nMissing Values After Processing:")
print(df_processed.isnull().sum())
print("\nUnique Values in Categorical Columns:")
for col in categorical_features:
print(f"{col}: {df[col].nunique()}")
Explicación del desglose del código:
- Importación de bibliotecas:
Importamos las bibliotecas necesarias:
pandas
para la manipulación de datos,numpy
para operaciones numéricas y varios módulos descikit-learn
para tareas de preprocesamiento. - Creación de un conjunto de datos de muestra:
Creamos un conjunto de datos más diverso con 10 entradas, incluyendo valores faltantes (
np.nan
) en diferentes columnas. Este conjunto de datos incluye una columna adicional llamadaeducation
para demostrar cómo manejar múltiples variables categóricas. - Visualización de los datos originales:
Imprimimos el conjunto de datos original para mostrar el estado inicial, incluidos los valores faltantes y posibles valores atípicos.
- Definición de los pasos de preprocesamiento:
Separamos nuestras características en columnas numéricas y categóricas. Luego, creamos pipelines de preprocesamiento para cada tipo:
- Para características numéricas: Usamos
SimpleImputer
para llenar valores faltantes con la mediana, y luego aplicamosStandardScaler
para normalizar los datos. - Para características categóricas: Usamos
SimpleImputer
para llenar valores faltantes con "Unknown", y luego aplicamosOneHotEncoder
para convertir las categorías en columnas binarias.
- Para características numéricas: Usamos
- Creación de un ColumnTransformer:
Usamos
ColumnTransformer
para aplicar diferentes pasos de preprocesamiento a distintas columnas, lo que nos permite manejar datos numéricos y categóricos simultáneamente. - Ajuste y transformación de datos:
Aplicamos nuestros pasos de preprocesamiento a todo el conjunto de datos usando
fit_transform()
. - Conversión a DataFrame:
Convertimos los datos procesados nuevamente en un
DataFrame
de pandas para facilitar su visualización y análisis. También creamos nombres de columnas apropiados para las variables categóricas codificadas con one-hot. - Manejo de valores atípicos:
En lugar de usar un valor fijo, limitamos la columna
age
al percentil 99. Este enfoque es más dinámico, ya que se adapta a la distribución de los datos. - Visualización de los datos procesados:
Imprimimos el conjunto de datos procesado para mostrar los resultados de los pasos de preprocesamiento.
- Estadísticas adicionales:
Proporcionamos más información sobre los datos procesados:
- Estadísticas básicas de los datos procesados utilizando
describe()
- Verificación de valores faltantes restantes
- Conteo de valores únicos en las columnas categóricas originales
Este ejemplo demuestra un enfoque robusto y completo para el preprocesamiento de datos para aprendizaje profundo. Maneja adecuadamente los valores faltantes, escala las características numéricas, codifica variables categóricas y aborda valores atípicos, mientras mantiene visibilidad clara de los datos en cada paso. Este enfoque es especialmente adecuado para escenarios del mundo real, donde los conjuntos de datos suelen incluir múltiples tipos de características y presentan varios desafíos de calidad de datos.
7.1.2 Paso 2: Escalado y Normalización
Las redes neuronales son altamente sensibles a la escala de los datos de entrada, lo que puede impactar significativamente su rendimiento y eficiencia. Las características con rangos muy diferentes pueden dominar el proceso de aprendizaje, lo que podría llevar a resultados sesgados o subóptimos. Para abordar este problema, los científicos de datos emplean técnicas de escalado y normalización, asegurando que todas las características de entrada contribuyan de manera equitativa al proceso de aprendizaje.
Existen dos métodos principales para este propósito:
Normalización
Esta técnica escala los datos a un rango específico, típicamente entre 0 y 1. La normalización es particularmente útil cuando se trabaja con características que tienen límites naturales, como valores de píxeles en imágenes (0-255) o métricas basadas en porcentajes (0-100%). Al mapear estos valores a un rango consistente, evitamos que las características con valores absolutos mayores eclipsen a aquellas con rangos más pequeños.
El proceso de normalización implica transformar los valores originales utilizando una fórmula matemática que mantiene las relaciones relativas entre los puntos de datos mientras los restringe dentro de un rango predeterminado. Esta transformación es especialmente beneficiosa en modelos de aprendizaje profundo por varias razones:
- Mejora de la convergencia del modelo: Las características normalizadas a menudo conducen a una convergencia más rápida y estable durante el entrenamiento, ya que el modelo no necesita aprender escalas muy diferentes para distintas características.
- Mayor interpretabilidad de las características: Cuando todas las características están en la misma escala, es más fácil interpretar su importancia relativa y su impacto en las predicciones del modelo.
- Mitigación de inestabilidad numérica: Los valores grandes pueden, en ocasiones, causar inestabilidad numérica en las redes neuronales, particularmente al usar funciones de activación como sigmoide o tangente hiperbólica. La normalización ayuda a prevenir estos problemas.
Las técnicas comunes de normalización incluyen el escalado Min-Max, que mapea el valor mínimo a 0 y el máximo a 1, y el escalado decimal, que mueve el punto decimal de los valores para crear un rango deseado. La elección del método de normalización a menudo depende de los requisitos específicos del modelo y la naturaleza de los datos que se están procesando.
Estandarización Este método reescala los datos para tener una media de cero y una desviación estándar de uno. La estandarización es especialmente beneficiosa al trabajar con conjuntos de datos que contienen características con escalas y distribuciones variables. Al centrar los datos alrededor de cero y escalarlos a una varianza unitaria, la estandarización garantiza que cada característica contribuya proporcionalmente al proceso de aprendizaje del modelo, independientemente de su escala original.
El proceso de estandarización implica restar el valor medio de cada característica de los puntos de datos y luego dividir por la desviación estándar. Esta transformación resulta en una distribución donde aproximadamente el 68% de los valores caen dentro de una desviación estándar de la media, el 95% dentro de dos desviaciones estándar y el 99.7% dentro de tres desviaciones estándar.
La estandarización ofrece varias ventajas en el contexto del aprendizaje profundo:
- Mejora del descenso del gradiente: Las características estandarizadas a menudo conducen a una convergencia más rápida durante la optimización, ya que el algoritmo de descenso del gradiente puede navegar más fácilmente por el espacio de características.
- Importancia de las características: Cuando las características están estandarizadas, sus coeficientes en el modelo pueden compararse directamente para evaluar su importancia relativa.
- Manejo de valores atípicos: La estandarización puede ayudar a mitigar el impacto de los valores atípicos al escalarlos en relación con la desviación estándar de la característica.
Sin embargo, es importante tener en cuenta que la estandarización no limita los valores a un rango específico, lo que puede ser una consideración para ciertas arquitecturas de redes neuronales o al trabajar con características que tienen límites naturales.
La elección entre normalización y estandarización a menudo depende de las características específicas del conjunto de datos y los requisitos de la arquitectura de la red neuronal. Por ejemplo:
- Las redes neuronales convolucionales (CNNs) para el procesamiento de imágenes suelen funcionar bien con datos normalizados, ya que los valores de píxeles naturalmente caen dentro de un rango fijo.
- Las redes neuronales recurrentes (RNNs) y otras arquitecturas que trabajan con series temporales o datos tabulares suelen beneficiarse de la estandarización, especialmente cuando las características tienen diferentes unidades o escalas.
Es importante destacar que el escalado debe aplicarse de manera consistente en los conjuntos de entrenamiento, validación y prueba para mantener la integridad de la evaluación del rendimiento del modelo. Además, al trabajar con datos nuevos y no vistos durante la inferencia, es crucial aplicar los mismos parámetros de escalado utilizados durante el entrenamiento para garantizar la consistencia en las predicciones del modelo.
Ejemplo: Escalado y normalización de características Profundicemos en el escalado de características numéricas utilizando dos métodos populares de Scikit-Learn: StandardScaler
y MinMaxScaler
. Estas técnicas son cruciales para preparar los datos para redes neuronales, ya que ayudan a garantizar que todas las características contribuyan de manera equitativa al proceso de aprendizaje del modelo.
StandardScaler
transforma los datos para tener una media de 0 y una desviación estándar de 1. Esto es particularmente útil cuando tus características tienen diferentes unidades o escalas. Por ejemplo, si tienes características como edad (0-100) e ingresos (de miles a millones), StandardScaler
las llevará a una escala comparable.
Por otro lado, MinMaxScaler
escala los datos a un rango fijo, típicamente entre 0 y 1. Esto es beneficioso cuando necesitas que tus características tengan un rango específico y delimitado, lo cual puede ser importante para ciertos algoritmos o cuando deseas preservar valores cero en datos dispersos.
La elección entre estos escaladores a menudo depende de la naturaleza de tus datos y los requisitos de tu red neuronal. En el siguiente ejemplo, demostraremos cómo aplicar ambas técnicas de escalado a un conjunto de datos de muestra.
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
import matplotlib.pyplot as plt
# Sample data
X = np.array([[25, 50000], [30, 60000], [35, 70000], [40, 80000], [45, 90000], [50, 100000], [55, 110000], [60, 120000]])
df = pd.DataFrame(X, columns=['Age', 'Income'])
# Standardization
scaler = StandardScaler()
X_standardized = scaler.fit_transform(X)
df_standardized = pd.DataFrame(X_standardized, columns=['Age_std', 'Income_std'])
# Normalization (Min-Max Scaling)
normalizer = MinMaxScaler()
X_normalized = normalizer.fit_transform(X)
df_normalized = pd.DataFrame(X_normalized, columns=['Age_norm', 'Income_norm'])
# Robust Scaling
robust_scaler = RobustScaler()
X_robust = robust_scaler.fit_transform(X)
df_robust = pd.DataFrame(X_robust, columns=['Age_robust', 'Income_robust'])
# Combine all scaled data
df_combined = pd.concat([df, df_standardized, df_normalized, df_robust], axis=1)
# Display results
print("Combined Data:")
print(df_combined)
# Visualize the scaling effects
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
fig.suptitle('Comparison of Scaling Techniques')
axes[0, 0].scatter(df['Age'], df['Income'])
axes[0, 0].set_title('Original Data')
axes[0, 1].scatter(df_standardized['Age_std'], df_standardized['Income_std'])
axes[0, 1].set_title('Standardized Data')
axes[1, 0].scatter(df_normalized['Age_norm'], df_normalized['Income_norm'])
axes[1, 0].set_title('Normalized Data')
axes[1, 1].scatter(df_robust['Age_robust'], df_robust['Income_robust'])
axes[1, 1].set_title('Robust Scaled Data')
for ax in axes.flat:
ax.set(xlabel='Age', ylabel='Income')
plt.tight_layout()
plt.show()
Explicación del desglose del código
- Importación de bibliotecas:
Se importan
numpy
para operaciones numéricas,pandas
para manipulación de datos,sklearn
para herramientas de preprocesamiento ymatplotlib
para visualización. - Creación de datos de muestra:
Se crea un conjunto de datos más amplio con 8 entradas, incluyendo datos de edad e ingresos. Esto proporciona un conjunto de datos más completo para demostrar los efectos del escalado.
- Estandarización (
StandardScaler
):- Transforma las características para tener una media de 0 y una desviación estándar de 1.
- Es útil cuando las características tienen diferentes escalas o unidades.
- Fórmula: z = (x - μ) / σ, donde μ es la media y σ es la desviación estándar.
- Normalización (
MinMaxScaler
):- Escala las características a un rango fijo, típicamente entre 0 y 1.
- Preserva valores cero y no centra los datos.
- Fórmula: x_scaled = (x - x_min) / (x_max - x_min).
- Escalado robusto (
RobustScaler
):- Escala las características utilizando estadísticas robustas a valores atípicos.
- Utiliza la mediana y el rango intercuartil en lugar de la media y la desviación estándar.
- Es útil cuando los datos contienen muchos valores atípicos.
- Combinación de datos:
Se combinan los conjuntos de datos originales y escalados en un único
DataFrame
para facilitar la comparación. - Visualización:
- Se crea una cuadrícula de gráficos de dispersión 2x2 para visualizar los efectos de las diferentes técnicas de escalado.
- Esto permite una comparación directa de cómo cada método transforma los datos.
Puntos clave:
StandardScaler
centra los datos y los escala a una varianza unitaria, como se observa en el gráfico estandarizado donde los datos están centrados alrededor de (0,0).MinMaxScaler
comprime todos los puntos de datos a un rango fijo [0,1], manteniendo la forma de la distribución original.RobustScaler
produce un resultado similar aStandardScaler
, pero es menos influenciado por valores atípicos.
Este ejemplo ofrece un examen exhaustivo de varias técnicas de escalado, su impacto en los datos y métodos para visualizar estas transformaciones. Es especialmente valioso para comprender cómo los enfoques de escalado afectan tu conjunto de datos antes de ingresarlo en una red neuronal.
7.1.3 Paso 3: Codificación de variables categóricas
Los datos categóricos requieren codificación antes de ser introducidos en una red neuronal. Este proceso transforma datos no numéricos en un formato que las redes neuronales pueden procesar eficazmente. Existen varias técnicas de codificación, cada una con sus fortalezas y casos de uso:
Codificación One-Hot
Este método transforma variables categóricas en un formato que las redes neuronales pueden procesar de manera efectiva. Crea un vector binario para cada categoría, donde cada valor único de la categoría se representa mediante una columna separada. Por ejemplo, considera una categoría "color" con valores "rojo", "azul" y "verde". La codificación one-hot generaría tres nuevas columnas: "color_rojo", "color_azul" y "color_verde". En cada fila, la columna correspondiente al color presente contendría un 1, mientras que las otras serían 0.
Esta técnica de codificación es particularmente valiosa para categorías nominales que carecen de un orden inherente. Al crear columnas binarias separadas para cada categoría, la codificación one-hot evita imponer relaciones numéricas artificiales entre las categorías. Esto es crucial porque las redes neuronales podrían interpretar las codificaciones numéricas como si tuvieran un orden o magnitud significativos.
Sin embargo, la codificación one-hot presenta algunas consideraciones importantes:
- Dimensionalidad: Para categorías con muchos valores únicos, la codificación one-hot puede aumentar significativamente el número de características de entrada, lo que podría conducir a la "maldición de la dimensionalidad".
- Esparcimiento: Los datos codificados resultantes pueden ser dispersos, con muchos valores 0, lo que podría afectar la eficiencia de algunos algoritmos.
- Manejo de nuevas categorías: La codificación one-hot puede enfrentar problemas con categorías nuevas y no vistas en datos de prueba o de producción que no estaban presentes durante el entrenamiento.
A pesar de estos desafíos, la codificación one-hot sigue siendo un método popular y efectivo para preparar datos categóricos para redes neuronales, especialmente al trabajar con categorías nominales de baja a moderada cardinalidad.
Aquí tienes un ejemplo de cómo implementar la codificación one-hot utilizando Python y la biblioteca pandas
.
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green'],
'size': ['small', 'medium', 'large', 'medium', 'small']
})
# Initialize the OneHotEncoder
encoder = OneHotEncoder(sparse=False)
# Fit and transform the data
encoded_data = encoder.fit_transform(data)
# Get feature names
feature_names = encoder.get_feature_names_out(['color', 'size'])
# Create a new DataFrame with encoded data
encoded_df = pd.DataFrame(encoded_data, columns=feature_names)
print("Original data:")
print(data)
print("\nOne-hot encoded data:")
print(encoded_df)
Explicación del desglose del código
- Importar las bibliotecas necesarias: Importamos
pandas
para la manipulación de datos yOneHotEncoder
desklearn
para la codificación one-hot. - Crear datos de muestra: Creamos un DataFrame simple con dos columnas categóricas: "color" y "size".
- Inicializar
OneHotEncoder
: Creamos una instancia deOneHotEncoder
consparse=False
para obtener una salida en forma de matriz densa en lugar de una matriz dispersa. - Ajustar y transformar los datos: Usamos el método
fit_transform
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Obtener nombres de características: Usamos
get_feature_names_out
para obtener los nombres de las nuevas columnas codificadas. - Crear un nuevo DataFrame: Creamos un nuevo DataFrame con los datos codificados, utilizando los nombres de las características como etiquetas de las columnas.
- Imprimir resultados: Mostramos tanto los datos originales como los codificados para comparación.
Este código demuestra cómo la codificación one-hot transforma las variables categóricas en un formato adecuado para modelos de aprendizaje automático, incluidas las redes neuronales. Cada valor único de categoría se convierte en una columna separada, con valores binarios que indican la presencia (1) o ausencia (0) de esa categoría en cada fila.
Cuando ejecutas este código, puedes observar cómo los datos categóricos originales se transforman en un formato codificado one-hot, donde cada valor único de categoría tiene su propia columna con indicadores binarios.
Codificación por etiquetas
Esta técnica asigna a cada categoría un número entero único. Por ejemplo, "rojo" podría codificarse como 0, "azul" como 1 y "verde" como 2. Aunque es eficiente en términos de uso de memoria, la codificación por etiquetas es más adecuada para datos ordinales (categorías con un orden significativo). Es importante tener en cuenta que las redes neuronales podrían interpretar el orden de las etiquetas como significativo, lo que puede llevar a suposiciones incorrectas en categorías nominales.
La codificación por etiquetas es particularmente útil al trabajar con variables ordinales, donde el orden de las categorías importa. Por ejemplo, al codificar niveles educativos (e.g., "Secundaria", "Licenciatura", "Maestría", "Doctorado"), la codificación por etiquetas preserva el orden inherente, lo cual puede ser significativo para el modelo.
Sin embargo, la codificación por etiquetas tiene limitaciones cuando se aplica a categorías nominales (aquellas sin un orden inherente). Por ejemplo, codificar razas de perros como números (e.g., Labrador = 0, Poodle = 1, Beagle = 2) podría llevar al modelo a inferir incorrectamente que la diferencia numérica entre razas tiene un significado.
La implementación de la codificación por etiquetas es sencilla utilizando bibliotecas como scikit-learn
.
import pandas as pd
from sklearn.preprocessing import LabelEncoder
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green', 'blue', 'yellow'],
'size': ['small', 'medium', 'large', 'medium', 'small', 'large', 'medium']
})
# Initialize LabelEncoder
le_color = LabelEncoder()
le_size = LabelEncoder()
# Fit and transform the data
data['color_encoded'] = le_color.fit_transform(data['color'])
data['size_encoded'] = le_size.fit_transform(data['size'])
print("Original and encoded data:")
print(data)
print("\nUnique categories and their encoded values:")
print("Colors:", dict(zip(le_color.classes_, le_color.transform(le_color.classes_))))
print("Sizes:", dict(zip(le_size.classes_, le_size.transform(le_size.classes_))))
# Demonstrate inverse transform
color_codes = [0, 1, 2, 3]
size_codes = [0, 1, 2]
print("\nDecoding back to original categories:")
print("Colors:", le_color.inverse_transform(color_codes))
print("Sizes:", le_size.inverse_transform(size_codes))
Explicación del desglose del código
- Importación de bibliotecas:
- Importamos
pandas
para la manipulación de datos yLabelEncoder
desklearn
para codificar variables categóricas.
- Importamos
- Creación de datos de muestra:
- Creamos un DataFrame con dos columnas categóricas: "color" y "size".
- Este ejemplo incluye datos más diversos para demostrar mejor el proceso de codificación.
- Inicialización de
LabelEncoder
:- Creamos dos instancias separadas de
LabelEncoder
, una para "color" y otra para "size". - Esto nos permite codificar cada categoría de forma independiente.
- Creamos dos instancias separadas de
- Ajuste y transformación de datos:
- Usamos
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Los valores codificados se añaden como nuevas columnas en el DataFrame.
- Usamos
- Visualización de resultados:
- Imprimimos los datos originales junto con los datos codificados para facilitar la comparación.
- Mostrar los mapeos de codificación:
- Creamos diccionarios para mostrar cómo cada categoría única se mapea a su valor codificado.
- Esto ayuda a comprender e interpretar los datos codificados.
- Demostración de transformación inversa:
- Mostramos cómo decodificar los valores numéricos de nuevo a sus categorías originales.
- Esto es útil cuando necesitas convertir predicciones o datos codificados a un formato comprensible para los humanos.
Este ejemplo proporciona una visión completa de la codificación por etiquetas. Demuestra cómo manejar múltiples variables categóricas, muestra el mapeo entre las categorías originales y los valores codificados, e incluye el proceso de transformación inversa. Este enfoque ofrece una comprensión más profunda de cómo funciona la codificación por etiquetas y cómo puede aplicarse en escenarios del mundo real.
Al utilizar la codificación por etiquetas, es crucial documentar el esquema de codificación y garantizar una aplicación consistente en los conjuntos de datos de entrenamiento, validación y prueba. Además, para modelos sensibles a la magnitud de las características de entrada (como redes neuronales), puede ser necesario escalar los valores codificados para evitar que el modelo atribuya una importancia indebida a las categorías con representaciones numéricas mayores.
Codificación Binaria
Este método combina aspectos tanto de la codificación one-hot como de la codificación por etiquetas, ofreciendo un equilibrio entre eficiencia e información preservada. Opera en dos pasos:
- Asignación de enteros: A cada categoría única se le asigna un entero, similar a la codificación por etiquetas.
- Conversión a binario: El entero asignado se convierte en su representación binaria.
Por ejemplo, si tenemos las categorías A, B, C y D, podrían asignarse los enteros 0, 1, 2 y 3 respectivamente. En binario, estos se representarían como 00, 01, 10 y 11.
Las ventajas de la codificación binaria incluyen:
- Eficiencia de memoria: Requiere menos columnas que la codificación one-hot, especialmente para categorías con muchos valores únicos. Para n categorías, la codificación binaria utiliza log2(n) columnas, mientras que la codificación one-hot utiliza n columnas.
- Preservación de información: A diferencia de la codificación por etiquetas, no impone una relación ordinal arbitraria entre categorías.
- Reducción de dimensionalidad: Crea menos características nuevas en comparación con la codificación one-hot, lo que puede ser beneficioso para el entrenamiento del modelo y la reducción del sobreajuste.
Sin embargo, la codificación binaria también tiene algunas consideraciones:
- Interpretación: Las características binarias resultantes pueden ser menos interpretables que las características codificadas one-hot.
- Compatibilidad con modelos: No todos los modelos pueden manejar características codificadas binariamente de manera óptima, por lo que es importante considerar los requisitos específicos de tu algoritmo elegido.
La codificación binaria es particularmente útil en escenarios donde se manejan variables categóricas de alta cardinalidad y la eficiencia de memoria es una preocupación, como en aplicaciones de aprendizaje automático a gran escala o cuando se trabaja con recursos computacionales limitados.
Aquí tienes un ejemplo de cómo implementar la codificación binaria utilizando Python y la biblioteca category_encoders
.
import pandas as pd
import category_encoders as ce
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green', 'blue', 'yellow'],
'size': ['small', 'medium', 'large', 'medium', 'small', 'large', 'medium']
})
# Initialize BinaryEncoder
encoder = ce.BinaryEncoder(cols=['color', 'size'])
# Fit and transform the data
encoded_data = encoder.fit_transform(data)
print("Original data:")
print(data)
print("\nBinary encoded data:")
print(encoded_data)
# Display mapping
print("\nEncoding mapping:")
print(encoder.mapping)
Explicación del desglose del código
- Importar bibliotecas:
- Importamos
pandas
para la manipulación de datos ycategory_encoders
para la codificación binaria.
- Importamos
- Crear datos de muestra:
- Creamos un DataFrame con dos columnas categóricas: "color" y "size".
- Inicializar
BinaryEncoder
:- Creamos una instancia de
BinaryEncoder
, especificando qué columnas codificar.
- Creamos una instancia de
- Ajustar y transformar datos:
- Usamos
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso.
- Usamos
- Visualizar resultados:
- Imprimimos los datos originales y los datos codificados binariamente para comparación.
- Mostrar mapeo de codificación:
- Mostramos el mapeo para ver cómo cada categoría se codifica en binario.
Cuando ejecutas este código, puedes observar cómo cada categoría única en "color" y "size" se transforma en un conjunto de columnas binarias. El número de columnas binarias para cada característica depende del número de categorías únicas en esa característica.
La codificación binaria proporciona una representación compacta de variables categóricas, especialmente útil para características de alta cardinalidad. Encuentra un equilibrio entre la explosión dimensional de la codificación one-hot y las suposiciones ordinales de la codificación por etiquetas, lo que la convierte en una herramienta valiosa en la ingeniería de características para aprendizaje profundo.
Embeddings
Para variables categóricas con alta cardinalidad (muchos valores únicos), los embeddings pueden ser una solución efectiva. Esta técnica aprende una representación vectorial de baja dimensión para cada categoría durante el proceso de entrenamiento de la red neuronal. Los embeddings pueden capturar relaciones complejas entre categorías y se utilizan comúnmente en tareas de procesamiento de lenguaje natural.
Los embeddings funcionan mapeando cada categoría a un vector denso en un espacio vectorial continuo. A diferencia de la codificación one-hot, que trata cada categoría como completamente distinta, los embeddings permiten comparaciones significativas entre categorías basadas en sus representaciones vectoriales aprendidas. Esto es particularmente útil al trabajar con grandes vocabularios en datos de texto o con variables categóricas que tienen similitudes o jerarquías inherentes.
La dimensionalidad del espacio de embeddings es un hiperparámetro que puede ajustarse. Por lo general, es mucho menor que el número de categorías únicas, lo que ayuda a reducir la complejidad del modelo y mitigar la maldición de la dimensionalidad. Por ejemplo, una variable categórica con 10,000 valores únicos podría incrustarse en un espacio de 50 o 100 dimensiones.
Una de las principales ventajas de los embeddings es su capacidad de generalización. Pueden capturar relaciones semánticas entre categorías, permitiendo que el modelo realice predicciones inteligentes incluso para categorías que no ha visto durante el entrenamiento. Esto es especialmente valioso en sistemas de recomendación, donde los embeddings pueden representar usuarios y elementos en un espacio compartido, facilitando el descubrimiento de preferencias y similitudes latentes.
En el contexto del aprendizaje profundo para datos tabulares, los embeddings pueden aprenderse como parte de la arquitectura de la red neuronal. Esto permite que el modelo descubra automáticamente representaciones óptimas para variables categóricas, adaptadas a la tarea específica. Los embeddings aprendidos también pueden visualizarse o analizarse por separado, proporcionando potencialmente ideas sobre las relaciones entre categorías que podrían no ser evidentes en los datos originales.
Aquí tienes un ejemplo de cómo implementar embeddings para variables categóricas utilizando TensorFlow/Keras.
import tensorflow as tf
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
# Sample data
data = pd.DataFrame({
'user_id': np.random.randint(1, 1001, 10000),
'product_id': np.random.randint(1, 501, 10000),
'purchase': np.random.randint(0, 2, 10000)
})
# Prepare features and target
X = data[['user_id', 'product_id']]
y = data['purchase']
# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Define the model
user_input = tf.keras.layers.Input(shape=(1,))
product_input = tf.keras.layers.Input(shape=(1,))
user_embedding = tf.keras.layers.Embedding(input_dim=1001, output_dim=50)(user_input)
product_embedding = tf.keras.layers.Embedding(input_dim=501, output_dim=50)(product_input)
user_vec = tf.keras.layers.Flatten()(user_embedding)
product_vec = tf.keras.layers.Flatten()(product_embedding)
concat = tf.keras.layers.Concatenate()([user_vec, product_vec])
dense = tf.keras.layers.Dense(64, activation='relu')(concat)
output = tf.keras.layers.Dense(1, activation='sigmoid')(dense)
model = tf.keras.Model(inputs=[user_input, product_input], outputs=output)
# Compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# Train the model
model.fit([X_train['user_id'], X_train['product_id']], y_train,
epochs=5, batch_size=32, validation_split=0.2)
# Evaluate the model
loss, accuracy = model.evaluate([X_test['user_id'], X_test['product_id']], y_test)
print(f"Test Accuracy: {accuracy:.4f}")
Explicación del desglose del código
- Preparación de datos:
- Creamos un conjunto de datos de muestra con IDs de usuarios, IDs de productos e información de compras.
- Los datos se dividen en conjuntos de entrenamiento y prueba.
- Arquitectura del modelo:
- Definimos capas de entrada separadas para
user_id
yproduct_id
. - Se crean capas de embeddings para los IDs de usuarios y productos. El
input_dim
se establece como el número de categorías únicas más uno (para considerar el posible indexado en cero), y eloutput_dim
se fija en 50 (la dimensión del embedding). - Los vectores embebidos se aplanan y concatenan.
- Se añaden capas densas para un procesamiento adicional, con una activación final sigmoide para clasificación binaria.
- Definimos capas de entrada separadas para
- Compilación y entrenamiento del modelo:
- El modelo se compila utilizando la pérdida de entropía cruzada binaria y el optimizador Adam.
- El modelo se entrena con los datos preparados.
- Evaluación:
- Se evalúa el rendimiento del modelo en el conjunto de prueba.
Este ejemplo demuestra cómo se pueden usar embeddings para representar variables categóricas de alta cardinalidad (IDs de usuarios y productos) en un espacio de menor dimensión. Las capas de embeddings aprenden a mapear cada ID único a un vector de 50 dimensiones durante el proceso de entrenamiento. Estos embeddings capturan relaciones significativas entre usuarios y productos, lo que permite al modelo realizar predicciones basadas en estas representaciones latentes.
Las principales ventajas de usar embeddings en este escenario incluyen:
- Reducción de dimensionalidad: En lugar de usar codificación one-hot, que resultaría en vectores dispersos de alta dimensionalidad, los embeddings proporcionan una representación densa y de menor dimensión.
- Captura de relaciones semánticas: El espacio de embeddings puede capturar similitudes entre usuarios o productos, incluso si no han sido vistos juntos en los datos de entrenamiento.
- Escalabilidad: Este enfoque se adapta bien a un gran número de categorías, lo que lo hace adecuado para aplicaciones del mundo real con muchos usuarios y productos.
Al usar embeddings, permitimos que la red neuronal aprenda representaciones óptimas de nuestras variables categóricas, específicamente adaptadas a la tarea de predecir compras. Esto puede conducir a un mejor rendimiento del modelo y una mejor generalización a datos no vistos.
La elección del método de codificación depende de la naturaleza de tus datos categóricos, los requisitos específicos de la arquitectura de tu red neuronal y el problema que estás tratando de resolver. Es beneficioso experimentar con diferentes técnicas de codificación para determinar cuál ofrece el mejor rendimiento para tu caso particular.
Preparar datos para redes neuronales es un proceso intrincado pero crucial que incluye limpieza, escalado y codificación de datos. Los datos correctamente transformados y escalados mejoran el proceso de aprendizaje, permitiendo que las redes neuronales converjan más rápido y ofrezcan resultados más precisos. Al garantizar que cada característica se maneje adecuadamente, ya sea escalando valores numéricos o codificando categorías, creamos una base sólida para un modelo de aprendizaje profundo exitoso.
7.1 Preparación de Datos para Redes Neuronales
El aprendizaje profundo ha revolucionado el campo de la ciencia de datos, ofreciendo herramientas sofisticadas capaces de manejar grandes cantidades de datos y descubrir patrones complejos. Estas redes neuronales avanzadas han demostrado capacidades notables en diversos dominios, desde el reconocimiento de imágenes y voz hasta el procesamiento de lenguaje natural y los sistemas autónomos. El poder del aprendizaje profundo radica en su capacidad para aprender automáticamente representaciones jerárquicas de los datos, permitiéndole capturar relaciones intrincadas y patrones que pueden ser difíciles de discernir para los humanos.
Sin embargo, la efectividad de los modelos de aprendizaje profundo depende en gran medida de la calidad y preparación de los datos de entrada. Esta dependencia resalta la importancia continua de la ingeniería de características, incluso en la era de las redes neuronales. Aunque los algoritmos de aprendizaje profundo pueden a menudo extraer características significativas a partir de datos en bruto, el proceso de preparar y estructurar estos datos sigue siendo crucial para un rendimiento óptimo.
A diferencia de los modelos tradicionales de aprendizaje automático que a menudo requieren una amplia ingeniería de características manual, las redes de aprendizaje profundo están diseñadas para aprender representaciones de alto nivel directamente de datos en bruto. Esta capacidad ha reducido significativamente la necesidad de características diseñadas a mano en muchas aplicaciones. Por ejemplo, en tareas de visión por computadora, las redes neuronales convolucionales pueden aprender automáticamente a detectar bordes, formas y objetos complejos a partir de datos de píxeles en bruto, eliminando la necesidad de extracción manual de características.
No obstante, garantizar que los datos de entrada estén bien estructurados, normalizados y sean relevantes es fundamental para mejorar el rendimiento y la estabilidad del modelo. Una preparación adecuada de los datos puede impactar significativamente en el proceso de aprendizaje, afectando factores como la velocidad de convergencia, la capacidad de generalización y la precisión general. Por ejemplo, en tareas de procesamiento de lenguaje natural, pasos de preprocesamiento como la tokenización, la eliminación de palabras vacías y el manejo de palabras fuera del vocabulario pueden influir enormemente en la capacidad del modelo para comprender y generar texto.
En este capítulo, profundizaremos en los aspectos esenciales de la ingeniería de características para aprendizaje profundo, cubriendo una amplia gama de técnicas para preparar datos, gestionar escalas de características y optimizar datos para redes neuronales. Exploraremos cómo estas metodologías pueden aplicarse a diferentes tipos de datos y dominios de problemas para maximizar el potencial de los modelos de aprendizaje profundo.
Comenzando con la preparación de datos, discutiremos las mejores prácticas para limpiar y transformar los datos para que sean compatibles con las redes neuronales. Esta sección cubrirá técnicas como el manejo de valores faltantes, el tratamiento de valores atípicos y el abordaje de desequilibrios en las clases. También exploraremos consideraciones específicas para preparar datos estructurados (por ejemplo, conjuntos de datos tabulares), datos de imágenes (por ejemplo, redimensionamiento, aumento) y datos de texto (por ejemplo, tokenización, incrustaciones).
Además, examinaremos técnicas avanzadas de ingeniería de características que pueden mejorar los modelos de aprendizaje profundo, tales como:
- Métodos de escalado y normalización de características para garantizar que todas las entradas contribuyan de manera equitativa al proceso de aprendizaje.
- Técnicas de reducción de dimensionalidad como Análisis de Componentes Principales (PCA) y t-SNE para datos de alta dimensión.
- Ingeniería de características específica de series temporales, incluyendo características de retraso y estadísticas rodantes.
- Métodos para manejar variables categóricas, como capas de incrustación para características de alta cardinalidad.
- Incorporación de conocimiento del dominio en la ingeniería de características para guiar el proceso de aprendizaje.
Dominando estas técnicas de ingeniería de características, los científicos de datos y practicantes de aprendizaje automático pueden mejorar significativamente el rendimiento y la robustez de sus modelos de aprendizaje profundo en una amplia gama de aplicaciones y dominios.
Preparar datos para redes neuronales es un proceso crítico que exige una meticulosa atención a los detalles. Esta preparación implica estructurar, escalar y formatear cuidadosamente los datos para optimizar el rendimiento de los modelos de aprendizaje profundo. Las redes neuronales están diseñadas fundamentalmente para procesar información en forma de matrices numéricas, lo que exige la conversión de todos los datos de entrada a un formato numérico consistente.
La importancia del preprocesamiento de datos en aprendizaje profundo no puede subestimarse. A diferencia de los algoritmos tradicionales de aprendizaje automático, las redes neuronales muestran una sensibilidad elevada a las variaciones en la distribución de los datos. Esta sensibilidad hace que los pasos de preprocesamiento, como el escalado y la codificación, no solo sean beneficiosos, sino esenciales para lograr un rendimiento óptimo. Estas medidas preparatorias garantizan que la red neuronal pueda aprender eficazmente de todas las características disponibles sin verse influenciada desproporcionadamente por una única entrada.
Para abordar este proceso de manera sistemática, podemos descomponer la preparación de datos para redes neuronales en tres pasos principales:
- Limpieza y Transformación de Datos: Este paso inicial implica identificar y abordar problemas como valores faltantes, valores atípicos e inconsistencias en el conjunto de datos. También puede incluir la selección o creación de características para garantizar que los datos de entrada sean relevantes e informativos para la tarea.
- Escalado y Normalización: Este paso asegura que todas las características numéricas estén en una escala similar, evitando que las características con magnitudes mayores dominen el proceso de aprendizaje. Las técnicas comunes incluyen escalado min-max, estandarización y escalado robusto.
- Codificación de Variables Categóricas: Dado que las redes neuronales operan sobre datos numéricos, las variables categóricas deben convertirse a un formato numérico. Esto a menudo implica técnicas como la codificación one-hot, la codificación ordinal o métodos más avanzados como las incrustaciones de entidades para variables categóricas de alta cardinalidad.
Al ejecutar meticulosamente estos pasos preparatorios, los científicos de datos pueden mejorar significativamente la eficiencia y efectividad de sus modelos de aprendizaje profundo, allanando el camino para predicciones e insights más precisos.
7.1.1 Paso 1: Limpieza y Transformación de Datos
El primer paso en la preparación de datos para una red neuronal es un proceso crítico que implica garantizar que todas las características estén bien definidas, libres de ruido y sean relevantes para la tarea. Esta etapa inicial establece la base para un entrenamiento y rendimiento exitosos del modelo. Incluye un examen exhaustivo del conjunto de datos para identificar y abordar posibles problemas que puedan obstaculizar el proceso de aprendizaje.
Las características bien definidas son aquellas que tienen significados claros e interpretaciones dentro del contexto del problema. Esto a menudo requiere experiencia en el dominio para comprender qué atributos son más propensos a contribuir al poder predictivo del modelo. Las características deben seleccionarse o diseñarse para capturar la esencia del problema que se está resolviendo.
Eliminar el ruido de los datos es crucial, ya que las redes neuronales pueden ser sensibles a variaciones irrelevantes. El ruido puede presentarse en diversas formas, como errores de medición, valores atípicos o información irrelevante. Las técnicas como el suavizado, la detección de valores atípicos y la selección de características pueden emplearse para reducir el ruido y mejorar la relación señal-ruido en el conjunto de datos.
Asegurar la relevancia de las características implica centrarse en los atributos que tienen más probabilidades de contribuir al poder predictivo del modelo. Esto puede involucrar técnicas de selección de características, la aplicación de conocimiento del dominio o incluso la creación de nuevas características mediante ingeniería de características. Las características relevantes ayudan al modelo a aprender patrones y relaciones significativas, lo que lleva a una mejor generalización y rendimiento en datos no vistos.
Al abordar meticulosamente estos aspectos en el paso inicial de la preparación de datos, establecemos una base sólida para las etapas posteriores de escalado, normalización y codificación, mejorando finalmente la capacidad de la red neuronal para aprender eficazmente de los datos.
Transformaciones Comunes
- Manejo de Valores Faltantes:
- Las redes neuronales requieren conjuntos de datos completos para un rendimiento óptimo. Los valores faltantes pueden llevar a predicciones sesgadas o inexactas, haciendo que su manejo sea crucial.
- Estrategias comunes para abordar datos faltantes incluyen:
- Imputación: Rellenar valores faltantes con estimaciones. Los métodos varían desde simples (imputación de media, mediana o moda) hasta más complejos (imputación por regresión o imputación múltiple).
- Eliminación: Remover filas o columnas con valores faltantes. Este enfoque es sencillo, pero puede llevar a una pérdida significativa de datos si la falta es prevalente.
- Uso de algoritmos que manejen valores faltantes: Algunos métodos avanzados, como ciertos árboles de decisión, pueden trabajar directamente con datos faltantes.
- Específicamente para aprendizaje profundo:
- Datos numéricos: La imputación por media es frecuentemente utilizada debido a su simplicidad y efectividad, aunque métodos más sofisticados como imputación k-NN o el uso de autoencoders pueden dar mejores resultados.
- Datos categóricos: Crear una nueva categoría para valores faltantes es común, permitiendo al modelo aprender patrones relacionados con la falta de datos.
- En modelos secuenciales, una capa de enmascaramiento puede ignorar valores faltantes durante el entrenamiento y la predicción.
- Eliminación de Valores Atípicos:
- Los valores atípicos pueden impactar significativamente el rendimiento de las redes neuronales, llevando a un aprendizaje inestable y a una generalización deficiente. Identificar y abordar valores atípicos es crucial para mantener la consistencia de los datos y mejorar la robustez del modelo.
- Estrategias para manejar valores atípicos incluyen:
- Eliminación: En algunos casos, eliminar completamente puntos de datos identificados como valores atípicos puede ser apropiado, aunque debe hacerse con precaución para evitar perder información valiosa.
- Transformación: Aplicar transformaciones matemáticas como logaritmos o raíces cuadradas puede ayudar a reducir el impacto de valores extremos mientras se preserva el punto de datos.
- Winsorización: Esta técnica consiste en limitar valores extremos a un percentil específico de los datos, reduciendo efectivamente su impacto sin eliminarlos por completo.
- Para características numéricas, implementar una estrategia de límites puede ser particularmente efectiva:
- Establecer límites superiores e inferiores basados en conocimiento del dominio o medidas estadísticas (p. ej., 3 desviaciones estándar de la media).
- Reemplazar valores que excedan estos límites con los valores límite respectivos.
- Esta aproximación preserva la distribución general mientras mitiga el efecto de valores atípicos extremos.
- Es importante destacar que la elección del método para manejar valores atípicos puede impactar significativamente el rendimiento del modelo. Por lo tanto, es beneficioso experimentar con diferentes enfoques y evaluar sus efectos en los resultados del modelo.
- Transformando características para compatibilidad con redes neuronales
Las redes neuronales requieren características de entrada numéricas para un procesamiento óptimo. Esto hace necesario transformar varios tipos de datos:
- Características categóricas: Estas deben codificarse en representaciones numéricas para ser compatibles con las redes neuronales. Métodos comunes incluyen:
- Codificación one-hot: Crea columnas binarias para cada categoría. Este método es particularmente útil para datos nominales sin un orden inherente. Por ejemplo, si tenemos una característica "color" con categorías "rojo", "azul" y "verde", la codificación one-hot crearía tres columnas binarias separadas, una para cada color.
- Codificación por etiquetas: Asigna un número entero único a cada categoría. Este enfoque es más adecuado para datos ordinales donde existe un orden significativo en las categorías. Por ejemplo, niveles educativos como "secundaria", "licenciatura" y "maestría" podrían codificarse como 1, 2 y 3, respectivamente.
- Capas de embeddings: Se utilizan para variables categóricas de alta cardinalidad, que son características con un gran número de categorías únicas. Los embeddings aprenden una representación vectorial densa para cada categoría, capturando relaciones semánticas entre ellas. Esto es particularmente efectivo en tareas de procesamiento de lenguaje natural o al trabajar con características como IDs de productos en sistemas de recomendación.
- Codificación por objetivo: Esta técnica avanzada reemplaza las categorías con el promedio de la variable objetivo para esa categoría. Es útil cuando existe una relación fuerte entre la categoría y la variable objetivo, pero debe usarse con precaución para evitar el sobreajuste.
La elección del método de codificación depende de la naturaleza de la variable categórica, los requisitos específicos de la arquitectura de la red neuronal y las características del problema que se desea resolver. Es beneficioso experimentar con diferentes técnicas de codificación para determinar cuál ofrece el mejor rendimiento para una tarea dada.
- Datos de texto: Requieren tokenización y embeddings, lo que implica:
- Dividir el texto en palabras o subpalabras individuales (tokens). Este proceso puede variar según el idioma y los requisitos específicos de la tarea. Por ejemplo, en inglés, una tokenización basada en espacios puede ser suficiente para muchas aplicaciones, mientras que idiomas más complejos pueden requerir tokenizadores especializados.
- Convertir los tokens en índices numéricos. Este paso crea un vocabulario donde a cada token único se le asigna un ID entero único. Esta conversión es necesaria porque las redes neuronales operan con datos numéricos.
- Aplicar embeddings de palabras para representaciones semánticas. Este paso crucial transforma los tokens en representaciones vectoriales densas que capturan relaciones semánticas entre palabras. Hay varios enfoques:
- Embeddings preentrenados: Utilizar modelos como Word2Vec, GloVe o FastText, entrenados en grandes corpus para capturar patrones generales del lenguaje.
- Embeddings específicos de la tarea: Entrenar embeddings desde cero en un conjunto de datos específico, lo que permite capturar relaciones semánticas específicas del dominio.
- Embeddings contextualizados: Usar modelos como BERT o GPT, que generan embeddings dinámicos basados en el contexto en el que aparece una palabra.
- Manejar palabras fuera del vocabulario (OOV): Implementar estrategias como usar un token especial "desconocido", emplear tokenización por subpalabras (e.g., WordPiece, Byte-Pair Encoding) o usar modelos a nivel de caracteres.
- Datos de series temporales: Requieren transformaciones especializadas para capturar patrones y dependencias temporales:
- Creación de características de desfase: Representan valores pasados de la variable objetivo u otras características relevantes. Por ejemplo, al predecir precios de acciones, se pueden incluir los precios del día, semana o mes anteriores como características.
- Aplicación de promedios móviles u otras estadísticas rodantes: Estas suavizan las fluctuaciones a corto plazo y destacan las tendencias a largo plazo. Las técnicas comunes incluyen promedios móviles simples, promedios móviles exponenciales y desviaciones estándar rodantes.
- Codificación de características cíclicas: Muchas series temporales tienen patrones cíclicos basados en períodos de tiempo. Por ejemplo:
- Día de la semana: Se puede codificar usando transformaciones seno y coseno para capturar la naturaleza circular de los patrones semanales.
- Mes del año: Codificado de manera similar para representar ciclos anuales.
- Hora del día: Útil para capturar patrones diarios en datos de alta frecuencia.
- Diferenciación: Tomar la diferencia entre pasos consecutivos puede ayudar a hacer estacionaria una serie temporal, lo cual es un requisito común para muchos modelos de series temporales.
- Descomposición: Separar una serie temporal en sus componentes de tendencia, estacionalidad y residuales puede proporcionar características valiosas para que el modelo aprenda.
- Datos de imágenes: Requieren preprocesamiento específico para garantizar un rendimiento óptimo en redes neuronales:
- Redimensionamiento a dimensiones consistentes: Este paso es crucial ya que las redes neuronales, particularmente las redes neuronales convolucionales (CNNs), requieren imágenes de entrada de tamaño uniforme. El redimensionamiento ayuda a estandarizar la entrada, permitiendo que la red procese imágenes de manera eficiente sin importar sus dimensiones originales.
- Normalización de valores de píxeles: Normalmente, esto implica escalar las intensidades de los píxeles a un rango de 0-1 o -1 a 1. La normalización es esencial porque:
- Ayuda a una convergencia más rápida durante el entrenamiento al asegurar que todas las características estén en una escala similar.
- Mitiga el impacto de condiciones de iluminación o configuraciones de cámara variables.
- Permite que el modelo trate las características de manera más equitativa, evitando que los píxeles de alta intensidad dominen.
- Aplicación de técnicas de aumento de datos: Esto es fundamental para aumentar la robustez del modelo y mejorar su capacidad de generalización. El aumento de datos amplía artificialmente el conjunto de entrenamiento creando versiones modificadas de imágenes existentes. Técnicas comunes incluyen:
- Transformaciones geométricas: Rotaciones, volteos, escalado y traslaciones.
- Aumentaciones del espacio de color: Ajustes de brillo, contraste o aplicación de modificaciones en el color.
- Adición de ruido o aplicación de filtros: Ruido gaussiano, desenfoque o efectos de nitidez.
- Mezcla de imágenes: Técnicas como mixup o CutMix que combinan múltiples imágenes de entrenamiento.
- Estandarización por canal: Para imágenes multicanal (e.g., RGB), a menudo es beneficioso estandarizar cada canal por separado.
- Manejo de datos faltantes o corruptos: Implementar estrategias para manejar imágenes incompletas o dañadas, como descartar, interpolar o usar modelos generativos para reconstruir partes faltantes.
Ejemplo: Limpieza y transformación de un conjunto de datos de muestra
Exploremos un ejemplo práctico utilizando Pandas para limpiar y preparar datos con valores faltantes y atípicos. Este proceso es crucial en la preprocesamiento de datos para modelos de aprendizaje profundo, ya que asegura la calidad y consistencia de los datos. Abordaremos paso a paso cómo manejar problemas comunes de datos:
- Valores faltantes: Demostraremos técnicas para imputar o eliminar puntos de datos faltantes, que pueden impactar significativamente el rendimiento del modelo si no se abordan.
- Atípicos: Exploraremos métodos para identificar y tratar valores atípicos, que pueden distorsionar distribuciones y afectar el entrenamiento del modelo.
- Transformación de datos: Mostraremos cómo convertir variables categóricas en un formato adecuado para redes neuronales.
Al final de este ejemplo, tendrás una comprensión clara de cómo aplicar estas técnicas esenciales de limpieza de datos utilizando Python y Pandas, sentando las bases para pasos más avanzados de ingeniería de características.
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
# Sample dataset
data = {
'age': [25, 30, np.nan, 35, 40, 100, 28, 45, np.nan, 50],
'income': [50000, 60000, 45000, 70000, np.nan, 200000, 55000, np.nan, 65000, 75000],
'category': ['A', 'B', np.nan, 'A', 'B', 'C', 'A', 'C', 'B', np.nan],
'education': ['High School', 'Bachelor', 'Master', np.nan, 'PhD', 'Bachelor', 'Master', 'High School', 'PhD', 'Bachelor']
}
df = pd.DataFrame(data)
# Display original data
print("Original Data:")
print(df)
print("\n")
# Define preprocessing steps for numerical and categorical columns
numeric_features = ['age', 'income']
categorical_features = ['category', 'education']
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='constant', fill_value='Unknown')),
('onehot', OneHotEncoder(handle_unknown='ignore'))
])
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
])
# Fit and transform the data
X_processed = preprocessor.fit_transform(df)
# Convert to DataFrame for better visualization
feature_names = (numeric_features +
preprocessor.named_transformers_['cat'].named_steps['onehot'].get_feature_names(categorical_features).tolist())
df_processed = pd.DataFrame(X_processed, columns=feature_names)
# Handle outliers (e.g., cap age at 99th percentile)
age_cap = np.percentile(df['age'].dropna(), 99)
df['age'] = np.where(df['age'] > age_cap, age_cap, df['age'])
print("Processed Data:")
print(df_processed)
# Additional statistics
print("\nData Statistics:")
print(df_processed.describe())
print("\nMissing Values After Processing:")
print(df_processed.isnull().sum())
print("\nUnique Values in Categorical Columns:")
for col in categorical_features:
print(f"{col}: {df[col].nunique()}")
Explicación del desglose del código:
- Importación de bibliotecas:
Importamos las bibliotecas necesarias:
pandas
para la manipulación de datos,numpy
para operaciones numéricas y varios módulos descikit-learn
para tareas de preprocesamiento. - Creación de un conjunto de datos de muestra:
Creamos un conjunto de datos más diverso con 10 entradas, incluyendo valores faltantes (
np.nan
) en diferentes columnas. Este conjunto de datos incluye una columna adicional llamadaeducation
para demostrar cómo manejar múltiples variables categóricas. - Visualización de los datos originales:
Imprimimos el conjunto de datos original para mostrar el estado inicial, incluidos los valores faltantes y posibles valores atípicos.
- Definición de los pasos de preprocesamiento:
Separamos nuestras características en columnas numéricas y categóricas. Luego, creamos pipelines de preprocesamiento para cada tipo:
- Para características numéricas: Usamos
SimpleImputer
para llenar valores faltantes con la mediana, y luego aplicamosStandardScaler
para normalizar los datos. - Para características categóricas: Usamos
SimpleImputer
para llenar valores faltantes con "Unknown", y luego aplicamosOneHotEncoder
para convertir las categorías en columnas binarias.
- Para características numéricas: Usamos
- Creación de un ColumnTransformer:
Usamos
ColumnTransformer
para aplicar diferentes pasos de preprocesamiento a distintas columnas, lo que nos permite manejar datos numéricos y categóricos simultáneamente. - Ajuste y transformación de datos:
Aplicamos nuestros pasos de preprocesamiento a todo el conjunto de datos usando
fit_transform()
. - Conversión a DataFrame:
Convertimos los datos procesados nuevamente en un
DataFrame
de pandas para facilitar su visualización y análisis. También creamos nombres de columnas apropiados para las variables categóricas codificadas con one-hot. - Manejo de valores atípicos:
En lugar de usar un valor fijo, limitamos la columna
age
al percentil 99. Este enfoque es más dinámico, ya que se adapta a la distribución de los datos. - Visualización de los datos procesados:
Imprimimos el conjunto de datos procesado para mostrar los resultados de los pasos de preprocesamiento.
- Estadísticas adicionales:
Proporcionamos más información sobre los datos procesados:
- Estadísticas básicas de los datos procesados utilizando
describe()
- Verificación de valores faltantes restantes
- Conteo de valores únicos en las columnas categóricas originales
Este ejemplo demuestra un enfoque robusto y completo para el preprocesamiento de datos para aprendizaje profundo. Maneja adecuadamente los valores faltantes, escala las características numéricas, codifica variables categóricas y aborda valores atípicos, mientras mantiene visibilidad clara de los datos en cada paso. Este enfoque es especialmente adecuado para escenarios del mundo real, donde los conjuntos de datos suelen incluir múltiples tipos de características y presentan varios desafíos de calidad de datos.
7.1.2 Paso 2: Escalado y Normalización
Las redes neuronales son altamente sensibles a la escala de los datos de entrada, lo que puede impactar significativamente su rendimiento y eficiencia. Las características con rangos muy diferentes pueden dominar el proceso de aprendizaje, lo que podría llevar a resultados sesgados o subóptimos. Para abordar este problema, los científicos de datos emplean técnicas de escalado y normalización, asegurando que todas las características de entrada contribuyan de manera equitativa al proceso de aprendizaje.
Existen dos métodos principales para este propósito:
Normalización
Esta técnica escala los datos a un rango específico, típicamente entre 0 y 1. La normalización es particularmente útil cuando se trabaja con características que tienen límites naturales, como valores de píxeles en imágenes (0-255) o métricas basadas en porcentajes (0-100%). Al mapear estos valores a un rango consistente, evitamos que las características con valores absolutos mayores eclipsen a aquellas con rangos más pequeños.
El proceso de normalización implica transformar los valores originales utilizando una fórmula matemática que mantiene las relaciones relativas entre los puntos de datos mientras los restringe dentro de un rango predeterminado. Esta transformación es especialmente beneficiosa en modelos de aprendizaje profundo por varias razones:
- Mejora de la convergencia del modelo: Las características normalizadas a menudo conducen a una convergencia más rápida y estable durante el entrenamiento, ya que el modelo no necesita aprender escalas muy diferentes para distintas características.
- Mayor interpretabilidad de las características: Cuando todas las características están en la misma escala, es más fácil interpretar su importancia relativa y su impacto en las predicciones del modelo.
- Mitigación de inestabilidad numérica: Los valores grandes pueden, en ocasiones, causar inestabilidad numérica en las redes neuronales, particularmente al usar funciones de activación como sigmoide o tangente hiperbólica. La normalización ayuda a prevenir estos problemas.
Las técnicas comunes de normalización incluyen el escalado Min-Max, que mapea el valor mínimo a 0 y el máximo a 1, y el escalado decimal, que mueve el punto decimal de los valores para crear un rango deseado. La elección del método de normalización a menudo depende de los requisitos específicos del modelo y la naturaleza de los datos que se están procesando.
Estandarización Este método reescala los datos para tener una media de cero y una desviación estándar de uno. La estandarización es especialmente beneficiosa al trabajar con conjuntos de datos que contienen características con escalas y distribuciones variables. Al centrar los datos alrededor de cero y escalarlos a una varianza unitaria, la estandarización garantiza que cada característica contribuya proporcionalmente al proceso de aprendizaje del modelo, independientemente de su escala original.
El proceso de estandarización implica restar el valor medio de cada característica de los puntos de datos y luego dividir por la desviación estándar. Esta transformación resulta en una distribución donde aproximadamente el 68% de los valores caen dentro de una desviación estándar de la media, el 95% dentro de dos desviaciones estándar y el 99.7% dentro de tres desviaciones estándar.
La estandarización ofrece varias ventajas en el contexto del aprendizaje profundo:
- Mejora del descenso del gradiente: Las características estandarizadas a menudo conducen a una convergencia más rápida durante la optimización, ya que el algoritmo de descenso del gradiente puede navegar más fácilmente por el espacio de características.
- Importancia de las características: Cuando las características están estandarizadas, sus coeficientes en el modelo pueden compararse directamente para evaluar su importancia relativa.
- Manejo de valores atípicos: La estandarización puede ayudar a mitigar el impacto de los valores atípicos al escalarlos en relación con la desviación estándar de la característica.
Sin embargo, es importante tener en cuenta que la estandarización no limita los valores a un rango específico, lo que puede ser una consideración para ciertas arquitecturas de redes neuronales o al trabajar con características que tienen límites naturales.
La elección entre normalización y estandarización a menudo depende de las características específicas del conjunto de datos y los requisitos de la arquitectura de la red neuronal. Por ejemplo:
- Las redes neuronales convolucionales (CNNs) para el procesamiento de imágenes suelen funcionar bien con datos normalizados, ya que los valores de píxeles naturalmente caen dentro de un rango fijo.
- Las redes neuronales recurrentes (RNNs) y otras arquitecturas que trabajan con series temporales o datos tabulares suelen beneficiarse de la estandarización, especialmente cuando las características tienen diferentes unidades o escalas.
Es importante destacar que el escalado debe aplicarse de manera consistente en los conjuntos de entrenamiento, validación y prueba para mantener la integridad de la evaluación del rendimiento del modelo. Además, al trabajar con datos nuevos y no vistos durante la inferencia, es crucial aplicar los mismos parámetros de escalado utilizados durante el entrenamiento para garantizar la consistencia en las predicciones del modelo.
Ejemplo: Escalado y normalización de características Profundicemos en el escalado de características numéricas utilizando dos métodos populares de Scikit-Learn: StandardScaler
y MinMaxScaler
. Estas técnicas son cruciales para preparar los datos para redes neuronales, ya que ayudan a garantizar que todas las características contribuyan de manera equitativa al proceso de aprendizaje del modelo.
StandardScaler
transforma los datos para tener una media de 0 y una desviación estándar de 1. Esto es particularmente útil cuando tus características tienen diferentes unidades o escalas. Por ejemplo, si tienes características como edad (0-100) e ingresos (de miles a millones), StandardScaler
las llevará a una escala comparable.
Por otro lado, MinMaxScaler
escala los datos a un rango fijo, típicamente entre 0 y 1. Esto es beneficioso cuando necesitas que tus características tengan un rango específico y delimitado, lo cual puede ser importante para ciertos algoritmos o cuando deseas preservar valores cero en datos dispersos.
La elección entre estos escaladores a menudo depende de la naturaleza de tus datos y los requisitos de tu red neuronal. En el siguiente ejemplo, demostraremos cómo aplicar ambas técnicas de escalado a un conjunto de datos de muestra.
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
import matplotlib.pyplot as plt
# Sample data
X = np.array([[25, 50000], [30, 60000], [35, 70000], [40, 80000], [45, 90000], [50, 100000], [55, 110000], [60, 120000]])
df = pd.DataFrame(X, columns=['Age', 'Income'])
# Standardization
scaler = StandardScaler()
X_standardized = scaler.fit_transform(X)
df_standardized = pd.DataFrame(X_standardized, columns=['Age_std', 'Income_std'])
# Normalization (Min-Max Scaling)
normalizer = MinMaxScaler()
X_normalized = normalizer.fit_transform(X)
df_normalized = pd.DataFrame(X_normalized, columns=['Age_norm', 'Income_norm'])
# Robust Scaling
robust_scaler = RobustScaler()
X_robust = robust_scaler.fit_transform(X)
df_robust = pd.DataFrame(X_robust, columns=['Age_robust', 'Income_robust'])
# Combine all scaled data
df_combined = pd.concat([df, df_standardized, df_normalized, df_robust], axis=1)
# Display results
print("Combined Data:")
print(df_combined)
# Visualize the scaling effects
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
fig.suptitle('Comparison of Scaling Techniques')
axes[0, 0].scatter(df['Age'], df['Income'])
axes[0, 0].set_title('Original Data')
axes[0, 1].scatter(df_standardized['Age_std'], df_standardized['Income_std'])
axes[0, 1].set_title('Standardized Data')
axes[1, 0].scatter(df_normalized['Age_norm'], df_normalized['Income_norm'])
axes[1, 0].set_title('Normalized Data')
axes[1, 1].scatter(df_robust['Age_robust'], df_robust['Income_robust'])
axes[1, 1].set_title('Robust Scaled Data')
for ax in axes.flat:
ax.set(xlabel='Age', ylabel='Income')
plt.tight_layout()
plt.show()
Explicación del desglose del código
- Importación de bibliotecas:
Se importan
numpy
para operaciones numéricas,pandas
para manipulación de datos,sklearn
para herramientas de preprocesamiento ymatplotlib
para visualización. - Creación de datos de muestra:
Se crea un conjunto de datos más amplio con 8 entradas, incluyendo datos de edad e ingresos. Esto proporciona un conjunto de datos más completo para demostrar los efectos del escalado.
- Estandarización (
StandardScaler
):- Transforma las características para tener una media de 0 y una desviación estándar de 1.
- Es útil cuando las características tienen diferentes escalas o unidades.
- Fórmula: z = (x - μ) / σ, donde μ es la media y σ es la desviación estándar.
- Normalización (
MinMaxScaler
):- Escala las características a un rango fijo, típicamente entre 0 y 1.
- Preserva valores cero y no centra los datos.
- Fórmula: x_scaled = (x - x_min) / (x_max - x_min).
- Escalado robusto (
RobustScaler
):- Escala las características utilizando estadísticas robustas a valores atípicos.
- Utiliza la mediana y el rango intercuartil en lugar de la media y la desviación estándar.
- Es útil cuando los datos contienen muchos valores atípicos.
- Combinación de datos:
Se combinan los conjuntos de datos originales y escalados en un único
DataFrame
para facilitar la comparación. - Visualización:
- Se crea una cuadrícula de gráficos de dispersión 2x2 para visualizar los efectos de las diferentes técnicas de escalado.
- Esto permite una comparación directa de cómo cada método transforma los datos.
Puntos clave:
StandardScaler
centra los datos y los escala a una varianza unitaria, como se observa en el gráfico estandarizado donde los datos están centrados alrededor de (0,0).MinMaxScaler
comprime todos los puntos de datos a un rango fijo [0,1], manteniendo la forma de la distribución original.RobustScaler
produce un resultado similar aStandardScaler
, pero es menos influenciado por valores atípicos.
Este ejemplo ofrece un examen exhaustivo de varias técnicas de escalado, su impacto en los datos y métodos para visualizar estas transformaciones. Es especialmente valioso para comprender cómo los enfoques de escalado afectan tu conjunto de datos antes de ingresarlo en una red neuronal.
7.1.3 Paso 3: Codificación de variables categóricas
Los datos categóricos requieren codificación antes de ser introducidos en una red neuronal. Este proceso transforma datos no numéricos en un formato que las redes neuronales pueden procesar eficazmente. Existen varias técnicas de codificación, cada una con sus fortalezas y casos de uso:
Codificación One-Hot
Este método transforma variables categóricas en un formato que las redes neuronales pueden procesar de manera efectiva. Crea un vector binario para cada categoría, donde cada valor único de la categoría se representa mediante una columna separada. Por ejemplo, considera una categoría "color" con valores "rojo", "azul" y "verde". La codificación one-hot generaría tres nuevas columnas: "color_rojo", "color_azul" y "color_verde". En cada fila, la columna correspondiente al color presente contendría un 1, mientras que las otras serían 0.
Esta técnica de codificación es particularmente valiosa para categorías nominales que carecen de un orden inherente. Al crear columnas binarias separadas para cada categoría, la codificación one-hot evita imponer relaciones numéricas artificiales entre las categorías. Esto es crucial porque las redes neuronales podrían interpretar las codificaciones numéricas como si tuvieran un orden o magnitud significativos.
Sin embargo, la codificación one-hot presenta algunas consideraciones importantes:
- Dimensionalidad: Para categorías con muchos valores únicos, la codificación one-hot puede aumentar significativamente el número de características de entrada, lo que podría conducir a la "maldición de la dimensionalidad".
- Esparcimiento: Los datos codificados resultantes pueden ser dispersos, con muchos valores 0, lo que podría afectar la eficiencia de algunos algoritmos.
- Manejo de nuevas categorías: La codificación one-hot puede enfrentar problemas con categorías nuevas y no vistas en datos de prueba o de producción que no estaban presentes durante el entrenamiento.
A pesar de estos desafíos, la codificación one-hot sigue siendo un método popular y efectivo para preparar datos categóricos para redes neuronales, especialmente al trabajar con categorías nominales de baja a moderada cardinalidad.
Aquí tienes un ejemplo de cómo implementar la codificación one-hot utilizando Python y la biblioteca pandas
.
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green'],
'size': ['small', 'medium', 'large', 'medium', 'small']
})
# Initialize the OneHotEncoder
encoder = OneHotEncoder(sparse=False)
# Fit and transform the data
encoded_data = encoder.fit_transform(data)
# Get feature names
feature_names = encoder.get_feature_names_out(['color', 'size'])
# Create a new DataFrame with encoded data
encoded_df = pd.DataFrame(encoded_data, columns=feature_names)
print("Original data:")
print(data)
print("\nOne-hot encoded data:")
print(encoded_df)
Explicación del desglose del código
- Importar las bibliotecas necesarias: Importamos
pandas
para la manipulación de datos yOneHotEncoder
desklearn
para la codificación one-hot. - Crear datos de muestra: Creamos un DataFrame simple con dos columnas categóricas: "color" y "size".
- Inicializar
OneHotEncoder
: Creamos una instancia deOneHotEncoder
consparse=False
para obtener una salida en forma de matriz densa en lugar de una matriz dispersa. - Ajustar y transformar los datos: Usamos el método
fit_transform
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Obtener nombres de características: Usamos
get_feature_names_out
para obtener los nombres de las nuevas columnas codificadas. - Crear un nuevo DataFrame: Creamos un nuevo DataFrame con los datos codificados, utilizando los nombres de las características como etiquetas de las columnas.
- Imprimir resultados: Mostramos tanto los datos originales como los codificados para comparación.
Este código demuestra cómo la codificación one-hot transforma las variables categóricas en un formato adecuado para modelos de aprendizaje automático, incluidas las redes neuronales. Cada valor único de categoría se convierte en una columna separada, con valores binarios que indican la presencia (1) o ausencia (0) de esa categoría en cada fila.
Cuando ejecutas este código, puedes observar cómo los datos categóricos originales se transforman en un formato codificado one-hot, donde cada valor único de categoría tiene su propia columna con indicadores binarios.
Codificación por etiquetas
Esta técnica asigna a cada categoría un número entero único. Por ejemplo, "rojo" podría codificarse como 0, "azul" como 1 y "verde" como 2. Aunque es eficiente en términos de uso de memoria, la codificación por etiquetas es más adecuada para datos ordinales (categorías con un orden significativo). Es importante tener en cuenta que las redes neuronales podrían interpretar el orden de las etiquetas como significativo, lo que puede llevar a suposiciones incorrectas en categorías nominales.
La codificación por etiquetas es particularmente útil al trabajar con variables ordinales, donde el orden de las categorías importa. Por ejemplo, al codificar niveles educativos (e.g., "Secundaria", "Licenciatura", "Maestría", "Doctorado"), la codificación por etiquetas preserva el orden inherente, lo cual puede ser significativo para el modelo.
Sin embargo, la codificación por etiquetas tiene limitaciones cuando se aplica a categorías nominales (aquellas sin un orden inherente). Por ejemplo, codificar razas de perros como números (e.g., Labrador = 0, Poodle = 1, Beagle = 2) podría llevar al modelo a inferir incorrectamente que la diferencia numérica entre razas tiene un significado.
La implementación de la codificación por etiquetas es sencilla utilizando bibliotecas como scikit-learn
.
import pandas as pd
from sklearn.preprocessing import LabelEncoder
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green', 'blue', 'yellow'],
'size': ['small', 'medium', 'large', 'medium', 'small', 'large', 'medium']
})
# Initialize LabelEncoder
le_color = LabelEncoder()
le_size = LabelEncoder()
# Fit and transform the data
data['color_encoded'] = le_color.fit_transform(data['color'])
data['size_encoded'] = le_size.fit_transform(data['size'])
print("Original and encoded data:")
print(data)
print("\nUnique categories and their encoded values:")
print("Colors:", dict(zip(le_color.classes_, le_color.transform(le_color.classes_))))
print("Sizes:", dict(zip(le_size.classes_, le_size.transform(le_size.classes_))))
# Demonstrate inverse transform
color_codes = [0, 1, 2, 3]
size_codes = [0, 1, 2]
print("\nDecoding back to original categories:")
print("Colors:", le_color.inverse_transform(color_codes))
print("Sizes:", le_size.inverse_transform(size_codes))
Explicación del desglose del código
- Importación de bibliotecas:
- Importamos
pandas
para la manipulación de datos yLabelEncoder
desklearn
para codificar variables categóricas.
- Importamos
- Creación de datos de muestra:
- Creamos un DataFrame con dos columnas categóricas: "color" y "size".
- Este ejemplo incluye datos más diversos para demostrar mejor el proceso de codificación.
- Inicialización de
LabelEncoder
:- Creamos dos instancias separadas de
LabelEncoder
, una para "color" y otra para "size". - Esto nos permite codificar cada categoría de forma independiente.
- Creamos dos instancias separadas de
- Ajuste y transformación de datos:
- Usamos
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Los valores codificados se añaden como nuevas columnas en el DataFrame.
- Usamos
- Visualización de resultados:
- Imprimimos los datos originales junto con los datos codificados para facilitar la comparación.
- Mostrar los mapeos de codificación:
- Creamos diccionarios para mostrar cómo cada categoría única se mapea a su valor codificado.
- Esto ayuda a comprender e interpretar los datos codificados.
- Demostración de transformación inversa:
- Mostramos cómo decodificar los valores numéricos de nuevo a sus categorías originales.
- Esto es útil cuando necesitas convertir predicciones o datos codificados a un formato comprensible para los humanos.
Este ejemplo proporciona una visión completa de la codificación por etiquetas. Demuestra cómo manejar múltiples variables categóricas, muestra el mapeo entre las categorías originales y los valores codificados, e incluye el proceso de transformación inversa. Este enfoque ofrece una comprensión más profunda de cómo funciona la codificación por etiquetas y cómo puede aplicarse en escenarios del mundo real.
Al utilizar la codificación por etiquetas, es crucial documentar el esquema de codificación y garantizar una aplicación consistente en los conjuntos de datos de entrenamiento, validación y prueba. Además, para modelos sensibles a la magnitud de las características de entrada (como redes neuronales), puede ser necesario escalar los valores codificados para evitar que el modelo atribuya una importancia indebida a las categorías con representaciones numéricas mayores.
Codificación Binaria
Este método combina aspectos tanto de la codificación one-hot como de la codificación por etiquetas, ofreciendo un equilibrio entre eficiencia e información preservada. Opera en dos pasos:
- Asignación de enteros: A cada categoría única se le asigna un entero, similar a la codificación por etiquetas.
- Conversión a binario: El entero asignado se convierte en su representación binaria.
Por ejemplo, si tenemos las categorías A, B, C y D, podrían asignarse los enteros 0, 1, 2 y 3 respectivamente. En binario, estos se representarían como 00, 01, 10 y 11.
Las ventajas de la codificación binaria incluyen:
- Eficiencia de memoria: Requiere menos columnas que la codificación one-hot, especialmente para categorías con muchos valores únicos. Para n categorías, la codificación binaria utiliza log2(n) columnas, mientras que la codificación one-hot utiliza n columnas.
- Preservación de información: A diferencia de la codificación por etiquetas, no impone una relación ordinal arbitraria entre categorías.
- Reducción de dimensionalidad: Crea menos características nuevas en comparación con la codificación one-hot, lo que puede ser beneficioso para el entrenamiento del modelo y la reducción del sobreajuste.
Sin embargo, la codificación binaria también tiene algunas consideraciones:
- Interpretación: Las características binarias resultantes pueden ser menos interpretables que las características codificadas one-hot.
- Compatibilidad con modelos: No todos los modelos pueden manejar características codificadas binariamente de manera óptima, por lo que es importante considerar los requisitos específicos de tu algoritmo elegido.
La codificación binaria es particularmente útil en escenarios donde se manejan variables categóricas de alta cardinalidad y la eficiencia de memoria es una preocupación, como en aplicaciones de aprendizaje automático a gran escala o cuando se trabaja con recursos computacionales limitados.
Aquí tienes un ejemplo de cómo implementar la codificación binaria utilizando Python y la biblioteca category_encoders
.
import pandas as pd
import category_encoders as ce
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green', 'blue', 'yellow'],
'size': ['small', 'medium', 'large', 'medium', 'small', 'large', 'medium']
})
# Initialize BinaryEncoder
encoder = ce.BinaryEncoder(cols=['color', 'size'])
# Fit and transform the data
encoded_data = encoder.fit_transform(data)
print("Original data:")
print(data)
print("\nBinary encoded data:")
print(encoded_data)
# Display mapping
print("\nEncoding mapping:")
print(encoder.mapping)
Explicación del desglose del código
- Importar bibliotecas:
- Importamos
pandas
para la manipulación de datos ycategory_encoders
para la codificación binaria.
- Importamos
- Crear datos de muestra:
- Creamos un DataFrame con dos columnas categóricas: "color" y "size".
- Inicializar
BinaryEncoder
:- Creamos una instancia de
BinaryEncoder
, especificando qué columnas codificar.
- Creamos una instancia de
- Ajustar y transformar datos:
- Usamos
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso.
- Usamos
- Visualizar resultados:
- Imprimimos los datos originales y los datos codificados binariamente para comparación.
- Mostrar mapeo de codificación:
- Mostramos el mapeo para ver cómo cada categoría se codifica en binario.
Cuando ejecutas este código, puedes observar cómo cada categoría única en "color" y "size" se transforma en un conjunto de columnas binarias. El número de columnas binarias para cada característica depende del número de categorías únicas en esa característica.
La codificación binaria proporciona una representación compacta de variables categóricas, especialmente útil para características de alta cardinalidad. Encuentra un equilibrio entre la explosión dimensional de la codificación one-hot y las suposiciones ordinales de la codificación por etiquetas, lo que la convierte en una herramienta valiosa en la ingeniería de características para aprendizaje profundo.
Embeddings
Para variables categóricas con alta cardinalidad (muchos valores únicos), los embeddings pueden ser una solución efectiva. Esta técnica aprende una representación vectorial de baja dimensión para cada categoría durante el proceso de entrenamiento de la red neuronal. Los embeddings pueden capturar relaciones complejas entre categorías y se utilizan comúnmente en tareas de procesamiento de lenguaje natural.
Los embeddings funcionan mapeando cada categoría a un vector denso en un espacio vectorial continuo. A diferencia de la codificación one-hot, que trata cada categoría como completamente distinta, los embeddings permiten comparaciones significativas entre categorías basadas en sus representaciones vectoriales aprendidas. Esto es particularmente útil al trabajar con grandes vocabularios en datos de texto o con variables categóricas que tienen similitudes o jerarquías inherentes.
La dimensionalidad del espacio de embeddings es un hiperparámetro que puede ajustarse. Por lo general, es mucho menor que el número de categorías únicas, lo que ayuda a reducir la complejidad del modelo y mitigar la maldición de la dimensionalidad. Por ejemplo, una variable categórica con 10,000 valores únicos podría incrustarse en un espacio de 50 o 100 dimensiones.
Una de las principales ventajas de los embeddings es su capacidad de generalización. Pueden capturar relaciones semánticas entre categorías, permitiendo que el modelo realice predicciones inteligentes incluso para categorías que no ha visto durante el entrenamiento. Esto es especialmente valioso en sistemas de recomendación, donde los embeddings pueden representar usuarios y elementos en un espacio compartido, facilitando el descubrimiento de preferencias y similitudes latentes.
En el contexto del aprendizaje profundo para datos tabulares, los embeddings pueden aprenderse como parte de la arquitectura de la red neuronal. Esto permite que el modelo descubra automáticamente representaciones óptimas para variables categóricas, adaptadas a la tarea específica. Los embeddings aprendidos también pueden visualizarse o analizarse por separado, proporcionando potencialmente ideas sobre las relaciones entre categorías que podrían no ser evidentes en los datos originales.
Aquí tienes un ejemplo de cómo implementar embeddings para variables categóricas utilizando TensorFlow/Keras.
import tensorflow as tf
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
# Sample data
data = pd.DataFrame({
'user_id': np.random.randint(1, 1001, 10000),
'product_id': np.random.randint(1, 501, 10000),
'purchase': np.random.randint(0, 2, 10000)
})
# Prepare features and target
X = data[['user_id', 'product_id']]
y = data['purchase']
# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Define the model
user_input = tf.keras.layers.Input(shape=(1,))
product_input = tf.keras.layers.Input(shape=(1,))
user_embedding = tf.keras.layers.Embedding(input_dim=1001, output_dim=50)(user_input)
product_embedding = tf.keras.layers.Embedding(input_dim=501, output_dim=50)(product_input)
user_vec = tf.keras.layers.Flatten()(user_embedding)
product_vec = tf.keras.layers.Flatten()(product_embedding)
concat = tf.keras.layers.Concatenate()([user_vec, product_vec])
dense = tf.keras.layers.Dense(64, activation='relu')(concat)
output = tf.keras.layers.Dense(1, activation='sigmoid')(dense)
model = tf.keras.Model(inputs=[user_input, product_input], outputs=output)
# Compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# Train the model
model.fit([X_train['user_id'], X_train['product_id']], y_train,
epochs=5, batch_size=32, validation_split=0.2)
# Evaluate the model
loss, accuracy = model.evaluate([X_test['user_id'], X_test['product_id']], y_test)
print(f"Test Accuracy: {accuracy:.4f}")
Explicación del desglose del código
- Preparación de datos:
- Creamos un conjunto de datos de muestra con IDs de usuarios, IDs de productos e información de compras.
- Los datos se dividen en conjuntos de entrenamiento y prueba.
- Arquitectura del modelo:
- Definimos capas de entrada separadas para
user_id
yproduct_id
. - Se crean capas de embeddings para los IDs de usuarios y productos. El
input_dim
se establece como el número de categorías únicas más uno (para considerar el posible indexado en cero), y eloutput_dim
se fija en 50 (la dimensión del embedding). - Los vectores embebidos se aplanan y concatenan.
- Se añaden capas densas para un procesamiento adicional, con una activación final sigmoide para clasificación binaria.
- Definimos capas de entrada separadas para
- Compilación y entrenamiento del modelo:
- El modelo se compila utilizando la pérdida de entropía cruzada binaria y el optimizador Adam.
- El modelo se entrena con los datos preparados.
- Evaluación:
- Se evalúa el rendimiento del modelo en el conjunto de prueba.
Este ejemplo demuestra cómo se pueden usar embeddings para representar variables categóricas de alta cardinalidad (IDs de usuarios y productos) en un espacio de menor dimensión. Las capas de embeddings aprenden a mapear cada ID único a un vector de 50 dimensiones durante el proceso de entrenamiento. Estos embeddings capturan relaciones significativas entre usuarios y productos, lo que permite al modelo realizar predicciones basadas en estas representaciones latentes.
Las principales ventajas de usar embeddings en este escenario incluyen:
- Reducción de dimensionalidad: En lugar de usar codificación one-hot, que resultaría en vectores dispersos de alta dimensionalidad, los embeddings proporcionan una representación densa y de menor dimensión.
- Captura de relaciones semánticas: El espacio de embeddings puede capturar similitudes entre usuarios o productos, incluso si no han sido vistos juntos en los datos de entrenamiento.
- Escalabilidad: Este enfoque se adapta bien a un gran número de categorías, lo que lo hace adecuado para aplicaciones del mundo real con muchos usuarios y productos.
Al usar embeddings, permitimos que la red neuronal aprenda representaciones óptimas de nuestras variables categóricas, específicamente adaptadas a la tarea de predecir compras. Esto puede conducir a un mejor rendimiento del modelo y una mejor generalización a datos no vistos.
La elección del método de codificación depende de la naturaleza de tus datos categóricos, los requisitos específicos de la arquitectura de tu red neuronal y el problema que estás tratando de resolver. Es beneficioso experimentar con diferentes técnicas de codificación para determinar cuál ofrece el mejor rendimiento para tu caso particular.
Preparar datos para redes neuronales es un proceso intrincado pero crucial que incluye limpieza, escalado y codificación de datos. Los datos correctamente transformados y escalados mejoran el proceso de aprendizaje, permitiendo que las redes neuronales converjan más rápido y ofrezcan resultados más precisos. Al garantizar que cada característica se maneje adecuadamente, ya sea escalando valores numéricos o codificando categorías, creamos una base sólida para un modelo de aprendizaje profundo exitoso.
7.1 Preparación de Datos para Redes Neuronales
El aprendizaje profundo ha revolucionado el campo de la ciencia de datos, ofreciendo herramientas sofisticadas capaces de manejar grandes cantidades de datos y descubrir patrones complejos. Estas redes neuronales avanzadas han demostrado capacidades notables en diversos dominios, desde el reconocimiento de imágenes y voz hasta el procesamiento de lenguaje natural y los sistemas autónomos. El poder del aprendizaje profundo radica en su capacidad para aprender automáticamente representaciones jerárquicas de los datos, permitiéndole capturar relaciones intrincadas y patrones que pueden ser difíciles de discernir para los humanos.
Sin embargo, la efectividad de los modelos de aprendizaje profundo depende en gran medida de la calidad y preparación de los datos de entrada. Esta dependencia resalta la importancia continua de la ingeniería de características, incluso en la era de las redes neuronales. Aunque los algoritmos de aprendizaje profundo pueden a menudo extraer características significativas a partir de datos en bruto, el proceso de preparar y estructurar estos datos sigue siendo crucial para un rendimiento óptimo.
A diferencia de los modelos tradicionales de aprendizaje automático que a menudo requieren una amplia ingeniería de características manual, las redes de aprendizaje profundo están diseñadas para aprender representaciones de alto nivel directamente de datos en bruto. Esta capacidad ha reducido significativamente la necesidad de características diseñadas a mano en muchas aplicaciones. Por ejemplo, en tareas de visión por computadora, las redes neuronales convolucionales pueden aprender automáticamente a detectar bordes, formas y objetos complejos a partir de datos de píxeles en bruto, eliminando la necesidad de extracción manual de características.
No obstante, garantizar que los datos de entrada estén bien estructurados, normalizados y sean relevantes es fundamental para mejorar el rendimiento y la estabilidad del modelo. Una preparación adecuada de los datos puede impactar significativamente en el proceso de aprendizaje, afectando factores como la velocidad de convergencia, la capacidad de generalización y la precisión general. Por ejemplo, en tareas de procesamiento de lenguaje natural, pasos de preprocesamiento como la tokenización, la eliminación de palabras vacías y el manejo de palabras fuera del vocabulario pueden influir enormemente en la capacidad del modelo para comprender y generar texto.
En este capítulo, profundizaremos en los aspectos esenciales de la ingeniería de características para aprendizaje profundo, cubriendo una amplia gama de técnicas para preparar datos, gestionar escalas de características y optimizar datos para redes neuronales. Exploraremos cómo estas metodologías pueden aplicarse a diferentes tipos de datos y dominios de problemas para maximizar el potencial de los modelos de aprendizaje profundo.
Comenzando con la preparación de datos, discutiremos las mejores prácticas para limpiar y transformar los datos para que sean compatibles con las redes neuronales. Esta sección cubrirá técnicas como el manejo de valores faltantes, el tratamiento de valores atípicos y el abordaje de desequilibrios en las clases. También exploraremos consideraciones específicas para preparar datos estructurados (por ejemplo, conjuntos de datos tabulares), datos de imágenes (por ejemplo, redimensionamiento, aumento) y datos de texto (por ejemplo, tokenización, incrustaciones).
Además, examinaremos técnicas avanzadas de ingeniería de características que pueden mejorar los modelos de aprendizaje profundo, tales como:
- Métodos de escalado y normalización de características para garantizar que todas las entradas contribuyan de manera equitativa al proceso de aprendizaje.
- Técnicas de reducción de dimensionalidad como Análisis de Componentes Principales (PCA) y t-SNE para datos de alta dimensión.
- Ingeniería de características específica de series temporales, incluyendo características de retraso y estadísticas rodantes.
- Métodos para manejar variables categóricas, como capas de incrustación para características de alta cardinalidad.
- Incorporación de conocimiento del dominio en la ingeniería de características para guiar el proceso de aprendizaje.
Dominando estas técnicas de ingeniería de características, los científicos de datos y practicantes de aprendizaje automático pueden mejorar significativamente el rendimiento y la robustez de sus modelos de aprendizaje profundo en una amplia gama de aplicaciones y dominios.
Preparar datos para redes neuronales es un proceso crítico que exige una meticulosa atención a los detalles. Esta preparación implica estructurar, escalar y formatear cuidadosamente los datos para optimizar el rendimiento de los modelos de aprendizaje profundo. Las redes neuronales están diseñadas fundamentalmente para procesar información en forma de matrices numéricas, lo que exige la conversión de todos los datos de entrada a un formato numérico consistente.
La importancia del preprocesamiento de datos en aprendizaje profundo no puede subestimarse. A diferencia de los algoritmos tradicionales de aprendizaje automático, las redes neuronales muestran una sensibilidad elevada a las variaciones en la distribución de los datos. Esta sensibilidad hace que los pasos de preprocesamiento, como el escalado y la codificación, no solo sean beneficiosos, sino esenciales para lograr un rendimiento óptimo. Estas medidas preparatorias garantizan que la red neuronal pueda aprender eficazmente de todas las características disponibles sin verse influenciada desproporcionadamente por una única entrada.
Para abordar este proceso de manera sistemática, podemos descomponer la preparación de datos para redes neuronales en tres pasos principales:
- Limpieza y Transformación de Datos: Este paso inicial implica identificar y abordar problemas como valores faltantes, valores atípicos e inconsistencias en el conjunto de datos. También puede incluir la selección o creación de características para garantizar que los datos de entrada sean relevantes e informativos para la tarea.
- Escalado y Normalización: Este paso asegura que todas las características numéricas estén en una escala similar, evitando que las características con magnitudes mayores dominen el proceso de aprendizaje. Las técnicas comunes incluyen escalado min-max, estandarización y escalado robusto.
- Codificación de Variables Categóricas: Dado que las redes neuronales operan sobre datos numéricos, las variables categóricas deben convertirse a un formato numérico. Esto a menudo implica técnicas como la codificación one-hot, la codificación ordinal o métodos más avanzados como las incrustaciones de entidades para variables categóricas de alta cardinalidad.
Al ejecutar meticulosamente estos pasos preparatorios, los científicos de datos pueden mejorar significativamente la eficiencia y efectividad de sus modelos de aprendizaje profundo, allanando el camino para predicciones e insights más precisos.
7.1.1 Paso 1: Limpieza y Transformación de Datos
El primer paso en la preparación de datos para una red neuronal es un proceso crítico que implica garantizar que todas las características estén bien definidas, libres de ruido y sean relevantes para la tarea. Esta etapa inicial establece la base para un entrenamiento y rendimiento exitosos del modelo. Incluye un examen exhaustivo del conjunto de datos para identificar y abordar posibles problemas que puedan obstaculizar el proceso de aprendizaje.
Las características bien definidas son aquellas que tienen significados claros e interpretaciones dentro del contexto del problema. Esto a menudo requiere experiencia en el dominio para comprender qué atributos son más propensos a contribuir al poder predictivo del modelo. Las características deben seleccionarse o diseñarse para capturar la esencia del problema que se está resolviendo.
Eliminar el ruido de los datos es crucial, ya que las redes neuronales pueden ser sensibles a variaciones irrelevantes. El ruido puede presentarse en diversas formas, como errores de medición, valores atípicos o información irrelevante. Las técnicas como el suavizado, la detección de valores atípicos y la selección de características pueden emplearse para reducir el ruido y mejorar la relación señal-ruido en el conjunto de datos.
Asegurar la relevancia de las características implica centrarse en los atributos que tienen más probabilidades de contribuir al poder predictivo del modelo. Esto puede involucrar técnicas de selección de características, la aplicación de conocimiento del dominio o incluso la creación de nuevas características mediante ingeniería de características. Las características relevantes ayudan al modelo a aprender patrones y relaciones significativas, lo que lleva a una mejor generalización y rendimiento en datos no vistos.
Al abordar meticulosamente estos aspectos en el paso inicial de la preparación de datos, establecemos una base sólida para las etapas posteriores de escalado, normalización y codificación, mejorando finalmente la capacidad de la red neuronal para aprender eficazmente de los datos.
Transformaciones Comunes
- Manejo de Valores Faltantes:
- Las redes neuronales requieren conjuntos de datos completos para un rendimiento óptimo. Los valores faltantes pueden llevar a predicciones sesgadas o inexactas, haciendo que su manejo sea crucial.
- Estrategias comunes para abordar datos faltantes incluyen:
- Imputación: Rellenar valores faltantes con estimaciones. Los métodos varían desde simples (imputación de media, mediana o moda) hasta más complejos (imputación por regresión o imputación múltiple).
- Eliminación: Remover filas o columnas con valores faltantes. Este enfoque es sencillo, pero puede llevar a una pérdida significativa de datos si la falta es prevalente.
- Uso de algoritmos que manejen valores faltantes: Algunos métodos avanzados, como ciertos árboles de decisión, pueden trabajar directamente con datos faltantes.
- Específicamente para aprendizaje profundo:
- Datos numéricos: La imputación por media es frecuentemente utilizada debido a su simplicidad y efectividad, aunque métodos más sofisticados como imputación k-NN o el uso de autoencoders pueden dar mejores resultados.
- Datos categóricos: Crear una nueva categoría para valores faltantes es común, permitiendo al modelo aprender patrones relacionados con la falta de datos.
- En modelos secuenciales, una capa de enmascaramiento puede ignorar valores faltantes durante el entrenamiento y la predicción.
- Eliminación de Valores Atípicos:
- Los valores atípicos pueden impactar significativamente el rendimiento de las redes neuronales, llevando a un aprendizaje inestable y a una generalización deficiente. Identificar y abordar valores atípicos es crucial para mantener la consistencia de los datos y mejorar la robustez del modelo.
- Estrategias para manejar valores atípicos incluyen:
- Eliminación: En algunos casos, eliminar completamente puntos de datos identificados como valores atípicos puede ser apropiado, aunque debe hacerse con precaución para evitar perder información valiosa.
- Transformación: Aplicar transformaciones matemáticas como logaritmos o raíces cuadradas puede ayudar a reducir el impacto de valores extremos mientras se preserva el punto de datos.
- Winsorización: Esta técnica consiste en limitar valores extremos a un percentil específico de los datos, reduciendo efectivamente su impacto sin eliminarlos por completo.
- Para características numéricas, implementar una estrategia de límites puede ser particularmente efectiva:
- Establecer límites superiores e inferiores basados en conocimiento del dominio o medidas estadísticas (p. ej., 3 desviaciones estándar de la media).
- Reemplazar valores que excedan estos límites con los valores límite respectivos.
- Esta aproximación preserva la distribución general mientras mitiga el efecto de valores atípicos extremos.
- Es importante destacar que la elección del método para manejar valores atípicos puede impactar significativamente el rendimiento del modelo. Por lo tanto, es beneficioso experimentar con diferentes enfoques y evaluar sus efectos en los resultados del modelo.
- Transformando características para compatibilidad con redes neuronales
Las redes neuronales requieren características de entrada numéricas para un procesamiento óptimo. Esto hace necesario transformar varios tipos de datos:
- Características categóricas: Estas deben codificarse en representaciones numéricas para ser compatibles con las redes neuronales. Métodos comunes incluyen:
- Codificación one-hot: Crea columnas binarias para cada categoría. Este método es particularmente útil para datos nominales sin un orden inherente. Por ejemplo, si tenemos una característica "color" con categorías "rojo", "azul" y "verde", la codificación one-hot crearía tres columnas binarias separadas, una para cada color.
- Codificación por etiquetas: Asigna un número entero único a cada categoría. Este enfoque es más adecuado para datos ordinales donde existe un orden significativo en las categorías. Por ejemplo, niveles educativos como "secundaria", "licenciatura" y "maestría" podrían codificarse como 1, 2 y 3, respectivamente.
- Capas de embeddings: Se utilizan para variables categóricas de alta cardinalidad, que son características con un gran número de categorías únicas. Los embeddings aprenden una representación vectorial densa para cada categoría, capturando relaciones semánticas entre ellas. Esto es particularmente efectivo en tareas de procesamiento de lenguaje natural o al trabajar con características como IDs de productos en sistemas de recomendación.
- Codificación por objetivo: Esta técnica avanzada reemplaza las categorías con el promedio de la variable objetivo para esa categoría. Es útil cuando existe una relación fuerte entre la categoría y la variable objetivo, pero debe usarse con precaución para evitar el sobreajuste.
La elección del método de codificación depende de la naturaleza de la variable categórica, los requisitos específicos de la arquitectura de la red neuronal y las características del problema que se desea resolver. Es beneficioso experimentar con diferentes técnicas de codificación para determinar cuál ofrece el mejor rendimiento para una tarea dada.
- Datos de texto: Requieren tokenización y embeddings, lo que implica:
- Dividir el texto en palabras o subpalabras individuales (tokens). Este proceso puede variar según el idioma y los requisitos específicos de la tarea. Por ejemplo, en inglés, una tokenización basada en espacios puede ser suficiente para muchas aplicaciones, mientras que idiomas más complejos pueden requerir tokenizadores especializados.
- Convertir los tokens en índices numéricos. Este paso crea un vocabulario donde a cada token único se le asigna un ID entero único. Esta conversión es necesaria porque las redes neuronales operan con datos numéricos.
- Aplicar embeddings de palabras para representaciones semánticas. Este paso crucial transforma los tokens en representaciones vectoriales densas que capturan relaciones semánticas entre palabras. Hay varios enfoques:
- Embeddings preentrenados: Utilizar modelos como Word2Vec, GloVe o FastText, entrenados en grandes corpus para capturar patrones generales del lenguaje.
- Embeddings específicos de la tarea: Entrenar embeddings desde cero en un conjunto de datos específico, lo que permite capturar relaciones semánticas específicas del dominio.
- Embeddings contextualizados: Usar modelos como BERT o GPT, que generan embeddings dinámicos basados en el contexto en el que aparece una palabra.
- Manejar palabras fuera del vocabulario (OOV): Implementar estrategias como usar un token especial "desconocido", emplear tokenización por subpalabras (e.g., WordPiece, Byte-Pair Encoding) o usar modelos a nivel de caracteres.
- Datos de series temporales: Requieren transformaciones especializadas para capturar patrones y dependencias temporales:
- Creación de características de desfase: Representan valores pasados de la variable objetivo u otras características relevantes. Por ejemplo, al predecir precios de acciones, se pueden incluir los precios del día, semana o mes anteriores como características.
- Aplicación de promedios móviles u otras estadísticas rodantes: Estas suavizan las fluctuaciones a corto plazo y destacan las tendencias a largo plazo. Las técnicas comunes incluyen promedios móviles simples, promedios móviles exponenciales y desviaciones estándar rodantes.
- Codificación de características cíclicas: Muchas series temporales tienen patrones cíclicos basados en períodos de tiempo. Por ejemplo:
- Día de la semana: Se puede codificar usando transformaciones seno y coseno para capturar la naturaleza circular de los patrones semanales.
- Mes del año: Codificado de manera similar para representar ciclos anuales.
- Hora del día: Útil para capturar patrones diarios en datos de alta frecuencia.
- Diferenciación: Tomar la diferencia entre pasos consecutivos puede ayudar a hacer estacionaria una serie temporal, lo cual es un requisito común para muchos modelos de series temporales.
- Descomposición: Separar una serie temporal en sus componentes de tendencia, estacionalidad y residuales puede proporcionar características valiosas para que el modelo aprenda.
- Datos de imágenes: Requieren preprocesamiento específico para garantizar un rendimiento óptimo en redes neuronales:
- Redimensionamiento a dimensiones consistentes: Este paso es crucial ya que las redes neuronales, particularmente las redes neuronales convolucionales (CNNs), requieren imágenes de entrada de tamaño uniforme. El redimensionamiento ayuda a estandarizar la entrada, permitiendo que la red procese imágenes de manera eficiente sin importar sus dimensiones originales.
- Normalización de valores de píxeles: Normalmente, esto implica escalar las intensidades de los píxeles a un rango de 0-1 o -1 a 1. La normalización es esencial porque:
- Ayuda a una convergencia más rápida durante el entrenamiento al asegurar que todas las características estén en una escala similar.
- Mitiga el impacto de condiciones de iluminación o configuraciones de cámara variables.
- Permite que el modelo trate las características de manera más equitativa, evitando que los píxeles de alta intensidad dominen.
- Aplicación de técnicas de aumento de datos: Esto es fundamental para aumentar la robustez del modelo y mejorar su capacidad de generalización. El aumento de datos amplía artificialmente el conjunto de entrenamiento creando versiones modificadas de imágenes existentes. Técnicas comunes incluyen:
- Transformaciones geométricas: Rotaciones, volteos, escalado y traslaciones.
- Aumentaciones del espacio de color: Ajustes de brillo, contraste o aplicación de modificaciones en el color.
- Adición de ruido o aplicación de filtros: Ruido gaussiano, desenfoque o efectos de nitidez.
- Mezcla de imágenes: Técnicas como mixup o CutMix que combinan múltiples imágenes de entrenamiento.
- Estandarización por canal: Para imágenes multicanal (e.g., RGB), a menudo es beneficioso estandarizar cada canal por separado.
- Manejo de datos faltantes o corruptos: Implementar estrategias para manejar imágenes incompletas o dañadas, como descartar, interpolar o usar modelos generativos para reconstruir partes faltantes.
Ejemplo: Limpieza y transformación de un conjunto de datos de muestra
Exploremos un ejemplo práctico utilizando Pandas para limpiar y preparar datos con valores faltantes y atípicos. Este proceso es crucial en la preprocesamiento de datos para modelos de aprendizaje profundo, ya que asegura la calidad y consistencia de los datos. Abordaremos paso a paso cómo manejar problemas comunes de datos:
- Valores faltantes: Demostraremos técnicas para imputar o eliminar puntos de datos faltantes, que pueden impactar significativamente el rendimiento del modelo si no se abordan.
- Atípicos: Exploraremos métodos para identificar y tratar valores atípicos, que pueden distorsionar distribuciones y afectar el entrenamiento del modelo.
- Transformación de datos: Mostraremos cómo convertir variables categóricas en un formato adecuado para redes neuronales.
Al final de este ejemplo, tendrás una comprensión clara de cómo aplicar estas técnicas esenciales de limpieza de datos utilizando Python y Pandas, sentando las bases para pasos más avanzados de ingeniería de características.
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
# Sample dataset
data = {
'age': [25, 30, np.nan, 35, 40, 100, 28, 45, np.nan, 50],
'income': [50000, 60000, 45000, 70000, np.nan, 200000, 55000, np.nan, 65000, 75000],
'category': ['A', 'B', np.nan, 'A', 'B', 'C', 'A', 'C', 'B', np.nan],
'education': ['High School', 'Bachelor', 'Master', np.nan, 'PhD', 'Bachelor', 'Master', 'High School', 'PhD', 'Bachelor']
}
df = pd.DataFrame(data)
# Display original data
print("Original Data:")
print(df)
print("\n")
# Define preprocessing steps for numerical and categorical columns
numeric_features = ['age', 'income']
categorical_features = ['category', 'education']
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
categorical_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='constant', fill_value='Unknown')),
('onehot', OneHotEncoder(handle_unknown='ignore'))
])
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
])
# Fit and transform the data
X_processed = preprocessor.fit_transform(df)
# Convert to DataFrame for better visualization
feature_names = (numeric_features +
preprocessor.named_transformers_['cat'].named_steps['onehot'].get_feature_names(categorical_features).tolist())
df_processed = pd.DataFrame(X_processed, columns=feature_names)
# Handle outliers (e.g., cap age at 99th percentile)
age_cap = np.percentile(df['age'].dropna(), 99)
df['age'] = np.where(df['age'] > age_cap, age_cap, df['age'])
print("Processed Data:")
print(df_processed)
# Additional statistics
print("\nData Statistics:")
print(df_processed.describe())
print("\nMissing Values After Processing:")
print(df_processed.isnull().sum())
print("\nUnique Values in Categorical Columns:")
for col in categorical_features:
print(f"{col}: {df[col].nunique()}")
Explicación del desglose del código:
- Importación de bibliotecas:
Importamos las bibliotecas necesarias:
pandas
para la manipulación de datos,numpy
para operaciones numéricas y varios módulos descikit-learn
para tareas de preprocesamiento. - Creación de un conjunto de datos de muestra:
Creamos un conjunto de datos más diverso con 10 entradas, incluyendo valores faltantes (
np.nan
) en diferentes columnas. Este conjunto de datos incluye una columna adicional llamadaeducation
para demostrar cómo manejar múltiples variables categóricas. - Visualización de los datos originales:
Imprimimos el conjunto de datos original para mostrar el estado inicial, incluidos los valores faltantes y posibles valores atípicos.
- Definición de los pasos de preprocesamiento:
Separamos nuestras características en columnas numéricas y categóricas. Luego, creamos pipelines de preprocesamiento para cada tipo:
- Para características numéricas: Usamos
SimpleImputer
para llenar valores faltantes con la mediana, y luego aplicamosStandardScaler
para normalizar los datos. - Para características categóricas: Usamos
SimpleImputer
para llenar valores faltantes con "Unknown", y luego aplicamosOneHotEncoder
para convertir las categorías en columnas binarias.
- Para características numéricas: Usamos
- Creación de un ColumnTransformer:
Usamos
ColumnTransformer
para aplicar diferentes pasos de preprocesamiento a distintas columnas, lo que nos permite manejar datos numéricos y categóricos simultáneamente. - Ajuste y transformación de datos:
Aplicamos nuestros pasos de preprocesamiento a todo el conjunto de datos usando
fit_transform()
. - Conversión a DataFrame:
Convertimos los datos procesados nuevamente en un
DataFrame
de pandas para facilitar su visualización y análisis. También creamos nombres de columnas apropiados para las variables categóricas codificadas con one-hot. - Manejo de valores atípicos:
En lugar de usar un valor fijo, limitamos la columna
age
al percentil 99. Este enfoque es más dinámico, ya que se adapta a la distribución de los datos. - Visualización de los datos procesados:
Imprimimos el conjunto de datos procesado para mostrar los resultados de los pasos de preprocesamiento.
- Estadísticas adicionales:
Proporcionamos más información sobre los datos procesados:
- Estadísticas básicas de los datos procesados utilizando
describe()
- Verificación de valores faltantes restantes
- Conteo de valores únicos en las columnas categóricas originales
Este ejemplo demuestra un enfoque robusto y completo para el preprocesamiento de datos para aprendizaje profundo. Maneja adecuadamente los valores faltantes, escala las características numéricas, codifica variables categóricas y aborda valores atípicos, mientras mantiene visibilidad clara de los datos en cada paso. Este enfoque es especialmente adecuado para escenarios del mundo real, donde los conjuntos de datos suelen incluir múltiples tipos de características y presentan varios desafíos de calidad de datos.
7.1.2 Paso 2: Escalado y Normalización
Las redes neuronales son altamente sensibles a la escala de los datos de entrada, lo que puede impactar significativamente su rendimiento y eficiencia. Las características con rangos muy diferentes pueden dominar el proceso de aprendizaje, lo que podría llevar a resultados sesgados o subóptimos. Para abordar este problema, los científicos de datos emplean técnicas de escalado y normalización, asegurando que todas las características de entrada contribuyan de manera equitativa al proceso de aprendizaje.
Existen dos métodos principales para este propósito:
Normalización
Esta técnica escala los datos a un rango específico, típicamente entre 0 y 1. La normalización es particularmente útil cuando se trabaja con características que tienen límites naturales, como valores de píxeles en imágenes (0-255) o métricas basadas en porcentajes (0-100%). Al mapear estos valores a un rango consistente, evitamos que las características con valores absolutos mayores eclipsen a aquellas con rangos más pequeños.
El proceso de normalización implica transformar los valores originales utilizando una fórmula matemática que mantiene las relaciones relativas entre los puntos de datos mientras los restringe dentro de un rango predeterminado. Esta transformación es especialmente beneficiosa en modelos de aprendizaje profundo por varias razones:
- Mejora de la convergencia del modelo: Las características normalizadas a menudo conducen a una convergencia más rápida y estable durante el entrenamiento, ya que el modelo no necesita aprender escalas muy diferentes para distintas características.
- Mayor interpretabilidad de las características: Cuando todas las características están en la misma escala, es más fácil interpretar su importancia relativa y su impacto en las predicciones del modelo.
- Mitigación de inestabilidad numérica: Los valores grandes pueden, en ocasiones, causar inestabilidad numérica en las redes neuronales, particularmente al usar funciones de activación como sigmoide o tangente hiperbólica. La normalización ayuda a prevenir estos problemas.
Las técnicas comunes de normalización incluyen el escalado Min-Max, que mapea el valor mínimo a 0 y el máximo a 1, y el escalado decimal, que mueve el punto decimal de los valores para crear un rango deseado. La elección del método de normalización a menudo depende de los requisitos específicos del modelo y la naturaleza de los datos que se están procesando.
Estandarización Este método reescala los datos para tener una media de cero y una desviación estándar de uno. La estandarización es especialmente beneficiosa al trabajar con conjuntos de datos que contienen características con escalas y distribuciones variables. Al centrar los datos alrededor de cero y escalarlos a una varianza unitaria, la estandarización garantiza que cada característica contribuya proporcionalmente al proceso de aprendizaje del modelo, independientemente de su escala original.
El proceso de estandarización implica restar el valor medio de cada característica de los puntos de datos y luego dividir por la desviación estándar. Esta transformación resulta en una distribución donde aproximadamente el 68% de los valores caen dentro de una desviación estándar de la media, el 95% dentro de dos desviaciones estándar y el 99.7% dentro de tres desviaciones estándar.
La estandarización ofrece varias ventajas en el contexto del aprendizaje profundo:
- Mejora del descenso del gradiente: Las características estandarizadas a menudo conducen a una convergencia más rápida durante la optimización, ya que el algoritmo de descenso del gradiente puede navegar más fácilmente por el espacio de características.
- Importancia de las características: Cuando las características están estandarizadas, sus coeficientes en el modelo pueden compararse directamente para evaluar su importancia relativa.
- Manejo de valores atípicos: La estandarización puede ayudar a mitigar el impacto de los valores atípicos al escalarlos en relación con la desviación estándar de la característica.
Sin embargo, es importante tener en cuenta que la estandarización no limita los valores a un rango específico, lo que puede ser una consideración para ciertas arquitecturas de redes neuronales o al trabajar con características que tienen límites naturales.
La elección entre normalización y estandarización a menudo depende de las características específicas del conjunto de datos y los requisitos de la arquitectura de la red neuronal. Por ejemplo:
- Las redes neuronales convolucionales (CNNs) para el procesamiento de imágenes suelen funcionar bien con datos normalizados, ya que los valores de píxeles naturalmente caen dentro de un rango fijo.
- Las redes neuronales recurrentes (RNNs) y otras arquitecturas que trabajan con series temporales o datos tabulares suelen beneficiarse de la estandarización, especialmente cuando las características tienen diferentes unidades o escalas.
Es importante destacar que el escalado debe aplicarse de manera consistente en los conjuntos de entrenamiento, validación y prueba para mantener la integridad de la evaluación del rendimiento del modelo. Además, al trabajar con datos nuevos y no vistos durante la inferencia, es crucial aplicar los mismos parámetros de escalado utilizados durante el entrenamiento para garantizar la consistencia en las predicciones del modelo.
Ejemplo: Escalado y normalización de características Profundicemos en el escalado de características numéricas utilizando dos métodos populares de Scikit-Learn: StandardScaler
y MinMaxScaler
. Estas técnicas son cruciales para preparar los datos para redes neuronales, ya que ayudan a garantizar que todas las características contribuyan de manera equitativa al proceso de aprendizaje del modelo.
StandardScaler
transforma los datos para tener una media de 0 y una desviación estándar de 1. Esto es particularmente útil cuando tus características tienen diferentes unidades o escalas. Por ejemplo, si tienes características como edad (0-100) e ingresos (de miles a millones), StandardScaler
las llevará a una escala comparable.
Por otro lado, MinMaxScaler
escala los datos a un rango fijo, típicamente entre 0 y 1. Esto es beneficioso cuando necesitas que tus características tengan un rango específico y delimitado, lo cual puede ser importante para ciertos algoritmos o cuando deseas preservar valores cero en datos dispersos.
La elección entre estos escaladores a menudo depende de la naturaleza de tus datos y los requisitos de tu red neuronal. En el siguiente ejemplo, demostraremos cómo aplicar ambas técnicas de escalado a un conjunto de datos de muestra.
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler
import matplotlib.pyplot as plt
# Sample data
X = np.array([[25, 50000], [30, 60000], [35, 70000], [40, 80000], [45, 90000], [50, 100000], [55, 110000], [60, 120000]])
df = pd.DataFrame(X, columns=['Age', 'Income'])
# Standardization
scaler = StandardScaler()
X_standardized = scaler.fit_transform(X)
df_standardized = pd.DataFrame(X_standardized, columns=['Age_std', 'Income_std'])
# Normalization (Min-Max Scaling)
normalizer = MinMaxScaler()
X_normalized = normalizer.fit_transform(X)
df_normalized = pd.DataFrame(X_normalized, columns=['Age_norm', 'Income_norm'])
# Robust Scaling
robust_scaler = RobustScaler()
X_robust = robust_scaler.fit_transform(X)
df_robust = pd.DataFrame(X_robust, columns=['Age_robust', 'Income_robust'])
# Combine all scaled data
df_combined = pd.concat([df, df_standardized, df_normalized, df_robust], axis=1)
# Display results
print("Combined Data:")
print(df_combined)
# Visualize the scaling effects
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
fig.suptitle('Comparison of Scaling Techniques')
axes[0, 0].scatter(df['Age'], df['Income'])
axes[0, 0].set_title('Original Data')
axes[0, 1].scatter(df_standardized['Age_std'], df_standardized['Income_std'])
axes[0, 1].set_title('Standardized Data')
axes[1, 0].scatter(df_normalized['Age_norm'], df_normalized['Income_norm'])
axes[1, 0].set_title('Normalized Data')
axes[1, 1].scatter(df_robust['Age_robust'], df_robust['Income_robust'])
axes[1, 1].set_title('Robust Scaled Data')
for ax in axes.flat:
ax.set(xlabel='Age', ylabel='Income')
plt.tight_layout()
plt.show()
Explicación del desglose del código
- Importación de bibliotecas:
Se importan
numpy
para operaciones numéricas,pandas
para manipulación de datos,sklearn
para herramientas de preprocesamiento ymatplotlib
para visualización. - Creación de datos de muestra:
Se crea un conjunto de datos más amplio con 8 entradas, incluyendo datos de edad e ingresos. Esto proporciona un conjunto de datos más completo para demostrar los efectos del escalado.
- Estandarización (
StandardScaler
):- Transforma las características para tener una media de 0 y una desviación estándar de 1.
- Es útil cuando las características tienen diferentes escalas o unidades.
- Fórmula: z = (x - μ) / σ, donde μ es la media y σ es la desviación estándar.
- Normalización (
MinMaxScaler
):- Escala las características a un rango fijo, típicamente entre 0 y 1.
- Preserva valores cero y no centra los datos.
- Fórmula: x_scaled = (x - x_min) / (x_max - x_min).
- Escalado robusto (
RobustScaler
):- Escala las características utilizando estadísticas robustas a valores atípicos.
- Utiliza la mediana y el rango intercuartil en lugar de la media y la desviación estándar.
- Es útil cuando los datos contienen muchos valores atípicos.
- Combinación de datos:
Se combinan los conjuntos de datos originales y escalados en un único
DataFrame
para facilitar la comparación. - Visualización:
- Se crea una cuadrícula de gráficos de dispersión 2x2 para visualizar los efectos de las diferentes técnicas de escalado.
- Esto permite una comparación directa de cómo cada método transforma los datos.
Puntos clave:
StandardScaler
centra los datos y los escala a una varianza unitaria, como se observa en el gráfico estandarizado donde los datos están centrados alrededor de (0,0).MinMaxScaler
comprime todos los puntos de datos a un rango fijo [0,1], manteniendo la forma de la distribución original.RobustScaler
produce un resultado similar aStandardScaler
, pero es menos influenciado por valores atípicos.
Este ejemplo ofrece un examen exhaustivo de varias técnicas de escalado, su impacto en los datos y métodos para visualizar estas transformaciones. Es especialmente valioso para comprender cómo los enfoques de escalado afectan tu conjunto de datos antes de ingresarlo en una red neuronal.
7.1.3 Paso 3: Codificación de variables categóricas
Los datos categóricos requieren codificación antes de ser introducidos en una red neuronal. Este proceso transforma datos no numéricos en un formato que las redes neuronales pueden procesar eficazmente. Existen varias técnicas de codificación, cada una con sus fortalezas y casos de uso:
Codificación One-Hot
Este método transforma variables categóricas en un formato que las redes neuronales pueden procesar de manera efectiva. Crea un vector binario para cada categoría, donde cada valor único de la categoría se representa mediante una columna separada. Por ejemplo, considera una categoría "color" con valores "rojo", "azul" y "verde". La codificación one-hot generaría tres nuevas columnas: "color_rojo", "color_azul" y "color_verde". En cada fila, la columna correspondiente al color presente contendría un 1, mientras que las otras serían 0.
Esta técnica de codificación es particularmente valiosa para categorías nominales que carecen de un orden inherente. Al crear columnas binarias separadas para cada categoría, la codificación one-hot evita imponer relaciones numéricas artificiales entre las categorías. Esto es crucial porque las redes neuronales podrían interpretar las codificaciones numéricas como si tuvieran un orden o magnitud significativos.
Sin embargo, la codificación one-hot presenta algunas consideraciones importantes:
- Dimensionalidad: Para categorías con muchos valores únicos, la codificación one-hot puede aumentar significativamente el número de características de entrada, lo que podría conducir a la "maldición de la dimensionalidad".
- Esparcimiento: Los datos codificados resultantes pueden ser dispersos, con muchos valores 0, lo que podría afectar la eficiencia de algunos algoritmos.
- Manejo de nuevas categorías: La codificación one-hot puede enfrentar problemas con categorías nuevas y no vistas en datos de prueba o de producción que no estaban presentes durante el entrenamiento.
A pesar de estos desafíos, la codificación one-hot sigue siendo un método popular y efectivo para preparar datos categóricos para redes neuronales, especialmente al trabajar con categorías nominales de baja a moderada cardinalidad.
Aquí tienes un ejemplo de cómo implementar la codificación one-hot utilizando Python y la biblioteca pandas
.
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green'],
'size': ['small', 'medium', 'large', 'medium', 'small']
})
# Initialize the OneHotEncoder
encoder = OneHotEncoder(sparse=False)
# Fit and transform the data
encoded_data = encoder.fit_transform(data)
# Get feature names
feature_names = encoder.get_feature_names_out(['color', 'size'])
# Create a new DataFrame with encoded data
encoded_df = pd.DataFrame(encoded_data, columns=feature_names)
print("Original data:")
print(data)
print("\nOne-hot encoded data:")
print(encoded_df)
Explicación del desglose del código
- Importar las bibliotecas necesarias: Importamos
pandas
para la manipulación de datos yOneHotEncoder
desklearn
para la codificación one-hot. - Crear datos de muestra: Creamos un DataFrame simple con dos columnas categóricas: "color" y "size".
- Inicializar
OneHotEncoder
: Creamos una instancia deOneHotEncoder
consparse=False
para obtener una salida en forma de matriz densa en lugar de una matriz dispersa. - Ajustar y transformar los datos: Usamos el método
fit_transform
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Obtener nombres de características: Usamos
get_feature_names_out
para obtener los nombres de las nuevas columnas codificadas. - Crear un nuevo DataFrame: Creamos un nuevo DataFrame con los datos codificados, utilizando los nombres de las características como etiquetas de las columnas.
- Imprimir resultados: Mostramos tanto los datos originales como los codificados para comparación.
Este código demuestra cómo la codificación one-hot transforma las variables categóricas en un formato adecuado para modelos de aprendizaje automático, incluidas las redes neuronales. Cada valor único de categoría se convierte en una columna separada, con valores binarios que indican la presencia (1) o ausencia (0) de esa categoría en cada fila.
Cuando ejecutas este código, puedes observar cómo los datos categóricos originales se transforman en un formato codificado one-hot, donde cada valor único de categoría tiene su propia columna con indicadores binarios.
Codificación por etiquetas
Esta técnica asigna a cada categoría un número entero único. Por ejemplo, "rojo" podría codificarse como 0, "azul" como 1 y "verde" como 2. Aunque es eficiente en términos de uso de memoria, la codificación por etiquetas es más adecuada para datos ordinales (categorías con un orden significativo). Es importante tener en cuenta que las redes neuronales podrían interpretar el orden de las etiquetas como significativo, lo que puede llevar a suposiciones incorrectas en categorías nominales.
La codificación por etiquetas es particularmente útil al trabajar con variables ordinales, donde el orden de las categorías importa. Por ejemplo, al codificar niveles educativos (e.g., "Secundaria", "Licenciatura", "Maestría", "Doctorado"), la codificación por etiquetas preserva el orden inherente, lo cual puede ser significativo para el modelo.
Sin embargo, la codificación por etiquetas tiene limitaciones cuando se aplica a categorías nominales (aquellas sin un orden inherente). Por ejemplo, codificar razas de perros como números (e.g., Labrador = 0, Poodle = 1, Beagle = 2) podría llevar al modelo a inferir incorrectamente que la diferencia numérica entre razas tiene un significado.
La implementación de la codificación por etiquetas es sencilla utilizando bibliotecas como scikit-learn
.
import pandas as pd
from sklearn.preprocessing import LabelEncoder
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green', 'blue', 'yellow'],
'size': ['small', 'medium', 'large', 'medium', 'small', 'large', 'medium']
})
# Initialize LabelEncoder
le_color = LabelEncoder()
le_size = LabelEncoder()
# Fit and transform the data
data['color_encoded'] = le_color.fit_transform(data['color'])
data['size_encoded'] = le_size.fit_transform(data['size'])
print("Original and encoded data:")
print(data)
print("\nUnique categories and their encoded values:")
print("Colors:", dict(zip(le_color.classes_, le_color.transform(le_color.classes_))))
print("Sizes:", dict(zip(le_size.classes_, le_size.transform(le_size.classes_))))
# Demonstrate inverse transform
color_codes = [0, 1, 2, 3]
size_codes = [0, 1, 2]
print("\nDecoding back to original categories:")
print("Colors:", le_color.inverse_transform(color_codes))
print("Sizes:", le_size.inverse_transform(size_codes))
Explicación del desglose del código
- Importación de bibliotecas:
- Importamos
pandas
para la manipulación de datos yLabelEncoder
desklearn
para codificar variables categóricas.
- Importamos
- Creación de datos de muestra:
- Creamos un DataFrame con dos columnas categóricas: "color" y "size".
- Este ejemplo incluye datos más diversos para demostrar mejor el proceso de codificación.
- Inicialización de
LabelEncoder
:- Creamos dos instancias separadas de
LabelEncoder
, una para "color" y otra para "size". - Esto nos permite codificar cada categoría de forma independiente.
- Creamos dos instancias separadas de
- Ajuste y transformación de datos:
- Usamos
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso. - Los valores codificados se añaden como nuevas columnas en el DataFrame.
- Usamos
- Visualización de resultados:
- Imprimimos los datos originales junto con los datos codificados para facilitar la comparación.
- Mostrar los mapeos de codificación:
- Creamos diccionarios para mostrar cómo cada categoría única se mapea a su valor codificado.
- Esto ayuda a comprender e interpretar los datos codificados.
- Demostración de transformación inversa:
- Mostramos cómo decodificar los valores numéricos de nuevo a sus categorías originales.
- Esto es útil cuando necesitas convertir predicciones o datos codificados a un formato comprensible para los humanos.
Este ejemplo proporciona una visión completa de la codificación por etiquetas. Demuestra cómo manejar múltiples variables categóricas, muestra el mapeo entre las categorías originales y los valores codificados, e incluye el proceso de transformación inversa. Este enfoque ofrece una comprensión más profunda de cómo funciona la codificación por etiquetas y cómo puede aplicarse en escenarios del mundo real.
Al utilizar la codificación por etiquetas, es crucial documentar el esquema de codificación y garantizar una aplicación consistente en los conjuntos de datos de entrenamiento, validación y prueba. Además, para modelos sensibles a la magnitud de las características de entrada (como redes neuronales), puede ser necesario escalar los valores codificados para evitar que el modelo atribuya una importancia indebida a las categorías con representaciones numéricas mayores.
Codificación Binaria
Este método combina aspectos tanto de la codificación one-hot como de la codificación por etiquetas, ofreciendo un equilibrio entre eficiencia e información preservada. Opera en dos pasos:
- Asignación de enteros: A cada categoría única se le asigna un entero, similar a la codificación por etiquetas.
- Conversión a binario: El entero asignado se convierte en su representación binaria.
Por ejemplo, si tenemos las categorías A, B, C y D, podrían asignarse los enteros 0, 1, 2 y 3 respectivamente. En binario, estos se representarían como 00, 01, 10 y 11.
Las ventajas de la codificación binaria incluyen:
- Eficiencia de memoria: Requiere menos columnas que la codificación one-hot, especialmente para categorías con muchos valores únicos. Para n categorías, la codificación binaria utiliza log2(n) columnas, mientras que la codificación one-hot utiliza n columnas.
- Preservación de información: A diferencia de la codificación por etiquetas, no impone una relación ordinal arbitraria entre categorías.
- Reducción de dimensionalidad: Crea menos características nuevas en comparación con la codificación one-hot, lo que puede ser beneficioso para el entrenamiento del modelo y la reducción del sobreajuste.
Sin embargo, la codificación binaria también tiene algunas consideraciones:
- Interpretación: Las características binarias resultantes pueden ser menos interpretables que las características codificadas one-hot.
- Compatibilidad con modelos: No todos los modelos pueden manejar características codificadas binariamente de manera óptima, por lo que es importante considerar los requisitos específicos de tu algoritmo elegido.
La codificación binaria es particularmente útil en escenarios donde se manejan variables categóricas de alta cardinalidad y la eficiencia de memoria es una preocupación, como en aplicaciones de aprendizaje automático a gran escala o cuando se trabaja con recursos computacionales limitados.
Aquí tienes un ejemplo de cómo implementar la codificación binaria utilizando Python y la biblioteca category_encoders
.
import pandas as pd
import category_encoders as ce
# Sample data
data = pd.DataFrame({
'color': ['red', 'blue', 'green', 'red', 'green', 'blue', 'yellow'],
'size': ['small', 'medium', 'large', 'medium', 'small', 'large', 'medium']
})
# Initialize BinaryEncoder
encoder = ce.BinaryEncoder(cols=['color', 'size'])
# Fit and transform the data
encoded_data = encoder.fit_transform(data)
print("Original data:")
print(data)
print("\nBinary encoded data:")
print(encoded_data)
# Display mapping
print("\nEncoding mapping:")
print(encoder.mapping)
Explicación del desglose del código
- Importar bibliotecas:
- Importamos
pandas
para la manipulación de datos ycategory_encoders
para la codificación binaria.
- Importamos
- Crear datos de muestra:
- Creamos un DataFrame con dos columnas categóricas: "color" y "size".
- Inicializar
BinaryEncoder
:- Creamos una instancia de
BinaryEncoder
, especificando qué columnas codificar.
- Creamos una instancia de
- Ajustar y transformar datos:
- Usamos
fit_transform()
para ajustar el codificador a nuestros datos y transformarlos en un solo paso.
- Usamos
- Visualizar resultados:
- Imprimimos los datos originales y los datos codificados binariamente para comparación.
- Mostrar mapeo de codificación:
- Mostramos el mapeo para ver cómo cada categoría se codifica en binario.
Cuando ejecutas este código, puedes observar cómo cada categoría única en "color" y "size" se transforma en un conjunto de columnas binarias. El número de columnas binarias para cada característica depende del número de categorías únicas en esa característica.
La codificación binaria proporciona una representación compacta de variables categóricas, especialmente útil para características de alta cardinalidad. Encuentra un equilibrio entre la explosión dimensional de la codificación one-hot y las suposiciones ordinales de la codificación por etiquetas, lo que la convierte en una herramienta valiosa en la ingeniería de características para aprendizaje profundo.
Embeddings
Para variables categóricas con alta cardinalidad (muchos valores únicos), los embeddings pueden ser una solución efectiva. Esta técnica aprende una representación vectorial de baja dimensión para cada categoría durante el proceso de entrenamiento de la red neuronal. Los embeddings pueden capturar relaciones complejas entre categorías y se utilizan comúnmente en tareas de procesamiento de lenguaje natural.
Los embeddings funcionan mapeando cada categoría a un vector denso en un espacio vectorial continuo. A diferencia de la codificación one-hot, que trata cada categoría como completamente distinta, los embeddings permiten comparaciones significativas entre categorías basadas en sus representaciones vectoriales aprendidas. Esto es particularmente útil al trabajar con grandes vocabularios en datos de texto o con variables categóricas que tienen similitudes o jerarquías inherentes.
La dimensionalidad del espacio de embeddings es un hiperparámetro que puede ajustarse. Por lo general, es mucho menor que el número de categorías únicas, lo que ayuda a reducir la complejidad del modelo y mitigar la maldición de la dimensionalidad. Por ejemplo, una variable categórica con 10,000 valores únicos podría incrustarse en un espacio de 50 o 100 dimensiones.
Una de las principales ventajas de los embeddings es su capacidad de generalización. Pueden capturar relaciones semánticas entre categorías, permitiendo que el modelo realice predicciones inteligentes incluso para categorías que no ha visto durante el entrenamiento. Esto es especialmente valioso en sistemas de recomendación, donde los embeddings pueden representar usuarios y elementos en un espacio compartido, facilitando el descubrimiento de preferencias y similitudes latentes.
En el contexto del aprendizaje profundo para datos tabulares, los embeddings pueden aprenderse como parte de la arquitectura de la red neuronal. Esto permite que el modelo descubra automáticamente representaciones óptimas para variables categóricas, adaptadas a la tarea específica. Los embeddings aprendidos también pueden visualizarse o analizarse por separado, proporcionando potencialmente ideas sobre las relaciones entre categorías que podrían no ser evidentes en los datos originales.
Aquí tienes un ejemplo de cómo implementar embeddings para variables categóricas utilizando TensorFlow/Keras.
import tensorflow as tf
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
# Sample data
data = pd.DataFrame({
'user_id': np.random.randint(1, 1001, 10000),
'product_id': np.random.randint(1, 501, 10000),
'purchase': np.random.randint(0, 2, 10000)
})
# Prepare features and target
X = data[['user_id', 'product_id']]
y = data['purchase']
# Split the data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Define the model
user_input = tf.keras.layers.Input(shape=(1,))
product_input = tf.keras.layers.Input(shape=(1,))
user_embedding = tf.keras.layers.Embedding(input_dim=1001, output_dim=50)(user_input)
product_embedding = tf.keras.layers.Embedding(input_dim=501, output_dim=50)(product_input)
user_vec = tf.keras.layers.Flatten()(user_embedding)
product_vec = tf.keras.layers.Flatten()(product_embedding)
concat = tf.keras.layers.Concatenate()([user_vec, product_vec])
dense = tf.keras.layers.Dense(64, activation='relu')(concat)
output = tf.keras.layers.Dense(1, activation='sigmoid')(dense)
model = tf.keras.Model(inputs=[user_input, product_input], outputs=output)
# Compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# Train the model
model.fit([X_train['user_id'], X_train['product_id']], y_train,
epochs=5, batch_size=32, validation_split=0.2)
# Evaluate the model
loss, accuracy = model.evaluate([X_test['user_id'], X_test['product_id']], y_test)
print(f"Test Accuracy: {accuracy:.4f}")
Explicación del desglose del código
- Preparación de datos:
- Creamos un conjunto de datos de muestra con IDs de usuarios, IDs de productos e información de compras.
- Los datos se dividen en conjuntos de entrenamiento y prueba.
- Arquitectura del modelo:
- Definimos capas de entrada separadas para
user_id
yproduct_id
. - Se crean capas de embeddings para los IDs de usuarios y productos. El
input_dim
se establece como el número de categorías únicas más uno (para considerar el posible indexado en cero), y eloutput_dim
se fija en 50 (la dimensión del embedding). - Los vectores embebidos se aplanan y concatenan.
- Se añaden capas densas para un procesamiento adicional, con una activación final sigmoide para clasificación binaria.
- Definimos capas de entrada separadas para
- Compilación y entrenamiento del modelo:
- El modelo se compila utilizando la pérdida de entropía cruzada binaria y el optimizador Adam.
- El modelo se entrena con los datos preparados.
- Evaluación:
- Se evalúa el rendimiento del modelo en el conjunto de prueba.
Este ejemplo demuestra cómo se pueden usar embeddings para representar variables categóricas de alta cardinalidad (IDs de usuarios y productos) en un espacio de menor dimensión. Las capas de embeddings aprenden a mapear cada ID único a un vector de 50 dimensiones durante el proceso de entrenamiento. Estos embeddings capturan relaciones significativas entre usuarios y productos, lo que permite al modelo realizar predicciones basadas en estas representaciones latentes.
Las principales ventajas de usar embeddings en este escenario incluyen:
- Reducción de dimensionalidad: En lugar de usar codificación one-hot, que resultaría en vectores dispersos de alta dimensionalidad, los embeddings proporcionan una representación densa y de menor dimensión.
- Captura de relaciones semánticas: El espacio de embeddings puede capturar similitudes entre usuarios o productos, incluso si no han sido vistos juntos en los datos de entrenamiento.
- Escalabilidad: Este enfoque se adapta bien a un gran número de categorías, lo que lo hace adecuado para aplicaciones del mundo real con muchos usuarios y productos.
Al usar embeddings, permitimos que la red neuronal aprenda representaciones óptimas de nuestras variables categóricas, específicamente adaptadas a la tarea de predecir compras. Esto puede conducir a un mejor rendimiento del modelo y una mejor generalización a datos no vistos.
La elección del método de codificación depende de la naturaleza de tus datos categóricos, los requisitos específicos de la arquitectura de tu red neuronal y el problema que estás tratando de resolver. Es beneficioso experimentar con diferentes técnicas de codificación para determinar cuál ofrece el mejor rendimiento para tu caso particular.
Preparar datos para redes neuronales es un proceso intrincado pero crucial que incluye limpieza, escalado y codificación de datos. Los datos correctamente transformados y escalados mejoran el proceso de aprendizaje, permitiendo que las redes neuronales converjan más rápido y ofrezcan resultados más precisos. Al garantizar que cada característica se maneje adecuadamente, ya sea escalando valores numéricos o codificando categorías, creamos una base sólida para un modelo de aprendizaje profundo exitoso.