Introducción
Esta práctica demuestra cómo utilizar diferentes técnicas de escalado y transformación en un conjunto de datos con valores atípicos utilizando la librería scikit-learn de Python.
Consejos sobre la VM
Una vez finalizada la inicialización de la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno y acceder a Jupyter Notebook para practicar.
En ocasiones, es posible que tenga que esperar unos segundos a que Jupyter Notebook termine de cargar. La validación de las operaciones no se puede automatizar debido a las limitaciones de Jupyter Notebook.
Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje su retroalimentación después de la sesión y resolveremos rápidamente el problema para usted.
Importar bibliotecas y conjunto de datos
En primer lugar, necesitamos importar las bibliotecas necesarias y cargar el conjunto de datos de viviendas de California de scikit-learn.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler, StandardScaler, RobustScaler, Normalizer, QuantileTransformer, PowerTransformer
from sklearn.datasets import fetch_california_housing
## Cargar el conjunto de datos de viviendas de California
dataset = fetch_california_housing()
X_full, y_full = dataset.data, dataset.target
feature_names = dataset.feature_names
Seleccionar características y definir el mapeo de características
A continuación, seleccionamos dos características del conjunto de datos para facilitar la visualización y definimos un mapeo de los nombres de las características para una mejor visualización.
## Seleccionar dos características
features = ["MedInc", "AveOccup"]
features_idx = [feature_names.index(feature) for feature in features]
X = X_full[:, features_idx]
## Definir el mapeo de características
feature_mapping = {
"MedInc": "Median income in block",
"AveOccup": "Average house occupancy",
}
Definir distribuciones
Definimos una lista de diferentes escaladores, transformadores y normalizadores para llevar los datos a un rango predefinido y los almacenamos en una lista llamada distribuciones.
## Definir distribuciones
distributions = [
("Unscaled data", X),
("Data after standard scaling", StandardScaler().fit_transform(X)),
("Data after min-max scaling", MinMaxScaler().fit_transform(X)),
("Data after robust scaling", RobustScaler(quantile_range=(25, 75)).fit_transform(X)),
("Data after sample-wise L2 normalizing", Normalizer().fit_transform(X)),
("Data after quantile transformation (uniform pdf)", QuantileTransformer(output_distribution="uniform").fit_transform(X)),
("Data after quantile transformation (gaussian pdf)", QuantileTransformer(output_distribution="normal").fit_transform(X)),
("Data after power transformation (Yeo-Johnson)", PowerTransformer(method="yeo-johnson").fit_transform(X)),
("Data after power transformation (Box-Cox)", PowerTransformer(method="box-cox").fit_transform(X)),
]
Graficar distribuciones
Finalmente, creamos una función para graficar cada distribución y llamamos a la función para cada distribución en la lista. La función mostrará dos gráficos para cada escalador/normalizador/transformador. El gráfico de la izquierda muestra un diagrama de dispersión del conjunto de datos completo, y el gráfico de la derecha excluye los valores extremos, considerando solo el 99% del conjunto de datos, excluyendo los valores atípicos marginales. Además, se mostrarán las distribuciones marginales para cada característica a los lados del diagrama de dispersión.
## Graficar distribuciones
def plot_distribution(axes, X, y, hist_nbins=50, title="", x0_label="", x1_label=""):
ax, hist_X1, hist_X0 = axes
ax.set_title(title)
ax.set_xlabel(x0_label)
ax.set_ylabel(x1_label)
## El diagrama de dispersión
colors = cm.plasma_r(y)
ax.scatter(X[:, 0], X[:, 1], alpha=0.5, marker="o", s=5, lw=0, c=colors)
## Quitando la espina superior y la derecha para mejorar la estética
## hacer un buen diseño de ejes
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
ax.get_xaxis().tick_bottom()
ax.get_yaxis().tick_left()
ax.spines["left"].set_position(("outward", 10))
ax.spines["bottom"].set_position(("outward", 10))
## Histograma para el eje X1 (característica 5)
hist_X1.set_ylim(ax.get_ylim())
hist_X1.hist(
X[:, 1], bins=hist_nbins, orientation="horizontal", color="grey", ec="grey"
)
hist_X1.axis("off")
## Histograma para el eje X0 (característica 0)
hist_X0.set_xlim(ax.get_xlim())
hist_X0.hist(
X[:, 0], bins=hist_nbins, orientation="vertical", color="grey", ec="grey"
)
hist_X0.axis("off")
## Escalar la salida entre 0 y 1 para la barra de colores
y = minmax_scale(y_full)
## plasma no existe en matplotlib < 1.5
cmap = getattr(cm, "plasma_r", cm.hot_r)
def create_axes(title, figsize=(16, 6)):
fig = plt.figure(figsize=figsize)
fig.suptitle(title)
## Definir el eje para el primer gráfico
left, width = 0.1, 0.22
bottom, height = 0.1, 0.7
bottom_h = height + 0.15
left_h = left + width + 0.02
rect_scatter = [left, bottom, width, height]
rect_histx = [left, bottom_h, width, 0.1]
rect_histy = [left_h, bottom, 0.05, height]
ax_scatter = plt.axes(rect_scatter)
ax_histx = plt.axes(rect_histx)
ax_histy = plt.axes(rect_histy)
## Definir el eje para el gráfico amplificado
left = width + left + 0.2
left_h = left + width + 0.02
rect_scatter = [left, bottom, width, height]
rect_histx = [left, bottom_h, width, 0.1]
rect_histy = [left_h, bottom, 0.05, height]
ax_scatter_zoom = plt.axes(rect_scatter)
ax_histx_zoom = plt.axes(rect_histx)
ax_histy_zoom = plt.axes(rect_histy)
## Definir el eje para la barra de colores
left, width = width + left + 0.13, 0.01
rect_colorbar = [left, bottom, width, height]
ax_colorbar = plt.axes(rect_colorbar)
return (
(ax_scatter, ax_histy, ax_histx),
(ax_scatter_zoom, ax_histy_zoom, ax_histx_zoom),
ax_colorbar,
)
def make_plot(item_idx):
title, X = distributions[item_idx]
ax_zoom_out, ax_zoom_in, ax_colorbar = create_axes(title)
axarr = (ax_zoom_out, ax_zoom_in)
plot_distribution(
axarr[0],
X,
y,
hist_nbins=200,
x0_label=feature_mapping[features[0]],
x1_label=feature_mapping[features[1]],
title="Full data",
)
## Zoom-in
zoom_in_percentile_range = (0, 99)
cutoffs_X0 = np.percentile(X[:, 0], zoom_in_percentile_range)
cutoffs_X1 = np.percentile(X[:, 1], zoom_in_percentile_range)
non_outliers_mask = np.all(X > [cutoffs_X0[0], cutoffs_X1[0]], axis=1) & np.all(
X < [cutoffs_X0[1], cutoffs_X1[1]], axis=1
)
plot_distribution(
axarr[1],
X[non_outliers_mask],
y[non_outliers_mask],
hist_nbins=50,
x0_label=feature_mapping[features[0]],
x1_label=feature_mapping[features[1]],
title="Zoom-in",
)
norm = mpl.colors.Normalize(y_full.min(), y_full.max())
mpl.colorbar.ColorbarBase(
ax_colorbar,
cmap=cmap,
norm=norm,
orientation="vertical",
label="Color mapping for values of y",
)
## Graficar todas las distribuciones
for i in range(len(distributions)):
make_plot(i)
plt.show()
Resumen
Esta práctica demostró cómo utilizar diferentes técnicas de escalado y transformación en un conjunto de datos con valores atípicos utilizando la biblioteca scikit-learn de Python. Aprendimos cómo seleccionar características, definir el mapeo de características y graficar distribuciones. También exploramos los efectos de diferentes técnicas de escalado y transformación y cómo pueden afectar los datos.