Explicación del escalado de datos numéricos: una guía visual con ejemplos de código para principiantes | por Samy Baladram | Sep, 2024

PREPROCESAMIENTO DE DATOS

Transformación de datos de tamaño adulto en modelos infantiles

Las características numéricas de los conjuntos de datos sin procesar son como adultos en un mundo creado para adultos. Algunas son como rascacielos (piense en ingresos de miles de millones de dólares), mientras que otras son apenas visibles (como probabilidades de 0,001). Pero, ¿y nuestros modelos de aprendizaje automático? Son niños que luchan por comprender este mundo de adultos.

El escalamiento de datos (que incluye lo que algunos llaman “normalización”) es el proceso de transformar estos números de tamaño adulto en proporciones adecuadas para niños. Se trata de crear un campo de juego nivelado donde cada característica, grande o pequeña, pueda ser comprendida y valorada adecuadamente.

Vamos a ver cinco técnicas de escalado distintas, todas demostradas en un pequeño conjunto de datos (con algunas imágenes, por supuesto). Desde el delicado toque de normalización hasta las acrobacias matemáticas de la transformación de Box-Cox, verás por qué elegir el método de escalado correcto puede ser la fórmula secreta de tu receta de aprendizaje automático.

Todas las imágenes fueron creadas por el autor con Canva Pro. Optimizadas para dispositivos móviles; pueden verse demasiado grandes en computadoras de escritorio.

Antes de entrar en los detalles de las técnicas de escalamiento, es bueno entender qué tipos de datos se benefician del escalamiento y cuáles no:

Datos que normalmente no necesitan escalamiento:

  1. Variables categóricas:Por lo general, estos datos deben codificarse en lugar de escalarse. Esto incluye datos categóricos tanto nominales como ordinales.
  2. Variables binarias:Las características que solo pueden tomar dos valores (0 y 1, o Verdadero y Falso) generalmente no necesitan escala.
  3. Contar datos:Los recuentos de números enteros suelen tener sentido tal como son y la escala puede dificultar su comprensión. En cambio, trátelos como categóricos. Existen algunas excepciones, especialmente con rangos de recuentos muy amplios.
  4. Características cíclicas:Los datos con una naturaleza cíclica (como los días de la semana o los meses del año) a menudo se benefician más de la codificación cíclica que de las técnicas de escalamiento estándar.

Datos que generalmente necesitan escalamiento:

  1. Características numéricas continuas con amplios rangos:Las características que pueden adoptar una amplia gama de valores a menudo se benefician del escalamiento para evitar que dominen otras características en el modelo.
  2. Características medidas en diferentes unidades:Cuando su conjunto de datos incluye características medidas en diferentes unidades (por ejemplo, metros, kilogramos, años), el escalado ayuda a colocarlas en una escala comparable.
  3. Características con magnitudes significativamente diferentes:Si algunas características tienen valores en miles mientras que otras están entre 0 y 1, el escalamiento puede ayudar a equilibrar su influencia en el modelo.
  4. Características de porcentaje o proporción:Si bien estos ya tienen una escala fija (normalmente de 0 a 100 o de 0 a 1), la escala aún puede ser beneficiosa, especialmente cuando se usa junto con funciones con rangos mucho más amplios.
  5. Características continuas acotadas:Las características con un mínimo y un máximo conocidos a menudo se benefician del escalamiento, especialmente si su rango es significativamente diferente de otras características en el conjunto de datos.
  6. Distribuciones sesgadas:Las características con distribuciones muy sesgadas a menudo se benefician de ciertos tipos de escalamiento o transformación para hacerlas más normalmente distribuidas y mejorar el rendimiento del modelo.

