RBF 核的显式特征图近似

Machine LearningMachine LearningBeginner
立即练习

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

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

本实验展示了如何使用RBFSampler和Nystroem来近似RBF核的特征图,以便在数字数据集上使用支持向量机(SVM)进行分类。我们比较了在原始空间中使用线性SVM、使用近似映射的线性SVM以及使用核化SVM的结果。展示了在近似映射中,不同数量的蒙特卡罗采样(对于使用随机傅里叶特征的RBFSampler)和训练集的不同大小子集(对于Nystroem)的时间和准确性。

虚拟机使用提示

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

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

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


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/AdvancedDataAnalysisandDimensionalityReductionGroup(["Advanced Data Analysis and Dimensionality Reduction"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn(("Sklearn")) -.-> sklearn/DataPreprocessingandFeatureEngineeringGroup(["Data Preprocessing and Feature Engineering"]) sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/kernel_approximation("Kernel Approximation") sklearn/AdvancedDataAnalysisandDimensionalityReductionGroup -.-> sklearn/decomposition("Matrix Decomposition") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/kernel_approximation -.-> lab-49176{{"RBF 核的显式特征图近似"}} sklearn/decomposition -.-> lab-49176{{"RBF 核的显式特征图近似"}} ml/sklearn -.-> lab-49176{{"RBF 核的显式特征图近似"}} end

Python 包和数据集导入、加载数据集

## 标准的科学 Python 导入
import matplotlib.pyplot as plt
import numpy as np
from time import time

## 导入数据集、分类器和性能指标
from sklearn import datasets, svm, pipeline
from sklearn.kernel_approximation import RBFSampler, Nystroem
from sklearn.decomposition import PCA

## 数字数据集
digits = datasets.load_digits(n_class=9)

时间和准确率绘图

## 要在此数据上应用分类器,我们需要将图像展平,
## 把数据转换为(样本数, 特征数)矩阵:
n_samples = len(digits.data)
data = digits.data / 16.0
data -= data.mean(axis=0)

## 我们在前半部分数字上学习数字特征
data_train, targets_train = (data[: n_samples // 2], digits.target[: n_samples // 2])

## 现在预测后半部分数字的值:
data_test, targets_test = (data[n_samples // 2 :], digits.target[n_samples // 2 :])

## 创建一个分类器:一个支持向量分类器
kernel_svm = svm.SVC(gamma=0.2)
linear_svm = svm.LinearSVC(dual="auto")

## 从核近似和线性支持向量机创建管道
feature_map_fourier = RBFSampler(gamma=0.2, random_state=1)
feature_map_nystroem = Nystroem(gamma=0.2, random_state=1)

fourier_approx_svm = pipeline.Pipeline([
  ("feature_map", feature_map_fourier),
  ("svm", svm.LinearSVC(dual="auto"))
])

nystroem_approx_svm = pipeline.Pipeline([
  ("feature_map", feature_map_nystroem),
  ("svm", svm.LinearSVC(dual="auto"))
])

## 使用线性和核支持向量机进行拟合和预测:
kernel_svm_time = time()
kernel_svm.fit(data_train, targets_train)
kernel_svm_score = kernel_svm.score(data_test, targets_test)
kernel_svm_time = time() - kernel_svm_time

linear_svm_time = time()
linear_svm.fit(data_train, targets_train)
linear_svm_score = linear_svm.score(data_test, targets_test)
linear_svm_time = time() - linear_svm_time

sample_sizes = 30 * np.arange(1, 10)
fourier_scores = []
nystroem_scores = []
fourier_times = []
nystroem_times = []

for D in sample_sizes:
  fourier_approx_svm.set_params(feature_map__n_components=D)
  nystroem_approx_svm.set_params(feature_map__n_components=D)

  start = time()
  nystroem_approx_svm.fit(data_train, targets_train)
  nystroem_times.append(time() - start)

  start = time()
  fourier_approx_svm.fit(data_train, targets_train)
  fourier_times.append(time() - start)

  fourier_score = fourier_approx_svm.score(data_test, targets_test)
  nystroem_score = nystroem_approx_svm.score(data_test, targets_test)
  nystroem_scores.append(nystroem_score)
  fourier_scores.append(fourier_score)

## 绘制结果:
plt.figure(figsize=(16, 4))
accuracy = plt.subplot(121)
## 第二个y轴用于时间
timescale = plt.subplot(122)

accuracy.plot(sample_sizes, nystroem_scores, label="Nystroem近似核")
timescale.plot(sample_sizes, nystroem_times, "--", label="Nystroem近似核")

accuracy.plot(sample_sizes, fourier_scores, label="傅里叶近似核")
timescale.plot(sample_sizes, fourier_times, "--", label="傅里叶近似核")

## 精确的rbf和线性核的水平线:
accuracy.plot([sample_sizes[0], sample_sizes[-1]], [linear_svm_score, linear_svm_score], label="线性支持向量机")
timescale.plot([sample_sizes[0], sample_sizes[-1]], [linear_svm_time, linear_svm_time], "--", label="线性支持向量机")

accuracy.plot([sample_sizes[0], sample_sizes[-1]], [kernel_svm_score, kernel_svm_score], label="rbf支持向量机")
timescale.plot([sample_sizes[0], sample_sizes[-1]], [kernel_svm_time, kernel_svm_time], "--", label="rbf支持向量机")

## 数据集维度 = 64的垂直线
accuracy.plot([64, 64], [0.7, 1], label="n_features")

## 图例和标签
accuracy.set_title("分类准确率")
timescale.set_title("训练时间")
accuracy.set_xlim(sample_sizes[0], sample_sizes[-1])
accuracy.set_xticks(())
accuracy.set_ylim(np.min(fourier_scores), 1)
timescale.set_xlabel("采样步数 = 变换后的特征维度")
accuracy.set_ylabel("分类准确率")
timescale.set_ylabel("训练时间(秒)")
accuracy.legend(loc="最佳")
timescale.legend(loc="最佳")
plt.tight_layout()
plt.show()

RBF核支持向量机和线性支持向量机的决策面

## 可视化决策面,投影到数据集的前两个主成分上
pca = PCA(n_components=8).fit(data_train)

X = pca.transform(data_train)

## 沿着前两个主成分生成网格
multiples = np.arange(-2, 2, 0.1)
## 沿着第一个成分的步长
first = multiples[:, np.newaxis] * pca.components_[0, :]
## 沿着第二个成分的步长
second = multiples[:, np.newaxis] * pca.components_[1, :]
## 合并
grid = first[np.newaxis, :, :] + second[:, np.newaxis, :]
flat_grid = grid.reshape(-1, data.shape[1])

## 绘图标题
titles = [
    "带rbf核的支持向量分类器",
    "带傅里叶rbf特征映射的支持向量分类器(线性核)\nn_components=100",
    "带Nystroem rbf特征映射的支持向量分类器(线性核)\nn_components=100",
]

plt.figure(figsize=(18, 7.5))
plt.rcParams.update({"font.size": 14})
## 预测并绘图
for i, clf in enumerate((kernel_svm, nystroem_approx_svm, fourier_approx_svm)):
    ## 绘制决策边界。为此,我们将为网格[x_min, x_max]x[y_min, y_max]中的每个点分配一种颜色。
    plt.subplot(1, 3, i + 1)
    Z = clf.predict(flat_grid)

    ## 将结果放入颜色图中
    Z = Z.reshape(grid.shape[:-1])
    levels = np.arange(10)
    lv_eps = 0.01  ## 调整从计算出的等高线级别到颜色的映射。
    plt.contourf(
        multiples,
        multiples,
        Z,
        levels=levels - lv_eps,
        cmap=plt.cm.tab10,
        vmin=0,
        vmax=10,
        alpha=0.7,
    )
    plt.axis("off")

    ## 也绘制训练点
    plt.scatter(
        X[:, 0],
        X[:, 1],
        c=targets_train,
        cmap=plt.cm.tab10,
        edgecolors=(0, 0, 0),
        vmin=0,
        vmax=10,
    )

    plt.title(titles[i])
plt.tight_layout()
plt.show()

总结

本实验展示了如何使用RBFSampler和Nystroem来近似RBF核的特征图,以便在数字数据集上使用支持向量机(SVM)进行分类。我们比较了在原始空间中使用线性SVM、使用近似映射的线性SVM以及使用核化SVM的结果。展示了在近似映射中,不同数量的蒙特卡罗采样(对于使用随机傅里叶特征的RBFSampler)和训练集的不同大小子集(对于Nystroem)的时间和准确性。最后,将分类器的决策面投影到数据的前两个主成分上进行了可视化。