绘制核岭回归

Machine LearningMachine LearningBeginner
立即练习

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

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

简介

在本教程中,我们将使用Scikit-Learn(Python中一个流行的机器学习库)比较核岭回归(KRR)和支持向量回归(SVR)。这两种模型都通过使用核技巧来学习非线性函数。KRR和SVR在损失函数和拟合方法上有所不同。我们将使用一个人工数据集,该数据集由一个正弦目标函数和每隔五个数据点添加的强噪声组成。

虚拟机使用提示

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

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

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


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/svm("Support Vector Machines") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/model_selection("Model Selection") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/kernel_ridge("Kernel Ridge Regression") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/svm -.-> lab-49178{{"绘制核岭回归"}} sklearn/model_selection -.-> lab-49178{{"绘制核岭回归"}} sklearn/kernel_ridge -.-> lab-49178{{"绘制核岭回归"}} ml/sklearn -.-> lab-49178{{"绘制核岭回归"}} end

生成样本数据

我们将生成一个数据集,该数据集由一个正弦目标函数和每隔五个数据点添加的强噪声组成。

import numpy as np

## 生成样本数据
rng = np.random.RandomState(42)
X = 5 * rng.rand(10000, 1)
y = np.sin(X).ravel()

## 给目标添加噪声
y[::5] += 3 * (0.5 - rng.rand(X.shape[0] // 5))

X_plot = np.linspace(0, 5, 100000)[:, None]

构建基于核的回归模型

我们将使用Scikit-Learn的GridSearchCV来构建KRR和SVR模型,以找到最佳超参数。

from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVR
from sklearn.kernel_ridge import KernelRidge

train_size = 100

## SVR模型
svr = GridSearchCV(
    SVR(kernel="rbf", gamma=0.1),
    param_grid={"C": [1e0, 1e1, 1e2, 1e3], "gamma": np.logspace(-2, 2, 5)},
)

## KRR模型
kr = GridSearchCV(
    KernelRidge(kernel="rbf", gamma=0.1),
    param_grid={"alpha": [1e0, 0.1, 1e-2, 1e-3], "gamma": np.logspace(-2, 2, 5)},
)

比较支持向量回归和核岭回归的时间

我们将使用在步骤2中找到的最佳超参数,比较支持向量回归(SVR)和核岭回归(KRR)模型的拟合时间和预测时间。

import time

## 拟合SVR
t0 = time.time()
svr.fit(X[:train_size], y[:train_size])
svr_fit = time.time() - t0

## 打印SVR模型的最佳参数和得分
print(f"最佳SVR的参数: {svr.best_params_},R2得分: {svr.best_score_:.3f}")
print("SVR选择了复杂度和带宽并在%.3f秒内拟合了模型" % svr_fit)

## 拟合KRR
t0 = time.time()
kr.fit(X[:train_size], y[:train_size])
kr_fit = time.time() - t0

## 打印KRR模型的最佳参数和得分
print(f"最佳KRR的参数: {kr.best_params_},R2得分: {kr.best_score_:.3f}")
print("KRR选择了复杂度和带宽并在%.3f秒内拟合了模型" % kr_fit)

## 计算SVR的支持向量比例
sv_ratio = svr.best_estimator_.support_.shape[0] / train_size
print("支持向量比例: %.3f" % sv_ratio)

## 使用SVR进行预测
t0 = time.time()
y_svr = svr.predict(X_plot)
svr_predict = time.time() - t0
print("SVR对%d个输入进行预测耗时%.3f秒" % (X_plot.shape[0], svr_predict))

## 使用KRR进行预测
t0 = time.time()
y_kr = kr.predict(X_plot)
kr_predict = time.time() - t0
print("KRR对%d个输入进行预测耗时%.3f秒" % (X_plot.shape[0], kr_predict))

查看结果

当使用网格搜索对RBF核的复杂度/正则化和带宽进行优化时,我们将可视化核岭回归(KRR)和支持向量回归(SVR)的学习模型。

import matplotlib.pyplot as plt

sv_ind = svr.best_estimator_.support_
plt.scatter(
    X[sv_ind],
    y[sv_ind],
    c="r",
    s=50,
    label="SVR支持向量",
    zorder=2,
    edgecolors=(0, 0, 0),
)
plt.scatter(X[:100], y[:100], c="k", label="数据", zorder=1, edgecolors=(0, 0, 0))
plt.plot(
    X_plot,
    y_svr,
    c="r",
    label="SVR(拟合: %.3f秒, 预测: %.3f秒)" % (svr_fit, svr_predict),
)
plt.plot(
    X_plot, y_kr, c="g", label="KRR(拟合: %.3f秒, 预测: %.3f秒)" % (kr_fit, kr_predict)
)
plt.xlabel("数据")
plt.ylabel("目标")
plt.title("SVR与核岭回归")
_ = plt.legend()

可视化训练和预测时间

我们将可视化不同训练集大小下核岭回归(KRR)和支持向量回归(SVR)的拟合时间和预测时间。

_, ax = plt.subplots()

sizes = np.logspace(1, 3.8, 7).astype(int)
for name, estimator in {
    "KRR": KernelRidge(kernel="rbf", alpha=0.01, gamma=10),
    "SVR": SVR(kernel="rbf", C=1e2, gamma=10),
}.items():
    train_time = []
    test_time = []
    for train_test_size in sizes:
        t0 = time.time()
        estimator.fit(X[:train_test_size], y[:train_test_size])
        train_time.append(time.time() - t0)

        t0 = time.time()
        estimator.predict(X_plot[:1000])
        test_time.append(time.time() - t0)

    plt.plot(
        sizes,
        train_time,
        "o-",
        color="r" if name == "SVR" else "g",
        label="%s(训练)" % name,
    )
    plt.plot(
        sizes,
        test_time,
        "o--",
        color="r" if name == "SVR" else "g",
        label="%s(测试)" % name,
    )

plt.xscale("log")
plt.yscale("log")
plt.xlabel("训练集大小")
plt.ylabel("时间(秒)")
plt.title("执行时间")
_ = plt.legend(loc="best")

可视化学习曲线

我们将可视化核岭回归(KRR)和支持向量回归(SVR)的学习曲线。

from sklearn.model_selection import LearningCurveDisplay

_, ax = plt.subplots()

svr = SVR(kernel="rbf", C=1e1, gamma=0.1)
kr = KernelRidge(kernel="rbf", alpha=0.1, gamma=0.1)

common_params = {
    "X": X[:100],
    "y": y[:100],
    "train_sizes": np.linspace(0.1, 1, 10),
    "scoring": "neg_mean_squared_error",
    "negate_score": True,
    "score_name": "Mean Squared Error",
    "std_display_style": None,
    "ax": ax,
}

LearningCurveDisplay.from_estimator(svr, **common_params)
LearningCurveDisplay.from_estimator(kr, **common_params)
ax.set_title("学习曲线")
ax.legend(handles=ax.get_legend_handles_labels()[0], labels=["SVR", "KRR"])

plt.show()

总结

在本教程中,我们使用Scikit-Learn比较了核岭回归(KRR)和支持向量回归(SVR)。我们生成了一个数据集,该数据集由一个正弦目标函数和每隔五个数据点添加的强噪声组成。我们使用Scikit-Learn的GridSearchCV构建了KRR和SVR模型,以找到最佳超参数。我们使用找到的最佳超参数比较了SVR和KRR模型的拟合时间和预测时间。当使用网格搜索对RBF核的复杂度/正则化和带宽进行优化时,我们可视化了KRR和SVR的学习模型。我们还可视化了不同训练集大小下KRR和SVR的拟合时间和预测时间。最后,我们可视化了KRR和SVR的学习曲线。