Ahora bien, puede que te preguntes: “¿Por qué molestarnos en escalar? ¿No podemos simplemente dejar que los datos sean como son?”. Bueno, en realidad, muchos algoritmos de aprendizaje automático funcionan mejor cuando todas las características están en una escala similar. A continuación, te explicamos por qué es necesario escalar:

  1. Igual importancia de las características:Las características sin escala pueden dominar accidentalmente el modelo. Por ejemplo, la velocidad del viento (0–50 km/h) puede eclipsar la temperatura (10–35 °C) simplemente por su mayor escala, no porque sea más importante.
  2. Convergencia más rápida:Muchos algoritmos de optimización utilizados en el aprendizaje automático convergen más rápido cuando las características están en una escala similar.
  3. Rendimiento mejorado del algoritmo:Algunos algoritmos, como K-Nearest Neighbors y Neural Networks, requieren explícitamente datos escalados para funcionar bien.
  4. Interpretabilidad:Los coeficientes escalados en modelos lineales son más fáciles de interpretar y comparar.
  5. Cómo evitar la inestabilidad numérica:Valores muy grandes o muy pequeños pueden provocar inestabilidad numérica en algunos algoritmos.

Ahora que comprendemos qué datos numéricos necesitan escalamiento y por qué, echemos un vistazo a nuestro conjunto de datos y veamos cómo podemos escalar sus variables numéricas utilizando cinco métodos de escalamiento diferentes. No se trata solo de escalar, sino de hacerlo correctamente.

Antes de adentrarnos en las técnicas de escalado, veamos nuestro conjunto de datos. Trabajaremos con datos de este club de golf ficticio.

import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler, StandardScaler, RobustScaler
from scipy import stats

# Read the data
data = {
'Temperature_Celsius': [15, 18, 22, 25, 28, 30, 32, 29, 26, 23, 20, 17],
'Humidity_Percent': [50, 55, 60, 65, 70, 75, 80, 72, 68, 62, 58, 52],
'Wind_Speed_kmh': [5, 8, 12, 15, 10, 7, 20, 18, 14, 9, 6, 11],
'Golfers_Count': [20, 35, 50, 75, 100, 120, 90, 110, 85, 60, 40, 25],
'Green_Speed': [8.5, 9.0, 9.5, 10.0, 10.5, 11.0, 11.5, 11.0, 10.5, 10.0, 9.5, 9.0]
}

df = pd.DataFrame(data)

Este conjunto de datos es perfecto para nuestras tareas de escalamiento porque contiene características con diferentes unidades, escalas y distribuciones.

Ahora veamos todos los métodos de escalamiento.

El escalado mínimo-máximo transforma todos los valores a un rango fijo, generalmente entre 0 y 1, restando el valor mínimo y dividiéndolo por el rango.

📊 Tipos de datos comunes: Características con un amplio rango de valores, donde se desea un rango específico.

🎯Objetivos:
–
Restringir las características a un rango específico (por ejemplo, 0 a 1).
– Conservar las relaciones originales entre los puntos de datos.
– Garantizar la interpretabilidad de los valores escalados.

En nuestro caso:Aplicamos esto a la temperatura porque la temperatura tiene un mínimo y un máximo naturales en nuestro contexto de golf. Conserva las diferencias relativas entre temperaturas, lo que hace que 0 sea el día más frío, 1 el más caluroso y 0,5 un día con temperatura promedio.

# 1. Min-Max Scaling for Temperature_Celsius
min_max_scaler = MinMaxScaler()
df['Temperature_MinMax'] = min_max_scaler.fit_transform(df[['Temperature_Celsius']])

El escalamiento estándar centra los datos alrededor de una media de 0 y los escala a una desviación estándar de 1, que se logra restando la media y dividiendo por la desviación estándar.

📊 Tipos de datos comunes: Características con diferentes escalas y distribuciones.

🎯Objetivos:
–
Estandarizar las características para tener una media de 0 y una desviación estándar de 1.
– Asegúrese de que las características con diferentes escalas contribuyan por igual a un modelo.
– Preparar datos para algoritmos sensibles a escalas de características (por ejemplo, SVM, KNN).

