En este tutorial vamos a ver las mejores técnicas de normalización de variables numéricas para Machine Learning y las vamos a implementar en Python.
En ocasiones puede ser conveniente transformar las variables numéricas de manera que logremos cambiar la distribución de los datos para que se corresponda con una distribución normal o gaussiana.
Normalizar en este ámbito viene de distribución normal (o gaussiana).
Una distribución normal es una forma específica de distribuir los datos, caracterizada por la famosa "curva de campana". En una distribución normal:
Es conveniente normalizar las variables numéricas cuando vamos a utilizar modelos de Machine Learning que asumen que los datos de entrada siguen una distribución normal.
Este es el caso de la regresión logística y de la regresión lineal.
En ocasiones al transformar la distribución de las características numéricas y convertirlas en gaussianas conseguimos incluso descubrir relaciones lineales entre las características y la variable objetivo, lo que puede mejorar el rendimiento de los modelos de Machine Learning que se basan en este tipo de relaciones entre los datos (como la regresión lineal y logística, que te comentaba antes 🙂).
Otro tipo de transformación habitual de variables numéricas es el escalado.
El escalado de variables se refiere al proceso de ajustar el rango de los datos numéricos para que se ajusten a una escala común.
En ocasiones se utiliza indistintamente el término "normalización" de variables numéricas para hacer referencia al escalado de variables y a la transformación de la distribución.
En este tutorial vamos a utilizar únicamente técnicas de transformación de la distribución pero puedes ver técnicas de escalado de variables numéricas y cuándo aplicarlas en este otro tutorial.
Para implementar en Python las transformaciones sobre las variables numéricas y cambiar su distribución vamos a utilizar el dataset Breast cancer Wisconsin (diagnosis) que está incluido en Scikit-learn.
El dataset se compone de características extraídas de imágenes digitalizadas de biopsias de mama.
Hay un total de 30 características, que se pueden agrupar en diez categorías principales, cada una con tres estadísticas: el promedio, el error estándar, y el "peor" o mayor (la media de las tres medidas más grandes) de estas características.
Te cuento un poco más sobre las categorías de características principales:
Además, cada muestra en el dataset tiene una etiqueta que indica si el tumor es maligno (M
) o benigno (B
).
Vamos a importar las librerías que vamos a usar y a cargar el dataset 🙂.
import numpy as np import pandas as pd import matplotlib.pyplot as plt import scipy.stats as stats from sklearn.datasets import load_breast_cancer from sklearn.preprocessing import FunctionTransformer cancer_data = load_breast_cancer() data = pd.DataFrame(cancer_data.data,columns=cancer_data.feature_names)
Ahora vamos a representar el histograma de las características que representan el error estándar, que son las que vamos a transformar.
data.iloc[:,10:20].hist(bins=30, figsize=(15, 10)) plt.tight_layout() plt.show()
Aquí te muestro el histograma de las 6 características que vamos a poner de ejemplo en este tutorial.
Antes de proseguir, decirte que puedes aplicar las siguientes técnicas sobre todas las variables numéricas pero tienes que cerciorarte de que no toman valores nulos en las transformaciones que no lo soportan.
# Hacemos una copia del DataFrame data_transformada = data.iloc[:,10:20].copy() # Comprobamos si las características que hemos seleccionado (las correspondientes al error) toman valores nulos if (data_transformada == 0).any().any(): print("Hay valores cero en el dataset.") else: print("No hay valores cero en el dataset.") # Reemplazamos los ceros por un valor pequeño data_transformada.replace(0, 1e-6, inplace=True)
Sobre los valores faltantes, ya te aviso yo de que este dataset no tiene 🙂.
La transformación logarítmica es muy útil cuando queremos transformar la distribución de una característica numérica.
Especialmente es conveniente aplicar una transformación logarítmica en estos si la característica numérica que quieres transformar cumple lo siguiente:
Vamos a transformar con Scikit-learn únicamente las 6 primeras características.
La transformación recíproca es otra técnica de preprocesamiento de características numéricas que puede ser útil en análisis de datos y machine learning, especialmente cuando trabajamos con variables que no se distribuyen de manera normal.
Esta transformación implica calcular el recíproco de cada valor de la variable, es decir, 1/x para cada valor x en el conjunto de datos.
Aquí hay algunas situaciones donde aplicar una transformación recíproca puede ser conveniente:
La transformación de variables numéricas mediante potenciación consiste simplemente en elevar los valores de la característica que queremos transformar a una potencia determinada.
Cuando los datos tienen un sesgo significativo (ya sea positivo o negativo), elevarlos a una potencia puede ayudar a corregir este sesgo y acercar la distribución a una normal.
Por ejemplo:
La transformación Box-Cox es un método estadístico parecido a la potenciación que se utiliza para hacer que los datos sean más similares a una distribución normal (que es lo que hemos venido a hacer hoy 😉).
Es especialmente útil cuando tratamos con datos que no cumplen los supuestos de normalidad requeridos para muchos análisis de datos o si queremos aplicar modelos de regresión.
⚠️ Un detalle importante es que la transformación Box-Cox solo se puede aplicar directamente a datos positivos. Si los datos incluyen ceros o valores negativos, se deben ajustar sumando una constante antes de aplicar la transformación.
PowerTransformer() permite aplicar transformaciones a los datos para hacer que su distribución se parezca más a la distribución normal. Este transformador es capaz de aplicar dos tipos de transformaciones: Box-Cox y Yeo-Johnson.
Al crear el transformador PowerTransformer
, debes especificar qué método de transformación deseas usar. En este caso: Box-Cox.
PowerTransformer
tiene un argumento llamado standardize
. Si lo estableces en True
, el transformador escalará los valores transformados para que tengan media 0 y varianza 1.
Antes de transformar los datos, necesitas "ajustar" el transformador a los datos que quieres transformar. Esto implica que PowerTransformer
analizará los datos proporcionados y aprenderá los valores óptimos de lambda (λ) para cada variable. Esto se hace llamando al método fit()
en la porción del DataFrame que contiene las variables que deseas transformar.
Una vez que el transformador está ajustado, almacena los valores de λ aprendidos en su atributo lambdas_
, que puedes revisar para entender cómo se transformó cada variable.
Finalmente, usas el método transform()
sobre la porción del DataFrame que quieres transformar. Esto aplicará la transformación Box-Cox (con los λ aprendidos durante el ajuste) a los datos y devolverá los valores transformados en un array de Numpy que luego volvemos a convertir en dataframe de Pandas.
Ten en cuenta que para hacer predicciones con modelos que incluyen características numéricas transformadas, generalmente necesitamos revertir la transformación (por ejemplo, exponenciando si hemos aplicado un logaritmo).
Es importante que tengas esto en cuenta para que las predicciones sean interpretables y comparables con los valores observados.