Hi,我是Johngo~
这几天有同学面试了米哈游算法岗位。
由于是刚刚毕业,一面一直是基础理论,持续一个半小时。
咱们今天分享一个其中的一个面试点:支持向量回归~
支持向量回归(Support Vector Regression, SVR)是机器学习中的一种回归算法。简单来说,它是通过找到一条最佳的直线(或曲线)来预测数据的趋势或结果,但它不只是简单地找最合适的直线,而是有点“宽容”地忽略一些离直线较远的数据点。
「什么是回归?」
我们先理解一下回归的概念。回归是一种预测连续值的方法。比如:
你想预测明天的气温 你想根据房子的面积预测房价
这些情况需要使用回归算法,因为它们的结果是一个连续的数值。
「什么是支持向量回归?」
支持向量回归的核心思想是:找到一条直线,尽量靠近所有的样本点,但允许有些点偏离直线,只要偏离的程度在我们设定的允许范围内就可以。这条线代表了我们对未来数据的预测。
举个简单的例子:
「假设场景」
假设一位菜农,有一系列的数据,显示了过去几天不同天气条件下的西红柿产量。想根据这些数据预测未来几天的西红柿产量。
数据看起来可能是这样:
温度 20°C,产量 100 公斤 温度 22°C,产量 110 公斤 温度 25°C,产量 130 公斤 温度 30°C,产量 150 公斤
你可以把这些数据点画在一个图上,横轴是温度,纵轴是产量。然后你希望找到一条直线(或者曲线),可以帮助你预测某个温度下的产量。
「支持向量回归的做法」
支持向量回归会试图在这些数据点中找到一条“最佳的直线”。它会试图让大部分的数据点尽可能接近这条线,但它不是严格要求每个点都在直线上,而是允许某些数据点稍微偏离这条线。
支持向量回归和其他回归的不同之处在于:
宽容度:支持向量回归允许某些点不在预测线附近,只要它们的误差在我们设定的范围内(这叫做“epsilon”)。比如,你可以设定“允许的误差范围是±10公斤”,只要预测的产量和实际产量之间的误差不超过10公斤,就算是可以接受的。
边界上的数据点:在支持向量回归中,决定最终回归线的其实是那些“刚好在边界上的数据点”(叫做支持向量)。这些数据点会帮助确定预测线的位置和方向。
「更具体一点的例子」
假设有以下温度和产量数据点:
温度 18°C,产量 90 公斤 温度 21°C,产量 105 公斤 温度 23°C,产量 115 公斤 温度 26°C,产量 135 公斤 温度 29°C,产量 140 公斤 温度 32°C,产量 160 公斤
希望预测30°C的温度下,产量是多少。
使用支持向量回归算法,它会画出一条预测线,并且允许有些点(比如产量 90 公斤和160 公斤的点)稍微偏离这条线,因为它们可能是特殊情况(比如那天温度虽然正常,但西红柿生长状况因为其他原因不佳)。
最终,支持向量回归预测出的30°C时的产量,可能是148公斤左右,这条线没有特别追求让所有数据点都完全对齐,而是追求了整体趋势的合理性。
支持向量回归
在支持向量机(SVM)的基础上,支持向量回归(SVR)通过引入一个ε-不敏感损失函数(ε-insensitive loss function)来处理回归问题。目标是找到一个函数 ( f(x) ),它不仅能很好地拟合数据,还能尽可能使模型具有一定的“宽容度”。
1. 支持向量回归的基本公式
假设给定数据集 ,其中 是特征, 是标签。SVR的目标是找到一个函数:
使得它能最小化以下目标函数(损失函数):
这个目标函数表示要尽量使 的范数最小,从而得到一个平滑的预测函数。
2. ε-不敏感损失函数
为了处理回归问题,SVR引入了ε-不敏感损失函数,它允许预测值和实际值之间的误差在某个阈值内不被计算为损失。即,当预测值和实际值之间的误差小于 ε 时,不会产生惩罚。
公式如下:
3. 软间隔
为了处理噪声或异常值,SVR引入了松弛变量 和 ,用于允许某些数据点位于ε以外的区域,但要对其进行惩罚。最终目标函数变为:
其中, 是惩罚系数,控制了对错误预测的惩罚力度。
4. 约束条件
约束条件如下:
通过拉格朗日乘子法和二次规划的求解,我们最终可以得出SVR的对偶形式,从而得到支持向量和回归函数的具体解。
咱们使用California Housing
数据集,并进行多维特征的回归预测。
# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR
from sklearn.datasets import fetch_california_housing
from sklearn.metrics import mean_squared_error, r2_score
import seaborn as sns
# 加载California Housing数据集
housing = fetch_california_housing()
X = housing.data
y = housing.target
# 数据标准化处理
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
# 定义SVR模型
svr = SVR(kernel='rbf', C=100, epsilon=0.1)
svr.fit(X_train, y_train)
# 预测
y_pred_train = svr.predict(X_train)
y_pred_test = svr.predict(X_test)
# 计算评估指标
mse_train = mean_squared_error(y_train, y_pred_train)
mse_test = mean_squared_error(y_test, y_pred_test)
r2_train = r2_score(y_train, y_pred_train)
r2_test = r2_score(y_test, y_pred_test)
print(f"训练集MSE: {mse_train:.3f}, R2: {r2_train:.3f}")
print(f"测试集MSE: {mse_test:.3f}, R2: {r2_test:.3f}")
# 绘制真实值与预测值的对比图(测试集)
plt.figure(figsize=(10, 6))
plt.scatter(y_test, y_pred_test, color='b', alpha=0.6, label='Predicted vs True')
plt.plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], color='r', lw=2, label='Ideal Fit')
plt.xlabel('True Values')
plt.ylabel('Predicted Values')
plt.title('SVR Predicted vs True Values (Test Set)')
plt.legend()
plt.grid(True)
plt.show()
# 残差分析
residuals = y_test - y_pred_test
plt.figure(figsize=(10, 6))
sns.histplot(residuals, kde=True, color='purple')
plt.title('Residuals Distribution (Test Set)')
plt.xlabel('Residuals')
plt.grid(True)
plt.show()
# 特征重要性分析:基于SVR的支持向量
support_vectors = svr.support_
plt.figure(figsize=(10, 6))
plt.scatter(X_train[support_vectors][:, 0], X_train[support_vectors][:, 1], c='r', s=50, label='Support Vectors')
plt.title('Support Vectors (2D Visualization)')
plt.xlabel(housing.feature_names[0])
plt.ylabel(housing.feature_names[1])
plt.legend()
plt.grid(True)
plt.show()
数据集:我们使用了 fetch_california_housing()
函数来加载California Housing
数据集,该数据集有8个特征,用于预测房价中位数。数据标准化:对特征进行标准化处理,使得不同特征的尺度相似,便于 SVM 模型的训练。 SVR模型:使用了RBF核函数的支持向量回归(SVR)模型,设置 C=100
,epsilon=0.1
。评估:使用均方误差(MSE)和决定系数(R²)来评估模型在训练集和测试集上的表现。