En nuestro caso:Utilizamos esto para la velocidad del viento porque la velocidad del viento suele seguir una distribución aproximadamente normal. Nos permite identificar fácilmente los días excepcionalmente tranquilos o ventosos por la cantidad de desviaciones estándar que se encuentran con respecto a la media.

# 2. Standard Scaling for Wind_Speed_kmh
std_scaler = StandardScaler()
df['Wind_Speed_Standardized'] = std_scaler.fit_transform(df[['Wind_Speed_kmh']])

El escalamiento robusto centra los datos alrededor de la mediana y escala utilizando el rango intercuartil (RIC)

📊 Tipos de datos comunes: Características con valores atípicos o datos ruidosos.

🎯Objetivos:
–
Manejar los valores atípicos de manera efectiva sin dejarse influenciar demasiado por ellos.
– Mantener el orden relativo de los puntos de datos.
– Lograr un escalamiento estable en presencia de datos ruidosos.

En nuestro caso:Aplicamos esto a la humedad porque las lecturas de humedad pueden tener valores atípicos debido a condiciones climáticas extremas o errores de medición. Esta escala garantiza que nuestras mediciones sean menos sensibles a estos valores atípicos.

# 3. Robust Scaling for Humidity_Percent
robust_scaler = RobustScaler()
df['Humidity_Robust'] = robust_scaler.fit_transform(df[['Humidity_Percent']])

Hasta ahora, hemos visto algunas formas de escalar datos mediante transformaciones. Ahora, exploremos un enfoque diferente: el uso de transformaciones para lograr el escalamiento, comenzando con la técnica común de transformación logarítmica.

Aplica una función logarítmica a los datos, comprimiendo la escala de valores muy grandes.

📊 Tipos de datos comunes:
– Datos sesgados a la derecha (cola larga).
– Contar datos.
– Datos con relaciones multiplicativas.

🎯Objetivos:
–
Abordar la asimetría hacia la derecha y normalizar la distribución.
– Estabilizar la varianza en todo el rango de la función.
– Mejorar el rendimiento del modelo para datos con estas características.

En nuestro caso:Utilizamos esto para el recuento de golfistas porque los datos de recuento suelen seguir una distribución sesgada hacia la derecha. Hace que la diferencia entre 10 y 20 golfistas sea más significativa que entre 100 y 110, lo que coincide con el impacto de estas diferencias en el mundo real.

# 4. Log Transformation for Golfers_Count
df['Golfers_Log'] = np.log1p(df['Golfers_Count'])

Esta es una familia de transformaciones de potencia (que incluye la transformación logarítmica como un caso especial) que tiene como objetivo normalizar la distribución de datos mediante la aplicación de una transformación de potencia con un parámetro lambda (λ), que está optimizado para lograr la normalidad deseada.

Tipos de datos comunes: Características que necesitan normalización para aproximarse a una distribución normal.

🎯Objetivos:
–
Normalizar la distribución de una característica.
– Mejorar el rendimiento de los modelos que asumen datos distribuidos normalmente.
– Estabilizar la varianza y mejorar potencialmente la linealidad.

En nuestro caso:Aplicamos esto a Green Speed ​​porque podría tener una distribución compleja que no se normaliza fácilmente con métodos más simples. Permite que los datos nos guíen hacia la transformación más adecuada, mejorando potencialmente sus relaciones con otras variables.

# 5. Box-Cox Transformation for Green_Speed
df['Green_Speed_BoxCox'], lambda_param = stats.boxcox(df['Green_Speed'])

Después de realizar la transformación, también es habitual escalarla aún más para que siga una determinada distribución (como la normal). Podemos hacer esto con las dos columnas transformadas que teníamos.


df['Golfers_Count_Log'] = np.log1p(df['Golfers_Count'])
df['Golfers_Count_Log_std'] = standard_scaler.fit_transform(df[['Golfers_Count_Log']])

