核岭回归与支持向量回归比较

核岭回归(KRR)和支持向量回归(SVR)都是通过核技巧来学习非线性函数机器学习方法。核技巧允许它们在由核函数诱导的空间中学习线性函数,这在原始空间中对应于非线性函数。这两种方法的主要区别在于它们的损失函数:KRR使用岭损失,而SVR使用ε-不敏感损失。与SVR相比,KRR可以以封闭形式拟合,对于中等规模的数据集来说,通常训练速度更快。然而,学习到的模型是非稀疏的,因此在预测时比SVR慢。

本例在包含正弦目标函数和强噪声的数据集上展示了这两种方法。噪声被添加到每第五个数据点上。这个例子由scikit-learn开发者编写,遵循BSD-3-Clause许可证。

首先,生成样本数据。使用numpy库来创建随机数生成器,并生成10000个数据点。然后,计算这些数据点的正弦值作为目标值,并人为地在每第五个数据点上添加噪声。接下来,为绘图创建了一个更密集的数据点集合。

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]

接下来,构建基于核的回归模型。使用sklearn库中的KernelRidge和SVR类,并利用GridSearchCV进行参数搜索,以找到最佳的C和gamma值。

from sklearn.kernel_ridge import KernelRidge from sklearn.model_selection import GridSearchCV from sklearn.svm import SVR train_size = 100 svr = GridSearchCV(SVR(kernel="rbf", gamma=0.1), param_grid={"C": [1e0, 1e1, 1e2, 1e3], "gamma": np.logspace(-2, 2, 5)}) kr = GridSearchCV(KernelRidge(kernel="rbf", gamma=0.1), param_grid={"alpha": [1e0, 0.1, 1e-2, 1e-3], "gamma": np.logspace(-2, 2, 5)})

比较了SVR和KRR的训练时间。结果显示,KRR的训练速度大约是SVR的3-4倍。尽管理论上SVR应该能够更快地预测100000个目标值,因为它只使用了大约1/3的训练数据点作为支持向量,学习了一个稀疏模型。然而,在实践中,由于模型实现细节的不同,KRR可能和SVR一样快,甚至更快。

import time t0 = time.time() svr.fit(X[:train_size], y[:train_size]) svr_fit = time.time() - t0 print(f"Best SVR with params: {svr.best_params_} and R2 score: {svr.best_score_:.3f}") print("SVR complexity and bandwidth selected and model fitted in %.3f s" % svr_fit) t0 = time.time() kr.fit(X[:train_size], y[:train_size]) kr_fit = time.time() - t0 print(f"Best KRR with params: {kr.best_params_} and R2 score: {kr.best_score_:.3f}") print("KRR complexity and bandwidth selected and model fitted in %.3f s" % kr_fit)

还可视化了训练和预测时间。图表显示了不同训练集大小下,KRR和SVR的训练和预测时间。对于中等规模的训练集(少于几千个样本),KRR的训练速度比SVR快;然而,对于更大的训练集,SVR的扩展性更好。在预测时间方面,理论上SVR应该比KRR快,但由于实现细节的不同,实际情况并非总是如此。

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 support vectors", zorder=2, edgecolors=(0, 0, 0)) plt.scatter(X[:100], y[:100], c="k", label="data", zorder=1, edgecolors=(0, 0, 0)) plt.plot(X_plot, y_svr, c="r", label="SVR (fit: %.3f s, predict: %.3f s)" % (svr_fit, svr_predict)) plt.plot(X_plot, y_kr, c="g", label="KRR (fit: %.3f s, predict: %.3f s)" % (kr_fit, kr_predict)) plt.xlabel("data") plt.ylabel("target") plt.title("SVR versus Kernel Ridge") _ = plt.legend()

最后,展示了学习曲线,以了解随着训练集大小的变化,模型的性能如何变化。通过这些图表,可以更好地理解不同模型在不同数据规模下的表现。

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", "score_type": "test", "std_display_style": None, "ax": ax} LearningCurveDisplay.from_estimator(svr, **common_params) LearningCurveDisplay.from_estimator(kr, **common_params) ax.set_title("Learning curves") ax.legend(handles=ax.get_legend_handles_labels()[0], labels=["SVR", "KRR"]) plt.show()
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485