简介
在本实验中,我们将学习如何使用 Scikit-learn 库中的 TargetEncoder 类。目标编码是一种用于将分类数据转换为数值数据的技术,这些数值数据可用作机器学习算法的输入。TargetEncoder 会用该类别目标变量的均值替换分类特征的每个类别。在分类特征与目标之间存在强关系的情况下,此方法很有用。
虚拟机使用提示
虚拟机启动完成后,点击左上角切换到 笔记本 标签页,以访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。
如果你在学习过程中遇到问题,随时向 Labby 提问。课程结束后提供反馈,我们会立即为你解决问题。
安装所需库
首先,我们需要安装所需的库。我们将使用 Scikit-learn、Pandas 和 Matplotlib 库。运行以下命令来安装这些库:
!pip install scikit-learn pandas matplotlib
导入所需库
接下来,我们需要导入所需的库。运行以下代码来导入所需的库:
import numpy as np
import pandas as pd
from sklearn.preprocessing import KBinsDiscretizer, TargetEncoder
from sklearn.linear_model import Ridge
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
创建合成数据集
在本实验中,我们将创建一个包含三个分类特征的合成数据集:一个具有中等基数的信息性特征、一个具有中等基数的非信息性特征和一个具有高基数的非信息性特征。我们将使用 Scikit-learn 中的 KBinsDiscretizer 类来生成信息性特征。运行以下代码来创建合成数据集:
n_samples = 50_000
rng = np.random.RandomState(42)
y = rng.randn(n_samples)
noise = 0.5 * rng.randn(n_samples)
n_categories = 100
kbins = KBinsDiscretizer(
n_bins=n_categories, encode="ordinal", strategy="uniform", random_state=rng
)
X_informative = kbins.fit_transform((y + noise).reshape(-1, 1))
permuted_categories = rng.permutation(n_categories)
X_informative = permuted_categories[X_informative.astype(np.int32)]
X_shuffled = rng.permutation(X_informative)
X_near_unique_categories = rng.choice(
int(0.9 * n_samples), size=n_samples, replace=True
).reshape(-1, 1)
X = pd.DataFrame(
np.concatenate(
[X_informative, X_shuffled, X_near_unique_categories],
axis=1,
),
columns=["informative", "shuffled", "near_unique"],
)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
在原始数据上训练岭回归模型
在本节中,我们将在编码和未编码的数据集上训练岭回归模型,并探讨目标编码器在有无区间交叉验证情况下的影响。首先,我们将在原始特征上训练岭回归模型。运行以下代码来训练岭回归模型:
ridge = Ridge(alpha=1e-6, solver="lsqr", fit_intercept=False)
raw_model = ridge.fit(X_train, y_train)
print("Raw Model score on training set: ", raw_model.score(X_train, y_train))
print("Raw Model score on test set: ", raw_model.score(X_test, y_test))
使用交叉验证训练岭回归模型
接下来,我们将创建一个包含 TargetEncoder 和岭回归模型的管道。该管道使用 TargetEncoder.fit_transform,它会使用交叉验证。运行以下代码以使用交叉验证训练岭回归模型:
model_with_cv = make_pipeline(TargetEncoder(random_state=0), ridge)
model_with_cv.fit(X_train, y_train)
print("Model with CV on training set: ", model_with_cv.score(X_train, y_train))
print("Model with CV on test set: ", model_with_cv.score(X_test, y_test))
使用交叉验证评估线性模型的系数
线性模型的系数表明,大部分权重都在列索引为 0 的特征上,即信息性特征。运行以下代码以使用交叉验证评估线性模型的系数:
coefs_cv = pd.Series(
model_with_cv[-1].coef_, index=model_with_cv[-1].feature_names_in_
).sort_values()
_ = coefs_cv.plot(kind="barh")
不使用交叉验证训练岭回归模型
虽然 TargetEncoder.fit_transform 使用区间交叉验证,但 TargetEncoder.transform 本身并不执行任何交叉验证。它使用完整训练集的聚合来转换分类特征。因此,我们可以使用 TargetEncoder.fit 后跟 TargetEncoder.transform 来禁用交叉验证。然后将这种编码传递给岭回归模型。运行以下代码以不使用交叉验证训练岭回归模型:
target_encoder = TargetEncoder(random_state=0)
target_encoder.fit(X_train, y_train)
X_train_no_cv_encoding = target_encoder.transform(X_train)
X_test_no_cv_encoding = target_encoder.transform(X_test)
model_no_cv = ridge.fit(X_train_no_cv_encoding, y_train)
print(
"Model without CV on training set: ",
model_no_cv.score(X_train_no_cv_encoding, y_train),
)
print(
"Model without CV on test set: ", model_no_cv.score(X_test_no_cv_encoding, y_test)
)
评估无交叉验证的线性模型系数
岭回归模型出现了过拟合,因为相对于信息性特征,它给极高基数特征赋予了更多权重。运行以下代码来评估无交叉验证的线性模型系数:
coefs_no_cv = pd.Series(
model_no_cv.coef_, index=model_no_cv.feature_names_in_
).sort_values()
_ = coefs_no_cv.plot(kind="barh")
总结
在本实验中,我们学习了如何使用 Scikit-learn 中的 TargetEncoder 类将分类数据转换为数值数据,这些数值数据可用作机器学习算法的输入。我们还了解了区间交叉验证在防止过拟合方面的重要性。我们在原始数据上训练了一个岭回归模型并评估了其性能。我们还使用交叉验证训练了一个岭回归模型,并评估了线性模型的系数。最后,我们在不使用交叉验证的情况下训练了一个岭回归模型,并评估了线性模型的系数。