使用 Scikit-learn 进行多项式核近似

Beginner

This tutorial is from open-source community. Access the source code

简介

本实验将演示如何在 scikit-learn 中使用多项式核近似来高效地生成多项式核特征空间近似。这用于训练线性分类器,使其近似核化分类器的准确率。我们将使用 Covtype 数据集,该数据集包含 581,012 个样本,每个样本有 54 个特征,分布在 6 个类别中。该数据集的目标是仅根据地图变量预测森林覆盖类型(无遥感数据)。加载后,我们将其转换为二分类问题,以匹配 LIBSVM 网页上的数据集版本,该版本是原始论文中使用的版本。

虚拟机提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签页,以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,请随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。

加载并准备数据

我们首先加载 Covtype 数据集,并通过仅选择一个类别将其转换为二分类问题。然后,我们将数据划分为训练集和测试集,并对特征进行归一化处理。

from sklearn.datasets import fetch_covtype
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler, Normalizer

## 加载 Covtype 数据集,仅选择一个类别
X, y = fetch_covtype(return_X_y=True)
y[y!= 2] = 0
y[y == 2] = 1

## 将数据划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, train_size=5000, test_size=10000, random_state=42
)

## 对特征进行归一化处理
mm = make_pipeline(MinMaxScaler(), Normalizer())
X_train = mm.fit_transform(X_train)
X_test = mm.transform(X_test)

建立基线模型

我们将在原始特征上训练一个线性支持向量机(SVM)来建立一个基线模型,并打印其准确率。

from sklearn.svm import LinearSVC

## 在原始特征上训练一个线性 SVM
lsvm = LinearSVC(dual="auto")
lsvm.fit(X_train, y_train)
lsvm_score = 100 * lsvm.score(X_test, y_test)

## 打印基线模型的准确率
print(f"Linear SVM score on raw features: {lsvm_score:.2f}%")

建立核近似模型

现在,我们将在由 PolynomialCountSketch 生成的具有不同 n_components 值的特征上训练线性支持向量机(SVM)。我们将使用一个循环来遍历不同的 n_components 值,并打印每个模型的准确率。

from sklearn.kernel_approximation import PolynomialCountSketch

n_runs = 1
N_COMPONENTS = [250, 500, 1000, 2000]

for n_components in N_COMPONENTS:
    ps_lsvm_score = 0
    for _ in range(n_runs):
        ## 在由 PolynomialCountSketch 生成的特征上训练一个线性 SVM
        pipeline = make_pipeline(
            PolynomialCountSketch(n_components=n_components, degree=4),
            LinearSVC(dual="auto"),
        )
        pipeline.fit(X_train, y_train)
        ps_lsvm_score += 100 * pipeline.score(X_test, y_test)

    ps_lsvm_score /= n_runs

    ## 打印模型的准确率
    print(f"Linear SVM score on {n_components} PolynomialCountSketch features: {ps_lsvm_score:.2f}%")

建立核支持向量机模型

我们将训练一个核支持向量机(SVM),以了解 PolynomialCountSketch 在近似核性能方面的表现如何。

from sklearn.svm import SVC

## 训练一个核支持向量机
ksvm = SVC(C=500.0, kernel="poly", degree=4, coef0=0, gamma=1.0)
ksvm.fit(X_train, y_train)
ksvm_score = 100 * ksvm.score(X_test, y_test)

## 打印核支持向量机的准确率
print(f"Kernel-SVM score on raw features: {ksvm_score:.2f}%")

比较结果

我们将绘制不同方法的结果与它们的训练时间,以比较它们的性能。

import matplotlib.pyplot as plt

## 绘制不同方法的结果
fig, ax = plt.subplots(figsize=(7, 7))
ax.scatter(
    [
        lsvm_time,
    ],
    [
        lsvm_score,
    ],
    label="线性支持向量机",
    c="绿色",
    marker="^",
)

for n_components in N_COMPONENTS:
    ax.scatter(
        [
            results[f"线性支持向量机 + PS({n_components})"]["时间"],
        ],
        [
            results[f"线性支持向量机 + PS({n_components})"]["得分"],
        ],
        c="蓝色",
    )
    ax.annotate(
        f"组件数量={n_components}",
        (
            results[f"线性支持向量机 + PS({n_components})"]["时间"],
            results[f"线性支持向量机 + PS({n_components})"]["得分"],
        ),
        xytext=(-30, 10),
        textcoords="offset pixels",
    )

ax.scatter(
    [
        ksvm_time,
    ],
    [
        ksvm_score,
    ],
    label="核支持向量机",
    c="红色",
    marker="x",
)

ax.set_xlabel("训练时间(秒)")
ax.set_ylabel("准确率(%)")
ax.legend()
plt.show()

需注意,代码中的results变量在前面未定义,可能会导致运行时错误,实际使用时请确保其已正确定义。

总结

本实验展示了如何在 scikit-learn 中使用多项式核近似来高效地生成多项式核特征空间近似。我们将此技术应用于 Covtype 数据集,将其转化为一个二分类问题,并训练线性分类器以近似核化分类器的准确率。我们还比较了不同方法的性能,并绘制了结果与它们的训练时间的关系图。