sklearn实现SVR回归(支持向量机)
支持向量回归(Support Vector Regression,SVR)是一种用于回归分析的机器学习算法,它借鉴了支持向量机(SVM)分类算法的思想。
💥 项目专栏:sklearn实现经典机器学习算法(附代码+原理介绍)
前言
🌟 哈喽,亲爱的小伙伴们,你们知道吗?最近我们的粉丝群里有好多小可爱私信问我一些关于决策树、逻辑回归等机器学习的超级有趣的问题呢!🌈 为了让大家更轻松地理解,我决定开一个超可爱的专栏,叫做 用sklearn玩转机器学习
,特别适合机器学习的小新手哦!
🍬 在这个专栏里,我们会用sklearn这个超级强大的魔法工具来实现各种闪闪发光的机器学习算法!不用担心难度哦,我会用最简单、最可爱的方式,带领大家一起探索算法的神秘世界!✨
🎈 适合哪些小伙伴加入呢?当然是对机器学习感兴趣的小新手们,还有那些刚开始接触sklearn的可爱宝宝们!我们会一起学习如何用sklearn轻松实现那些看起来好厉害的机器学习算法,让新手小白也能快快乐乐地理解它们哦!
🌸 在这个专栏里,大家可以看到用sklearn实现的机器学习算法,我们不仅仅是理论学习哦,每一篇文章都会附带 完整的代码+超级可爱的原理讲解
,让大家在轻松愉快的氛围中一起学习成长呢!🌼 快来加入我们的学习大冒险吧!
🚨 我的项目环境:
- 平台:Windows11
- 语言环境:Python 3.10
- 编译器:Jupyter Lab、PyCharm
- scikit-learn:1.2.1
- Pandas:1.3.5
- Numpy:1.19.3
- Scipy:1.7.3
- Matplotlib:3.1.3
💥 项目专栏:sklearn实现经典机器学习算法(附代码+原理介绍)
一、算法背景
支持向量回归(Support Vector Regression,SVR)是一种用于回归分析的机器学习算法,它借鉴了支持向量机(SVM)分类算法的思想。SVR的算法背景如下:
-
支持向量机(SVM):
- 支持向量机是一种用于二元分类的强大机器学习算法。它的核心思想是找到一个能够将两个不同类别的数据分隔开的最优超平面(决策边界),并使得两侧离超平面最近的数据点(支持向量)到超平面的距离最大化。这个距离被称为间隔(margin)。
- SVM通过优化一个凸二次规划问题来找到最佳超平面,这个问题的目标是最大化间隔,同时限制支持向量的误分类错误。支持向量机还引入了核函数的概念,使其能够处理非线性可分的数据。
-
SVR的引入:
- SVR是基于SVM的思想,专门用于回归问题。与分类不同,回归任务的目标是预测连续数值输出,而不是离散的类别标签。SVR通过在训练数据中找到一个回归函数,以尽量拟合数据点并保持较大的间隔来解决回归问题。
- 与SVM类似,SVR引入了核函数来处理非线性关系。SVR的目标是找到一个最优超平面,使得在这个超平面上的预测值与真实值之间的误差尽可能小,同时限制误差不超过一个用户定义的容忍度。
-
工作原理:
- SVR的工作原理是在训练集上寻找一个超平面,使得所有训练样本点都位于这个超平面的ε-tube(一个带宽为ε的管道)内。ε-tube内的数据点对回归函数的拟合没有影响,而位于ε-tube之外的点会被视为异常值。
- SVR的目标是最小化误差项,同时限制误差项不超过ε。可以通过调整超参数(如C、ε、核函数等)来控制模型的复杂性和泛化能力。
总之,支持向量回归(SVR)是一种用于回归分析的机器学习算法,它通过在训练数据上找到一个最优超平面来拟合数据,同时限制误差项,从而实现对连续数值输出的预测。SVR借鉴了支持向量机(SVM)的思想,通过核函数处理非线性关系,是回归问题中的有力工具。
二、算法原理
支持向量回归(Support Vector Regression,SVR)是一种用于解决回归问题的机器学习算法,它基于支持向量机(SVM)的思想,并通过最小化带宽为 ε 的管道内的训练数据点与模型预测之间的误差来建立回归模型。以下是SVR的算法原理的详细介绍:
-
数据表示:
- SVR处理的数据集包括一组输入特征(通常表示为X)和对应的连续目标值或标签(通常表示为y)。这些目标值是实数,而不是离散的类别标签。
-
目标函数:
- SVR的目标是建立一个回归函数f(X),该函数能够预测目标值y。SVR通过最小化目标函数的误差来拟合数据。目标函数通常表示为:
其中,||f(X) - y||^2 表示欧几里得范数(L2范数)的平方,用于测量预测值与真实值之间的距离。min 0.5 * ||f(X) - y||^2
- SVR的目标是建立一个回归函数f(X),该函数能够预测目标值y。SVR通过最小化目标函数的误差来拟合数据。目标函数通常表示为:
-
带宽 ε-tube:
- SVR引入了一个带宽为 ε 的管道(ε-tube),它是一个容忍度范围,在这个管道内的误差被认为是可以接受的。管道的宽度 ε 是一个超参数,控制了模型的容忍度。
- SVR的目标是最小化误差项,同时确保大部分训练数据点都位于 ε-tube 内,只有一小部分数据点位于管道外。这些位于管道外的数据点称为"支持向量"。
-
支持向量:
- 在SVR中,支持向量是指那些位于 ε-tube 边界上或管道外的训练数据点。这些数据点对于模型的拟合起着关键作用,它们影响着管道的位置和宽度,从而影响了回归函数的形状。
- 支持向量的数目通常较少,因为它们是在训练数据中与模型预测相差较大的样本点。
-
超参数调整:
- SVR有一些关键的超参数需要调整,例如 ε(带宽)、C(正则化参数)、核函数的类型等。这些超参数的选择可以影响模型的性能和复杂性。
- 超参数 C 控制了模型的复杂性,较小的 C 值将产生更平滑的回归函数,而较大的 C 值将允许更多的数据点位于 ε-tube 外。
-
核函数:
- 类似于支持向量机,SVR也可以使用不同类型的核函数,如线性核、多项式核、RBF(径向基函数)核等,来处理非线性关系。选择适当的核函数对于拟合复杂的数据模式非常重要。
-
求解问题:
- SVR的优化问题可以通过凸二次规划来求解。这个问题的目标是最小化目标函数,并满足约束条件,包括管道内的误差不超过 ε 和支持向量上的误差等于 ε。
-
预测:
- 一旦模型训练完成,可以使用它来进行预测。给定一个新的输入样本,SVR会计算出相应的目标值,这个值可以用于回归任务的预测。
总之,支持向量回归(SVR)是一种用于回归分析的强大算法,它通过最小化带宽为 ε 的管道内的误差来建立回归模型,同时限制了模型的复杂性。SVR的核心思想是通过选择支持向量来捕获数据中的关键信息,从而建立一个能够适应数据分布的回归函数。通过调整超参数和选择合适的核函数,SVR可以处理各种不同类型的回归问题。
三、算法实现
3.1 导包
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.svm import SVR
3.2 加载数据集
# 生成样本数据
X = np.sort(5 * np.random.rand(40, 1), axis=0)
y = np.sin(X).ravel()
# 向目标值添加噪声
y[::5] += 3 * (0.5 - np.random.rand(8))
这部分代码用于生成样本数据,并向目标值添加一些噪声。让我为您详细解释每一部分的功能:
-
X = np.sort(5 * np.random.rand(40, 1), axis=0)
:- 这行代码生成了一个包含40个样本的输入特征
X
,这些样本是在0到5之间均匀分布的随机数。np.random.rand(40, 1)
用于生成一个形状为(40, 1)的随机数矩阵,其中每个元素都在0到1之间。然后,通过乘以5,将这些随机数扩展到0到5之间。最后,np.sort
函数对生成的数据进行排序,以确保输入特征按升序排列。
- 这行代码生成了一个包含40个样本的输入特征
-
y = np.sin(X).ravel()
:- 这行代码生成了目标值
y
,它是输入特征X
的正弦函数。np.sin(X)
计算了每个输入特征对应的正弦值,并将结果存储在y
中。.ravel()
函数用于将y
转换为一维数组,以匹配X
的形状。
- 这行代码生成了目标值
-
y[::5] += 3 * (0.5 - np.random.rand(8))
:- 这行代码向目标值
y
的每个第5个元素(每隔5个元素)添加一些噪声。具体地说,它在这些位置上添加了从-1.5到1.5之间的随机噪声,这是通过计算3 * (0.5 - np.random.rand(8))
得到的。这个步骤模拟了实际数据中的随机噪声,使数据更加现实并具有一定的噪声性质。
- 这行代码向目标值
最终,您生成了一个具有一些噪声的正弦函数数据集,这样可以用于训练和测试支持向量回归(SVR)模型。这个数据集包含输入特征 X
和对应的目标值 y
,用于建立回归模型并评估其性能。
3.3 划分训练集、测试集
在机器学习中,将数据集分为训练集和测试集是为了评估模型的性能。训练集用于训练模型,而测试集用于评估模型在未见过的数据上的表现。您已经正确地将数据分为训练集和测试集。以下是您的代码和解释:
train_test_split
函数是Scikit-Learn中用于将数据集分割成训练集和测试集的函数。X
是输入特征的数据,y
是目标值(标签)的数据。test_size=0.2
指定了测试集的大小,这里设置为20%。这意味着80%的数据将用于训练模型,而20%的数据将用于测试模型。random_state=42
是一个随机种子,它确保每次运行代码时分割的方式都是相同的,以便结果的可重复性。
分割数据集是一个重要的步骤,它允许您在训练模型之后评估其性能,并检查模型在未见过的数据上的泛化能力。训练集用于拟合模型,而测试集用于评估模型的预测能力。
# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
3.4 定义模型
已经创建了三个不同核函数的支持向量回归(SVR)模型,包括RBF核、线性核和多项式核。以下是每个模型的说明:
-
RBF核模型 (
svr_rbf
):- 使用径向基函数(Radial Basis Function,RBF)核。RBF核是一种常用的非线性核函数,适用于处理复杂的非线性关系。
C=100
是正则化参数,控制了模型的复杂性。较大的C值允许模型更好地拟合训练数据,但可能导致过拟合。gamma=0.1
是RBF核的一个超参数,控制了核函数的形状。较小的gamma值会产生较大的核函数半径,从而使模型更平滑。epsilon=0.1
是SVR中带宽 ε-tube 的带宽参数,它控制了对训练误差的容忍度。
-
线性核模型 (
svr_lin
):- 使用线性核。线性核适用于处理线性关系的问题,它在数据线性可分时表现良好。
C=100
是正则化参数,与RBF核相同,它控制了模型的复杂性。
-
多项式核模型 (
svr_poly
):- 使用多项式核。多项式核适用于处理多项式关系的问题,通过增加多项式的次数来建模数据。
C=100
是正则化参数,与其他核相同。degree=3
是多项式核的次数,指定了多项式的阶数,这里是3次多项式。
这些不同核函数的选择允许您在回归问题中尝试不同的函数形式,以找到最适合数据的模型。接下来,您可以使用这些模型进行训练和测试,然后评估它们在您的数据集上的性能。
# 创建SVR模型,包括RBF、线性和多项式核函数
svr_rbf = SVR(kernel="rbf", C=100, gamma=0.1, epsilon=0.1)
svr_lin = SVR(kernel="linear", C=100)
svr_poly = SVR(kernel="poly", C=100, degree=3)
以下是以表格形式展示Scikit-Learn中支持向量回归(SVR)类的常用参数,包括参数名称、描述以及可选的值或类型:
参数 | 描述 | 可选的值/类型 |
---|---|---|
kernel | 用于指定核函数的类型。 | ‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’ |
C | 正则化强度的倒数,较小的值表示更强的正则化。 | 正浮点数 |
epsilon | ε-tube的宽度,用于控制对训练误差的容忍度。 | 正浮点数 |
gamma | RBF、多项式、Sigmoid核函数的系数。 | 正浮点数、‘scale’、‘auto’ |
degree | 多项式核的次数(仅对多项式核有效)。 | 正整数 |
coef0 | 核函数的独立系数(仅对多项式和Sigmoid核有效)。 | 浮点数 |
shrinking | 是否启用收缩启发式算法,可以加速训练。 | 布尔值 |
tol | 求解器的收敛容忍度。 | 正浮点数 |
max_iter | 求解器的最大迭代次数。 | 正整数 |
cache_size | 内核缓存大小(以MB为单位)。 | 正整数 |
verbose | 控制详细程度的日志输出级别。 | 正整数 |
coef0 | 核函数的独立系数(仅对多项式和Sigmoid核有效)。 | 浮点数 |
random_state | 随机数生成器的种子。 | 整数或 None |
decision_function_shape | 决策函数的形状,用于多类分类问题。 | ‘ovo’(一对一)、‘ovr’(一对其余)或 None |
这些参数允许您在构建支持向量回归模型时进行精细的调整,以满足您特定的数据和任务需求。不同的核函数和超参数选择可以影响模型的性能和拟合能力。理解这些参数及其影响有助于优化SVR模型以获得最佳的回归结果。
3.5 网格搜索
这段代码用于使用网格搜索(Grid Search)来寻找支持向量回归(SVR)模型的最佳超参数组合。以下是代码的详细说明:
-
param_grid
字典定义了需要搜索的超参数和其候选值:'C'
: 正则化参数C的候选值,包括1、10和100。'kernel'
: 核函数的候选类型,包括’rbf’(径向基函数核)、‘linear’(线性核)和’poly’(多项式核)。'gamma'
: RBF和多项式核的系数γ的候选值,包括0.1和1。
-
GridSearchCV(SVR(), param_grid, cv=5)
:GridSearchCV
是Scikit-Learn中的网格搜索交叉验证工具,用于在指定参数范围内搜索最佳超参数组合。SVR()
创建了一个支持向量回归模型的实例,param_grid
指定了需要搜索的超参数范围。cv=5
指定了交叉验证的折数,这里设置为5折交叉验证,以评估不同参数组合的性能。
-
grid_search.fit(X_train, y_train)
:fit
方法执行了网格搜索过程,它将在训练集X_train
和y_train
上寻找最佳超参数组合。- 网格搜索会尝试所有可能的参数组合,并使用交叉验证来评估每个组合的性能。
-
best_svr = grid_search.best_estimator_
:- 一旦网格搜索完成,
best_estimator_
属性会返回具有最佳性能的SVR模型。 - 这个最佳模型包含了最佳超参数组合下训练得到的SVR。
- 一旦网格搜索完成,
通过执行这段代码,您可以找到在指定的超参数范围内性能最佳的SVR模型,以便用于回归任务。这有助于提高模型的性能并获得更好的预测结果。
# 使用网格搜索来寻找最佳超参数
param_grid = {
'C': [1, 10, 100],
'kernel': ['rbf', 'linear', 'poly'],
'gamma': [0.1, 1],
}
grid_search = GridSearchCV(SVR(), param_grid, cv=5)
grid_search.fit(X_train, y_train)
# 获取最佳模型
best_svr = grid_search.best_estimator_
3.6 可视化拟合曲线
# 用于可视化的设置
lw = 2
svrs = [svr_rbf, svr_lin, svr_poly]
kernel_label = ["RBF", "Linear", "Polynomial"]
model_color = ["m", "c", "g"]
# 创建子图
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(15, 5), sharey=True)
# 训练模型并绘制结果
for ix, svr in enumerate(svrs):
y_pred = svr.fit(X_train, y_train).predict(X)
axes[ix].plot(X, y_pred, color=model_color[ix], lw=lw, label="{} model".format(kernel_label[ix]))
axes[ix].scatter(X_train, y_train, facecolor="none", edgecolor="k", s=50, label="training data")
axes[ix].scatter(X_test, y_test, facecolor="none", edgecolor="r", s=50, label="testing data")
axes[ix].legend()
axes[ix].set_title("SVR with {} kernel".format(kernel_label[ix]))
axes[ix].text(0.02, 0.85, "MSE: {:.2f}".format(mean_squared_error(y, y_pred)), transform=axes[ix].transAxes)
axes[ix].text(0.02, 0.75, "R2: {:.2f}".format(r2_score(y, y_pred)), transform=axes[ix].transAxes)
fig.text(0.5, 0.04, "data", ha="center", va="center")
fig.text(0.06, 0.5, "target", ha="center", va="center", rotation="vertical")
fig.suptitle("Support Vector Regression", fontsize=14)
plt.show()
这段代码用于可视化不同核函数的支持向量回归(SVR)模型的训练和预测结果,并展示了模型性能的评估指标。以下是代码的详细说明:
-
lw = 2
:lw
是线宽(linewidth)参数,用于指定线条的宽度。
-
svrs = [svr_rbf, svr_lin, svr_poly]
:svrs
是一个包含了三种不同核函数的SVR模型的列表。这些模型分别是RBF核、线性核和多项式核,之前已经创建。
-
kernel_label = ["RBF", "Linear", "Polynomial"]
:kernel_label
是一个包含核函数类型名称的列表,用于标识每个模型的核函数类型。
-
model_color = ["m", "c", "g"]
:model_color
是一个包含模型图形颜色的列表,用于为每个模型选择不同的颜色。
-
创建子图:
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(15, 5), sharey=True)
创建了一个包含3个子图的图形,每个子图对应一个不同核函数的SVR模型的结果可视化。nrows=1
和ncols=3
指定了子图的行数和列数,figsize
指定了图形的尺寸,sharey=True
表示所有子图共享y轴刻度。
-
训练模型并绘制结果:
- 使用一个循环遍历每个SVR模型(RBF、线性、多项式):
y_pred = svr.fit(X_train, y_train).predict(X)
训练模型并对所有数据点进行预测,将结果存储在y_pred
中。axes[ix].plot(X, y_pred, color=model_color[ix], lw=lw, label="{} model".format(kernel_label[ix]))
绘制模型的预测结果曲线。axes[ix].scatter(X_train, y_train, facecolor="none", edgecolor="k", s=50, label="training data")
绘制训练数据点。axes[ix].scatter(X_test, y_test, facecolor="none", edgecolor="r", s=50, label="testing data")
绘制测试数据点。axes[ix].legend()
添加图例。axes[ix].set_title("SVR with {} kernel".format(kernel_label[ix]))
设置子图的标题。- 使用
axes[ix].text
在子图中添加MSE和R2评估指标的文本标签。
- 使用一个循环遍历每个SVR模型(RBF、线性、多项式):
-
最后的一些代码用于设置图形的标签、标题和显示。
通过执行这段代码,您可以可视化不同核函数下SVR模型的拟合情况,以及模型性能的评估指标(均方误差和R²分数)。这有助于您比较不同核函数的模型性能并选择最合适的SVR模型。
完整源码
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.svm import SVR
# 生成样本数据
X = np.sort(5 * np.random.rand(40, 1), axis=0)
y = np.sin(X).ravel()
# 向目标值添加噪声
y[::5] += 3 * (0.5 - np.random.rand(8))
# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建SVR模型,包括RBF、线性和多项式核函数
svr_rbf = SVR(kernel="rbf", C=100, gamma=0.1, epsilon=0.1)
svr_lin = SVR(kernel="linear", C=100)
svr_poly = SVR(kernel="poly", C=100, degree=3)
# 使用网格搜索来寻找最佳超参数
param_grid = {
'C': [1, 10, 100],
'kernel': ['rbf', 'linear', 'poly'],
'gamma': [0.1, 1],
}
grid_search = GridSearchCV(SVR(), param_grid, cv=5)
grid_search.fit(X_train, y_train)
# 获取最佳模型
best_svr = grid_search.best_estimator_
# 用于可视化的设置
lw = 2
svrs = [svr_rbf, svr_lin, svr_poly]
kernel_label = ["RBF", "Linear", "Polynomial"]
model_color = ["m", "c", "g"]
# 创建子图
fig, axes = plt.subplots(nrows=1, ncols=3, figsize=(15, 5), sharey=True)
# 训练模型并绘制结果
for ix, svr in enumerate(svrs):
y_pred = svr.fit(X_train, y_train).predict(X)
axes[ix].plot(X, y_pred, color=model_color[ix], lw=lw, label="{} model".format(kernel_label[ix]))
axes[ix].scatter(X_train, y_train, facecolor="none", edgecolor="k", s=50, label="training data")
axes[ix].scatter(X_test, y_test, facecolor="none", edgecolor="r", s=50, label="testing data")
axes[ix].legend()
axes[ix].set_title("SVR with {} kernel".format(kernel_label[ix]))
axes[ix].text(0.02, 0.85, "MSE: {:.2f}".format(mean_squared_error(y, y_pred)), transform=axes[ix].transAxes)
axes[ix].text(0.02, 0.75, "R2: {:.2f}".format(r2_score(y, y_pred)), transform=axes[ix].transAxes)
fig.text(0.5, 0.04, "data", ha="center", va="center")
fig.text(0.06, 0.5, "target", ha="center", va="center", rotation="vertical")
fig.suptitle("Support Vector Regression", fontsize=14)
plt.show()
# 打印最佳超参数和评估指标
print("最佳超参数:", grid_search.best_params_)
y_pred_train = best_svr.predict(X_train)
y_pred_test = best_svr.predict(X_test)
print("训练集MSE:", mean_squared_error(y_train, y_pred_train))
print("训练集R2:", r2_score(y_train, y_pred_train))
print("测试集MSE:", mean_squared_error(y_test, y_pred_test))
print("测试集R2:", r2_score(y_test, y_pred_test))
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)