支持向量机(SVM)详解
支持向量机(SVM)详解
什么是支持向量机
支持向量机(Support Vector Machine,SVM)是一种强大的分类和回归算法。它的核心思想是找到一个最优的决策边界(超平面),使得不同类别之间的间隔(margin)最大化。
最大间隔分类
SVM的目标是找到一个超平面,使得:
- 所有样本被正确分类
- 距离超平面最近的样本(支持向量)到超平面的距离最大化
间隔的数学定义:
$$margin = \frac{2}{||w||}$$
其中 $w$ 是超平面的法向量。
核函数技巧
对于线性不可分的数据,SVM使用核函数将数据映射到高维空间:
常用核函数
| 核函数 | 公式 | 适用场景 |
|---|---|---|
| 线性核 | $K(x,y) = x^T y$ | 线性可分数据 |
| 多项式核 | $K(x,y) = (x^T y + c)^d$ | 多项式关系 |
| RBF核 | $K(x,y) = e^{-\gamma | |
| Sigmoid核 | $K(x,y) = \tanh(\alpha x^T y + c)$ | 神经网络类似 |
软间隔
在实际应用中,数据往往不完全线性可分。软间隔允许一些样本违反间隔约束:
$$\min \frac{1}{2}||w||^2 + C\sum_{i=1}^{n}\xi_i$$
其中 $C$ 是惩罚参数:
- $C$ 越大,对错误分类的惩罚越大
- $C$ 越小,允许更多的分类错误
代码示例:SVM分类与回归
import numpy as np
from sklearn.datasets import load_iris, make_moons
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC, SVR
from sklearn.metrics import accuracy_score, classification_report
import warnings
warnings.filterwarnings('ignore')
# --- 分类任务 ---
print("=== SVM分类 ===")
# 加载数据
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, stratify=y
)
# 数据标准化(SVM对尺度敏感)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 不同核函数比较
kernels = ['linear', 'rbf', 'poly']
print("\n不同核函数性能:")
for kernel in kernels:
svm = SVC(kernel=kernel, random_state=42)
svm.fit(X_train_scaled, y_train)
acc = accuracy_score(y_test, svm.predict(X_test_scaled))
n_support = sum(svm.n_support_)
print(f" {kernel:8} | 准确率: {acc:.4f} | 支持向量数: {n_support}")
# RBF核的参数调优
print("\n=== RBF核参数调优 ===")
param_grid = {
'C': [0.1, 1, 10, 100],
'gamma': ['scale', 'auto', 0.1, 1]
}
grid_search = GridSearchCV(
SVC(kernel='rbf', random_state=42),
param_grid, cv=5, scoring='accuracy', n_jobs=-1
)
grid_search.fit(X_train_scaled, y_train)
print(f"最佳参数: {grid_search.best_params_}")
print(f"最佳CV分数: {grid_search.best_score_:.4f}")
best_svm = grid_search.best_estimator_
test_acc = accuracy_score(y_test, best_svm.predict(X_test_scaled))
print(f"测试集准确率: {test_acc:.4f}")
# 详细分类报告
print("\n=== 分类报告 ===")
y_pred = best_svm.predict(X_test_scaled)
print(classification_report(y_test, y_pred, target_names=iris.target_names))
# --- 非线性数据分类 ---
print("\n=== 非线性数据分类 ===")
X_moon, y_moon = make_moons(n_samples=200, noise=0.15, random_state=42)
X_m_train, X_m_test, y_m_train, y_m_test = train_test_split(
X_moon, y_moon, test_size=0.3, random_state=42
)
scaler_m = StandardScaler()
X_m_train_scaled = scaler_m.fit_transform(X_m_train)
X_m_test_scaled = scaler_m.transform(X_m_test)
for kernel in ['linear', 'rbf', 'poly']:
svm_moon = SVC(kernel=kernel, C=1.0, random_state=42)
svm_moon.fit(X_m_train_scaled, y_m_train)
acc = accuracy_score(y_m_test, svm_moon.predict(X_m_test_scaled))
print(f" {kernel:8} | 准确率: {acc:.4f}")
# --- 回归任务 ---
print("\n=== SVM回归 (SVR) ===")
from sklearn.datasets import make_regression
from sklearn.metrics import mean_squared_error, r2_score
X_reg, y_reg = make_regression(n_samples=200, n_features=1, noise=10, random_state=42)
X_r_train, X_r_test, y_r_train, y_r_test = train_test_split(
X_reg, y_reg, test_size=0.2, random_state=42
)
scaler_r = StandardScaler()
X_r_train_scaled = scaler_r.fit_transform(X_r_train)
X_r_test_scaled = scaler_r.transform(X_r_test)
svr = SVR(kernel='rbf', C=1.0, epsilon=0.1)
svr.fit(X_r_train_scaled, y_r_train)
y_r_pred = svr.predict(X_r_test_scaled)
print(f"R²分数: {r2_score(y_r_test, y_r_pred):.4f}")
print(f"MSE: {mean_squared_error(y_r_test, y_r_pred):.4f}")
SVM的优缺点
优点:
- 在高维空间表现优秀
- 内存效率高(只用支持向量)
- 对过拟合有较好的抵抗力
- 核函数灵活处理非线性问题
缺点:
- 对大规模数据训练速度慢
- 对参数和核函数选择敏感
- 对缺失数据敏感
- 结果不易解释
总结
SVM是一种理论基础扎实、分类效果优秀的算法。在中小规模数据集、高维特征场景下表现尤为出色。理解SVM的原理有助于深入理解机器学习的数学基础。