SVM(支持向量机)是一种常用的机器学习算法,主要用于分类问题,但是也可以扩展做回归任务。

SVM的主要思想是:

  1. 将样本映射到高维空间中,转换为线性可分问题
  2. 在高维空间中,存在很多分隔超平面可以将不同类样本完全分开。SVM试图找到这些超平面的最优解,即最大间隔超平面,这样可以获得最佳的分类 GENERALIZATION(泛化)能力。
  3. 最大间隔超平面可以由支持向量决定,而支持向量就是离分隔超平面最近的样本点。
  4. 通过核函数,SVM可以隐式地实现高维映射,并建立优化问题求解最大间隔超平面, thus分类模型。

SVM决策超平面的推导过程:

设训练样本为\(\{(x_1, y_1), (x_2, y_2), \cdots, (x_n, y_n)\}\),其中\(x_i \in \mathbb{R}^d\),\(y_i \in \{-1,+1\}\)

SVM的目标是找到一个分类超平面:

\[w^Tx + b = 0\]

将两类样本完全分开,且间隔尽可能大。

定义样本\(x_i\)到超平面的函数间隔为:

\[d_i = \frac{|w^Tx_i + b|}{||w||}\]

则求最大间隔等价于最小化\(||w||\),满足约束:

\[y_i(w^Tx_i + b) \geq 1, i=1,2,\cdots,n\]

即解决以下优化问题:

\[\min\limits_{w,b} \frac{1}{2}||w||^2\]

\[\text{s.t. } y_i(w^Tx_i + b) \geq 1, i=1,2,\cdots,n\]

引入拉格朗日乘子\(\alpha_i \geq 0\),构建拉格朗日函数:

\[L(w,b,\alpha) = \frac{1}{2}||w||^2 - \sum\limits_{i=1}^{n}{\alpha_i[y_i(w^Tx_i + b) - 1]}\]

\(w,b\)的偏导数等于0可得:

\[w = \sum\limits_{i=1}^{n}{\alpha_i y_i x_i}\]

\[\sum\limits_{i=1}^{n}{\alpha_i y_i} = 0\]

\(w\)代回原问题,得到对偶问题:

\[\max\limits_{\alpha} \sum\limits_{i=1}^{n}{\alpha_i} - \frac{1}{2}\sum\limits_{i,j=1}^{n}{\alpha_i \alpha_j y_i y_j (x_i \cdot x_j)}\]

\[\text{s.t. } \alpha_i \geq 0, \sum\limits_{i=1}^{n}{\alpha_i y_i} = 0\]

求解得到\(\alpha\),则最大间隔超平面为:

\[w = \sum\limits_{i=1}^{n}{\alpha_i y_i x_i}\] \[b = \frac{1}{y_i} - w \cdot x_i, \text{对任一支持向量}i\]

将输入样本映射到高维特征空间。SVM试图在高维空间中找到一个最优分类超平面,以获得最佳的分类效果。

通过核函数实现了从低维到高维的隐式映射。常见的核函数有线性核、多项式核、Gauss核(RBF核)等。

通过求解对偶问题,只需要输入数据的内积,而输入数据的高维映射可以通过核函数实现。

这样就可以在低维输入空间构建最优分隔超平面,而实际上是在高维特征空间实现,从而处理非线性分类问题。

常见的Gauss RBF核将输入映射到无穷维,可以看成在高维空间构建一个泛化能力最强的分类模型。

核技巧扩展了SVM的适用范围,使其不仅适用于线性可分问题,也可用于复杂的非线性分类问题。

通过选择不同的核函数,可以灵活地处理各种类型的数据集。

核技巧是SVM强大的原因之一,它寻求高维映射以求分类的最优解,却只需要计算低维数据的内积, thus有效实现了“维度灾难”的解决。


以下是一个在二维求解决策平面的代码示例:

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
30
31
32
33
34
35
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm

# 生成样本数据
np.random.seed(0)
X = np.r_[np.random.randn(20, 2) - [2, 2], np.random.randn(20, 2) + [2, 2]]
y = [0] * 20 + [1] * 20

# 拟合SVM模型
clf = svm.SVC(kernel='linear')
clf.fit(X, y)

