SVM支持向量机详解:从间隔最大化到核技巧
支持向量机(Support Vector Machine,SVM)是机器学习中最优雅的算法之一,通过最大化分类间隔来实现良好的泛化能力。
线性可分SVM
SVM的核心思想是找到一个超平面,使得两类样本之间的间隔最大:
$$\max_{\mathbf{w}, b} \frac{2}{|\mathbf{w}|} \quad \text{s.t.} \quad y_i(\mathbf{w}^T\mathbf{x}_i + b) \geq 1$$
等价于:
$$\min_{\mathbf{w}, b} \frac{1}{2}|\mathbf{w}|^2 \quad \text{s.t.} \quad y_i(\mathbf{w}^T\mathbf{x}_i + b) \geq 1$$
手动实现线性SVM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import numpy as np
class LinearSVM: def __init__(self, lr=0.001, lambda_param=0.01, n_iters=1000): self.lr = lr self.lambda_param = lambda_param self.n_iters = n_iters
def fit(self, X, y): n_samples, n_features = X.shape y_ = np.where(y <= 0, -1, 1)
self.w = np.zeros(n_features) self.b = 0
for _ in range(self.n_iters): for idx, x_i in enumerate(y_): condition = y_[idx] * (np.dot(x_i, self.w) + self.b) >= 1 if condition: self.w -= self.lr * (2 * self.lambda_param * self.w) else: self.w -= self.lr * (2 * self.lambda_param * self.w - np.dot(x_i, y_[idx])) self.b -= self.lr * y_[idx] return self
def predict(self, X): linear_output = np.dot(X, self.w) + self.b return np.sign(linear_output)
|
软间隔与C参数
当数据不完全线性可分时,引入松弛变量:
$$\min \frac{1}{2}|\mathbf{w}|^2 + C\sum_{i=1}^{n}\xi_i$$
C参数控制间隔与分类错误的权衡:
- C大:更关注分类正确,可能过拟合
- C小:更关注间隔最大化,可能欠拟合
核技巧
核技巧是SVM处理非线性问题的关键。通过将数据映射到高维空间,使其在高维空间线性可分:
1 2 3 4 5 6 7 8 9 10 11 12 13
| from sklearn.svm import SVC
svm_linear = SVC(kernel='linear', C=1.0)
svm_poly = SVC(kernel='poly', degree=3, C=1.0)
svm_rbf = SVC(kernel='rbf', gamma='scale', C=1.0)
svm_sigmoid = SVC(kernel='sigmoid', C=1.0)
|
常见核函数
线性核
$$K(\mathbf{x}_i, \mathbf{x}_j) = \mathbf{x}_i^T\mathbf{x}_j$$
多项式核
$$K(\mathbf{x}_i, \mathbf{x}_j) = (\gamma\mathbf{x}_i^T\mathbf{x}_j + r)^d$$
RBF核
$$K(\mathbf{x}_i, \mathbf{x}_j) = \exp(-\gamma|\mathbf{x}_i - \mathbf{x}_j|^2)$$
1 2 3 4 5
| def rbf_kernel(X1, X2, gamma=1.0): """手动实现RBF核""" sq_dist = np.sum(X1**2, axis=1).reshape(-1, 1) + \ np.sum(X2**2, axis=1) - 2 * np.dot(X1, X2.T) return np.exp(-gamma * sq_dist)
|
SVM回归(SVR)
SVM也可以用于回归任务:
1 2 3 4 5
| from sklearn.svm import SVR
svr = SVR(kernel='rbf', C=1.0, epsilon=0.1) svr.fit(X_train, y_train) y_pred = svr.predict(X_test)
|
参数调优
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from sklearn.model_selection import GridSearchCV from sklearn.datasets import load_iris
iris = load_iris() X, y = iris.data, iris.target
param_grid = { 'C': [0.1, 1, 10, 100], 'gamma': ['scale', 'auto', 0.001, 0.01, 0.1], 'kernel': ['rbf', 'poly', 'sigmoid'] }
grid_search = GridSearchCV(SVC(), param_grid, cv=5, scoring='accuracy') grid_search.fit(X, y)
print(f"Best parameters: {grid_search.best_params_}") print(f"Best score: {grid_search.best_score_:.4f}")
|
SVM的优缺点
优点:
- 在高维空间表现良好
- 核技巧有效处理非线性问题
- 通过最大化间隔获得良好的泛化能力
- 决策函数只依赖支持向量,内存效率高
缺点:
- 训练时间复杂度O(n²)到O(n³),不适合大规模数据
- 对参数选择敏感
- 不直接提供概率估计
总结
SVM通过最大化间隔和核技巧,在中小规模数据集上表现优异。理解间隔最大化、软间隔和核技巧是掌握SVM的关键。虽然在大数据场景下不如深度学习灵活,但SVM仍然是机器学习工具箱中不可或缺的算法。