box_cox_transformer = PowerTransformer(method='box-cox') # By default already has standardizing
df['Green_Speed_BoxCox'] = box_cox_transformer.fit_transform(df[['Green_Speed']])print("\nBox-Cox lambda parameter:", lambda_param)
print("\nBox-Cox lambda parameter:", lambda_param)

Así que, ahí lo tienes. Cinco técnicas de escalado diferentes, todas aplicadas a nuestro conjunto de datos de campos de golf. Ahora, todas las características numéricas están transformadas y listas para los modelos de aprendizaje automático.

A continuación se ofrece un resumen rápido de cada método y su aplicación:

  • Escala mín.-máx.:Se aplica a la temperatura, normalizando los valores a un rango de 0 a 1 para una mejor interpretabilidad del modelo.
  • Escala estándar:Se utiliza para la velocidad del viento, estandarizando la distribución para reducir el impacto de valores extremos.
  • Escalabilidad robusta:Se aplica a la humedad para manejar posibles valores atípicos y reducir su efecto en el rendimiento del modelo.
  • Transformación de registros:Se utiliza para el conteo de golfistas para normalizar los datos de conteo sesgados a la derecha y mejorar la estabilidad del modelo.
  • Transformación de Box-Cox:Se aplica a Green Speed ​​para hacer que la distribución sea más normal, lo que a menudo requieren los algoritmos de aprendizaje automático.

Cada método de escalamiento cumple un propósito específico y se elige en función de la naturaleza de los datos y los requisitos del algoritmo de aprendizaje automático. Al aplicar estas técnicas, hemos preparado nuestras características numéricas para su uso en varios modelos de aprendizaje automático, lo que potencialmente mejora su rendimiento y confiabilidad.

import pandas as pd
import numpy as np
from sklearn.preprocessing import MinMaxScaler, StandardScaler, RobustScaler, PowerTransformer

# Read the data
data = {
'Temperature_Celsius': [15, 18, 22, 25, 28, 30, 32, 29, 26, 23, 20, 17],
'Humidity_Percent': [50, 55, 60, 65, 70, 75, 80, 72, 68, 62, 58, 52],
'Wind_Speed_kmh': [5, 8, 12, 15, 10, 7, 20, 18, 14, 9, 6, 11],
'Golfers_Count': [20, 35, 50, 75, 100, 120, 90, 110, 85, 60, 40, 25],
'Green_Speed': [8.5, 9.0, 9.5, 10.0, 10.5, 11.0, 11.5, 11.0, 10.5, 10.0, 9.5, 9.0]
}

df = pd.DataFrame(data)

# 1. Min-Max Scaling for Temperature_Celsius
min_max_scaler = MinMaxScaler()
df['Temperature_MinMax'] = min_max_scaler.fit_transform(df[['Temperature_Celsius']])

# 2. Standard Scaling for Wind_Speed_kmh
std_scaler = StandardScaler()
df['Wind_Speed_Standardized'] = std_scaler.fit_transform(df[['Wind_Speed_kmh']])

# 3. Robust Scaling for Humidity_Percent
robust_scaler = RobustScaler()
df['Humidity_Robust'] = robust_scaler.fit_transform(df[['Humidity_Percent']])

# 4. Log Transformation for Golfers_Count
df['Golfers_Log'] = np.log1p(df['Golfers_Count'])
df['Golfers_Log_std'] = standard_scaler.fit_transform(df[['Golfers_Log']])

# 5. Box-Cox Transformation for Green_Speed
box_cox_transformer = PowerTransformer(method='box-cox') # By default already has standardizing
df['Green_Speed_BoxCox'] = box_cox_transformer.fit_transform(df[['Green_Speed']])

# Display the results
transformed_data = df[[
'Temperature_MinMax',
'Humidity_Robust',
'Wind_Speed_Standardized',
'Green_Speed_BoxCox',
'Golfers_Log_std',
]]

transformed_data = transformed_data.round(2)
print(transformed_data)