在机器学习领域,核岭回归(Kernel Ridge Regression, KRR)和支持向量回归(Support Vector Regression, SVR)是两种常用的回归分析方法。它们都利用核技巧来实现非线性函数的拟合。尽管两者在某些方面相似,但在损失函数、模型稀疏性以及计算效率等方面存在显著差异。本文将通过一个包含正弦波目标函数和强噪声的人工数据集来展示这两种方法的性能对比。
首先,生成了一个包含10000个样本点的数据集,其中目标函数为正弦波形,并且每第五个数据点上添加了强噪声。接着,构建了基于核的回归模型,包括SVR和KRR。为了优化模型参数,采用了网格搜索(GridSearchCV)方法来选择最佳的正则化参数和核函数带宽。
import numpy as np
from sklearn.kernel_ridge import KernelRidge
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVR
# 设置随机数种子以保证结果可复现
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]
在模型构建过程中,使用了径向基函数(RBF)核,并对其进行了参数调优。通过GridSearchCV,为SVR和KRR分别选择了最佳的C(正则化参数)和gamma(核函数带宽)值。
接下来,比较了SVR和KRR在模型训练和预测阶段所需的时间。实验结果表明,KRR在训练阶段的速度大约是SVR的3-4倍。尽管理论上SVR在预测阶段应该更快,因为它学习了一个稀疏模型,但实际上,由于核函数计算的实现细节,KRR在某些情况下可能与SVR一样快甚至更快。
import time
# 训练SVR模型
t0 = time.time()
svr.fit(X[:100], y[:100])
svr_fit = time.time() - t0
# 训练KRR模型
t0 = time.time()
kr.fit(X[:100], y[:100])
kr_fit = time.time() - t0
此外,还绘制了SVR和KRR在不同训练集大小下的拟合和预测时间。结果表明,对于中等大小的训练集(几千个样本),KRR的拟合速度更快;而对于更大的训练集,SVR的扩展性更好。在预测时间方面,尽管SVR理论上应该更快,但由于实现细节的差异,实际情况可能并非如此。
为了进一步分析模型的学习性能,绘制了学习曲线。通过比较不同训练集大小下的平均均方误差(Mean Squared Error, MSE),可以观察到模型性能随训练数据量的增加而变化的趋势。
from sklearn.model_selection import LearningCurveDisplay
import matplotlib.pyplot as plt
# 设置绘图参数
_, 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()