简介
本实验展示了如何使用 Python 的 scikit-learn 库,对包含异常值的数据集使用不同的缩放和转换技术。
虚拟机使用提示
虚拟机启动完成后,点击左上角切换到“笔记本”标签,以访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。
如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们会及时为你解决问题。
本实验展示了如何使用 Python 的 scikit-learn 库,对包含异常值的数据集使用不同的缩放和转换技术。
虚拟机启动完成后,点击左上角切换到“笔记本”标签,以访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。
如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们会及时为你解决问题。
首先,我们需要导入必要的库,并从 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
## 加载加利福尼亚住房数据集
dataset = fetch_california_housing()
X_full, y_full = dataset.data, dataset.target
feature_names = dataset.feature_names
接下来,我们从数据集中选择两个特征,以便于可视化,并定义特征名称的映射,以实现更好的可视化效果。
## 选择两个特征
features = ["MedInc", "AveOccup"]
features_idx = [feature_names.index(feature) for feature in features]
X = X_full[:, features_idx]
## 定义特征映射
feature_mapping = {
"MedInc": "街区中位数收入",
"AveOccup": "房屋平均入住率",
}
我们定义了一个包含不同缩放器、转换器和归一化器的列表,以便将数据缩放到预定义范围内,并将它们存储在一个名为 distributions 的列表中。
## 定义分布
distributions = [
("未缩放的数据", X),
("标准缩放后的数据", StandardScaler().fit_transform(X)),
("最小 - 最大缩放后的数据", MinMaxScaler().fit_transform(X)),
("稳健缩放后的数据", RobustScaler(quantile_range=(25, 75)).fit_transform(X)),
("样本-wise L2 归一化后的数据", Normalizer().fit_transform(X)),
("分位数变换后的数据(均匀概率密度函数)", QuantileTransformer(output_distribution="uniform").fit_transform(X)),
("分位数变换后的数据(高斯概率密度函数)", QuantileTransformer(output_distribution="normal").fit_transform(X)),
("幂变换后的数据(Yeo-Johnson 方法)", PowerTransformer(method="yeo-johnson").fit_transform(X)),
("幂变换后的数据(Box-Cox 方法)", PowerTransformer(method="box-cox").fit_transform(X)),
]
最后,我们创建一个函数来绘制每个分布,并对列表中的每个分布调用该函数。该函数将为每个缩放器/归一化器/转换器显示两个图。左边的图展示完整数据集的散点图,右边的图排除极端值,仅考虑数据集中的 99%,不包括边缘异常值。此外,每个特征的边缘分布将显示在散点图的两侧。
## 绘制分布
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)
## 散点图
colors = cm.plasma_r(y)
ax.scatter(X[:, 0], X[:, 1], alpha=0.5, marker="o", s=5, lw=0, c=colors)
## 移除顶部和右侧的边框以美化
## 制作美观的轴布局
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))
## 轴 X1(特征 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")
## 轴 X0(特征 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")
## 将输出缩放到 0 到 1 之间以用于颜色条
y = minmax_scale(y_full)
## matplotlib < 1.5 中不存在 plasma
cmap = getattr(cm, "plasma_r", cm.hot_r)
def create_axes(title, figsize=(16, 6)):
fig = plt.figure(figsize=figsize)
fig.suptitle(title)
## 定义第一个图的轴
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)
## 定义放大图的轴
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)
## 定义颜色条的轴
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="完整数据",
)
## 放大
放大的百分位数范围 = (0, 99)
cutoffs_X0 = np.percentile(X[:, 0], 放大的百分位数范围)
cutoffs_X1 = np.percentile(X[:, 1], 放大的百分位数范围)
非异常值掩码 = 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[非异常值掩码],
y[非异常值掩码],
hist_nbins=50,
x0_label=feature_mapping[features[0]],
x1_label=feature_mapping[features[1]],
title="放大",
)
norm = mpl.colors.Normalize(y_full.min(), y_full.max())
mpl.colorbar.ColorbarBase(
ax_colorbar,
cmap=cmap,
norm=norm,
orientation="vertical",
label="y 值的颜色映射",
)
## 绘制所有分布
for i in range(len(distributions)):
make_plot(i)
plt.show()
本实验展示了如何使用 Python 的 scikit-learn 库,对包含异常值的数据集应用不同的缩放和转换技术。我们学习了如何选择特征、定义特征映射以及绘制分布。我们还探讨了不同缩放和转换技术的效果,以及它们如何影响数据。