# 绘制样本点
plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)

# 绘制决策边界
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()

# 创建网格采样点
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = clf.decision_function(xy).reshape(XX.shape)

# 绘制决策边界
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])

# 绘制支持向量
ax.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=100, linewidth=1, facecolors='none',
edgecolors='k')
plt.show()

pC7xzjJ.png

在这个例子中,我们先随机生成了两类二维样本数据,然后训练一个线性核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
30
31
32
33
34
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm

# 生成一个环形分布的数据集
np.random.seed(1)
X = np.vstack((np.random.randn(150, 2) + [1, 2],
np.random.randn(150, 2) - [1, 2]))
y = [0] * 150 + [1] * 150

# 使用RBF核的SVM
clf = svm.SVC(kernel='rbf')
clf.fit(X, y)

# 绘制样本点
plt.scatter(X[:, 0], X[:, 1], c=y, s=30, cmap=plt.cm.Paired)

# 绘制决策边界
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()

# 创建网格采样点
xx, yy = np.meshgrid(np.linspace(xlim[0], xlim[1], 200),
np.linspace(ylim[0], ylim[1], 200))

Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

ax.contourf(xx, yy, Z, alpha=0.75, cmap=plt.cm.Paired)
ax.set_xlim(xlim)
ax.set_ylim(ylim)

plt.show()

pC7z14f.png

通过构造一个环形分布的二维非线性数据,然后使用RBF核的SVM进行建模。可以看到SVM学会了一个非线性的决策边界将两类不同程度的区分开。


生成了200个样本的二维数据集,然后进行了三维可视化。通过升维操作,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
30
31
32
33
34
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn.svm import SVC

# 生成二维非线性可分数据集
np.random.seed(100)
X1 = np.random.randn(100, 2) + [2, 2]
X2 = np.random.randn(100, 2) - [2, 2]
X = np.vstack((X1, X2)).astype(np.float32)
y = np.array([0] * 100 + [1] * 100)

# 升维到三维
X_3d = np.hstack((X, (X[:, 0]**2 + X[:, 1]**2)[:, None]))

# 三维可视化
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X_3d[:, 0], X_3d[:, 1], X_3d[:, 2], c=y, s=10, cmap=plt.cm.Spectral)

# 在三维空间构建最大间隔超平面
clf = SVC(kernel='linear')
clf.fit(X_3d, y)

# 绘制三维决策平面
x1_min, x1_max = X[:, 0].min(), X[:, 0].max()
x2_min, x2_max = X[:, 1].min(), X[:, 1].max()
x1, x2 = np.mgrid[x1_min:x1_max:200j, x2_min:x2_max:200j]
x_grid = np.stack((x1.ravel(), x2.ravel(), x1.ravel() ** 2 + x2.ravel() ** 2), axis=1)
y_hat = clf.decision_function(x_grid)
y_grid = y_hat.reshape((200, 200))
ax.plot_surface(x1, x2, y_grid, alpha=0.5)

plt.show()

pCHSwsH.png

SVM(支持向量机)的主要思想和实现方法可以概括如下:

  1. 思想:SVM试图找到一个最优分类超平面,使不同类样本 Reality隔的边界尽可能大,从而获得最佳的 GENERALIZATION能力。

  2. 实现:将样本映射到高维特征空间,转换为线性可分问题。在高维空间中求解最大间隔超平面作为决策面。

  3. 优化目标:构建约束优化问题,最小化||w||并满足分类约束。求解得到最优w和b确定超平面。

  4. 对偶问题:引入拉格朗日乘子α,将原问题转换为对偶问题,求解α即可得到最优超平面。

  5. 核技巧:通过核函数计算输入样本的内积,实现高维映射。常用核有线性核、多项式核、Gauss RBF核等。

  6. 模型参数:主要就是支持向量及对应的α。决策函数只依赖支持向量。

  7. 实现方法:一般通过求解相应的凸二次规划问题获得最优α,然后求出w,b。常用SMO算法加速训练。

  8. 应用:可处理线性和非线性分类问题。还可以扩展到回归任务。

SVM通过间隔最大化寻求最佳分类超平面,核技巧实现高维映射,是一种流行的分类与回归方法。