【机器学习】3.SVM支持向量机
·
支持向量机(SVM)全体系梳理
支持向量机(Support Vector Machine,SVM)是机器学习中经典的分类/回归算法,核心思想是找到最优超平面最大化分类间隔,可处理线性可分、线性不可分、非线性及回归任务,泛化能力强。以下从核心概念、分类体系、语法、案例等维度系统梳理。
一、核心基础概念
| 概念 | 定义 |
|---|---|
| 超平面 | n维空间中分割样本的线性边界,方程为 w⋅x+b=0w·x + b = 0w⋅x+b=0(www 为法向量,bbb 为截距) |
| 分类间隔 | 两类样本到超平面的最小距离之和,SVM目标是最大化此间隔 |
| 支持向量 | 距离超平面最近的样本点(决定超平面位置,其他样本不影响) |
| 松弛变量 | 软间隔SVM中引入的 ξi≥0\xi_i \geq 0ξi≥0,允许少量样本违反间隔约束 |
| 核函数 | 将低维非线性数据映射到高维线性可分空间的函数,避免高维直接计算(降计算成本) |
二、SVM分类体系(方法总览)
| SVM类型 | 适用场景 | 核心思想 | 关键参数 | sklearn实现类 |
|---|---|---|---|---|
| 硬间隔线性SVM | 严格线性可分、无噪声 | 最大化间隔,无惩罚(不允许样本越界) | 无(仅线性核) | SVC(kernel='linear', C=1e9)(近似) |
| 软间隔线性SVM | 线性不可分(少量噪声) | 允许少量样本越界,CCC 控制越界惩罚强度 | CCC(惩罚系数) | SVC(kernel='linear', C=xx) |
| 非线性SVM(核函数) | 非线性可分数据集 | 核函数映射到高维,转化为线性可分问题 | kernel、gamma、Ckernel、gamma、Ckernel、gamma、C | SVC(kernel='rbf'/'poly'/'sigmoid') |
| SVM回归(SVR) | 连续值回归任务 | 允许预测值与真实值有 ε\varepsilonε 偏差,最小化间隔 | C、epsilon、kernelC、epsilon、kernelC、epsilon、kernel | SVR(kernel='linear'/'rbf') |
| 多分类SVM | 多类别分类任务(≥3类) | 一对一对(OVO)/一对多(OVR)策略 | decisionfunctionshapedecision_function_shapedecisionfunctionshape | SVC(decision_function_shape='ovo'/'ovr') |
三、各类型SVM详解(语法+参数)
1. 硬间隔线性SVM
核心限制
仅适用于严格线性可分数据,无噪声;实际中几乎不用(数据多含噪声),可通过将惩罚系数 CCC 设为极大值(如1e9)近似实现。
语法(sklearn)
from sklearn.svm import SVC
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split
# 生成线性可分数据
X, y = make_blobs(n_samples=100, n_features=2, centers=2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 硬间隔线性SVM(C设为极大值)
hard_svm = SVC(kernel='linear', C=1e9, random_state=42)
hard_svm.fit(X_train, y_train)
y_pred = hard_svm.predict(X_test)
print("硬间隔SVM准确率:", hard_svm.score(X_test, y_test))
2. 软间隔线性SVM
核心改进
引入惩罚系数 CCC:
- C↑C \uparrowC↑:惩罚越重,模型越接近硬间隔(易过拟合);
- C↓C \downarrowC↓:允许更多样本越界(易欠拟合)。
语法(sklearn)
# 软间隔线性SVM(C=1.0为默认值)
soft_svm = SVC(kernel='linear', C=1.0, random_state=42)
soft_svm.fit(X_train, y_train)
# 关键属性
print("支持向量:", soft_svm.support_vectors_) # 输出支持向量坐标
print("支持向量索引:", soft_svm.support_) # 支持向量在训练集中的索引
print("每类支持向量数:", soft_svm.n_support_) # 每类的支持向量数量
3. 非线性SVM(核函数)
核心:核函数选择(关键表格)
| 核函数 | 公式 | 适用场景 | sklearn参数设置 |
|---|---|---|---|
| 线性核 | K(xi,xj)=xi⋅xjK(x_i, x_j) = x_i·x_jK(xi,xj)=xi⋅xj | 线性/近似线性可分数据 | kernel='linear' |
| 多项式核 | K(xi,xj)=(γxi⋅xj+r)dK(x_i, x_j) = (\gamma x_i·x_j + r)^dK(xi,xj)=(γxi⋅xj+r)d | 中等复杂度非线性数据 | kernel='poly' + degree(次数)、gamma、coef0(r) |
| 高斯核(RBF) | $K(x_i, x_j) = exp(-\gamma | x_i - x_j | |
| Sigmoid核 | K(xi,xj)=tanh(γxi⋅xj+r)K(x_i, x_j) = tanh(\gamma x_i·x_j + r)K(xi,xj)=tanh(γxi⋅xj+r) | 类神经网络场景 | kernel='sigmoid' + gamma、coef0(r) |
关键参数说明
- γ\gammaγ:核函数系数,γ↑\gamma \uparrowγ↑ 模型越复杂(易过拟合),γ=′scale′\gamma='scale'γ=′scale′(默认)表示 γ=1/(nfeatures⋅X.var())\gamma=1/(n_{features}·X.var())γ=1/(nfeatures⋅X.var());
- degreedegreedegree:多项式核次数,默认3;
- coef0coef0coef0:多项式/Sigmoid核的常数项,默认0。
语法(sklearn)
# 1. RBF核SVM(最常用)
rbf_svm = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42)
rbf_svm.fit(X_train, y_train)
# 2. 多项式核SVM
poly_svm = SVC(kernel='poly', degree=3, gamma='scale', coef0=0.0, C=1.0, random_state=42)
poly_svm.fit(X_train, y_train)
# 3. Sigmoid核SVM
sigmoid_svm = SVC(kernel='sigmoid', gamma='scale', coef0=0.0, C=1.0, random_state=42)
sigmoid_svm.fit(X_train, y_train)
4. SVM回归(SVR)
核心思想
不再追求分类间隔,而是允许预测值与真实值有 ε\varepsilonε(epsilon)的偏差,目标是最小化间隔 + 惩罚越界样本。
关键参数
- ϵ\epsilonϵ:允许的偏差范围,ϵ↑\epsilon \uparrowϵ↑ 模型越简单;
- 其他参数(C、kernel、gammaC、kernel、gammaC、kernel、gamma)与分类SVM一致。
语法(sklearn)
from sklearn.svm import SVR
from sklearn.datasets import load_diabetes
from sklearn.metrics import mean_absolute_error
# 加载回归数据集
data = load_diabetes()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 线性SVR
linear_svr = SVR(kernel='linear', C=1.0, epsilon=0.1)
linear_svr.fit(X_train, y_train)
y_pred = linear_svr.predict(X_test)
print("线性SVR MAE:", mean_absolute_error(y_test, y_pred))
# RBF核SVR
rbf_svr = SVR(kernel='rbf', C=1.0, gamma='scale', epsilon=0.1)
rbf_svr.fit(X_train, y_train)
5. 多分类SVM
两种策略
- OVO(One-Vs-One,默认):两两类别构建二分类SVM,共 n(n−1)/2n(n-1)/2n(n−1)/2 个模型,预测时投票;
- OVR(One-Vs-Rest):一类对其余所有类构建二分类SVM,共 nnn 个模型,预测时选概率最大类。
语法(sklearn)
from sklearn.datasets import load_iris
from sklearn.metrics import classification_report
# 加载多分类数据集(鸢尾花,3类)
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# OVR策略多分类SVM
multi_svm = SVC(kernel='linear', decision_function_shape='ovr', C=1.0, random_state=42)
multi_svm.fit(X_train, y_train)
y_pred = multi_svm.predict(X_test)
print(classification_report(y_test, y_pred))
四、完整案例实战
案例1:非线性SVM分类(月亮数据集)
目标:对比不同核函数的决策边界,处理非线性可分数据。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
# 1. 生成非线性数据(月亮数据集)
X, y = make_moons(n_samples=200, noise=0.1, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 2. 训练不同核函数的SVM
models = {
"线性核": SVC(kernel='linear', C=1.0, random_state=42),
"RBF核": SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42),
"多项式核(degree=2)": SVC(kernel='poly', degree=2, gamma='scale', random_state=42)
}
# 3. 可视化决策边界
plt.figure(figsize=(15, 5))
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 200), np.linspace(y_min, y_max, 200))
for idx, (name, model) in enumerate(models.items()):
model.fit(X_train, y_train)
score = model.score(X_test, y_test)
# 绘制决策边界
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.subplot(1, 3, idx+1)
plt.contourf(xx, yy, Z, alpha=0.3, cmap=plt.cm.Spectral)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap=plt.cm.Spectral, edgecolors='k')
plt.title(f"{name} (准确率:{score:.2f})")
plt.xlabel("特征1")
plt.ylabel("特征2")
plt.tight_layout()
plt.show()
结果分析
- 线性核:无法拟合月亮数据的非线性边界,准确率约0.8;
- RBF核:完美拟合非线性边界,准确率≈1.0;
- 二次多项式核:拟合效果接近RBF核,准确率≈0.98。
案例2:SVR回归(波士顿房价预测)
from sklearn.svm import SVR
from sklearn.datasets import fetch_california_housing
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
# 1. 加载数据并预处理(SVM对特征缩放敏感)
data = fetch_california_housing()
X, y = data.data, data.target
scaler = StandardScaler() # 特征标准化
X_scaled = scaler.fit_transform(X)
# 2. 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
# 3. 训练SVR
svr = SVR(kernel='rbf', C=10, gamma='scale', epsilon=0.1)
svr.fit(X_train, y_train)
# 4. 评估
y_pred = svr.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"均方误差(MSE):{mse:.2f}")
print(f"决定系数(R²):{r2:.2f}")
结果分析
- SVR对特征缩放敏感,必须先标准化;
- 调整 C=10C=10C=10(增大惩罚)、ϵ=0.1\epsilon=0.1ϵ=0.1 后,R²可达0.8以上,拟合效果较好。
五、关键技巧与注意事项
- 特征缩放:SVM基于距离计算,对特征量纲敏感,必须标准化/归一化;
- 参数调优:
- CCC:平衡“间隔最大化”和“样本越界惩罚”,建议用网格搜索(
GridSearchCV); - γ\gammaγ(RBF核):越大模型越复杂,越小越简单;
- ϵ\epsilonϵ(SVR):根据业务允许的误差范围调整;
- CCC:平衡“间隔最大化”和“样本越界惩罚”,建议用网格搜索(
- 核函数选择:
- 线性/低维数据:线性核(速度快,可解释性强);
- 复杂非线性数据:RBF核(通用性最强);
- 中等复杂度数据:多项式核(需调次数);
- 样本量:SVM在小样本上表现优秀,大样本(>10万)建议用
SGDClassifier(随机梯度下降)或核近似方法。
六、总结
SVM是兼顾理论优美和实践效果的算法,核心优势是小样本下泛化能力强、抗过拟合,缺点是大样本训练慢、对参数和特征缩放敏感。掌握“间隔最大化”核心思想,结合核函数处理非线性问题,配合参数调优,可高效解决分类/回归任务。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)