支持向量机模型 0基础小白也能懂(附代码)
支持向量机模型 0基础小白也能懂(附代码)
支持向量机(SVM)是一种在机器学习领域具有重要影响力的算法,尤其在处理中小型数据集时表现出色。本文将从零开始,详细讲解SVM的基本概念、数学原理以及实际应用,适合对机器学习感兴趣但缺乏系统了解的读者。
什么是支持向量机模型
支持向量机学习方法,针对不同的情况,有由简至繁的不同模型:
- 线性可分支持向量机:训练数据线性可分的情况下,通过硬间隔最大化,学习一个线性的分类器。
- 线性支持向量机:训练数据近似线性可分的情况下,通过软间隔最大化,学习一个线性的分类器。
- 非线性支持向量机:训练数据线性不可分的情况下,通过使用核技巧及软间隔最大化,学习非线性分类器。
支持向量机可以借助核技巧完成复杂场景下的非线性分类。核函数是一种将低维数据映射到高维空间的方式,以便在高维空间中处理复杂的非线性问题。
最大间隔分类器
分类问题与线性模型
分类问题是监督学习的一个核心问题。在监督学习中,当输出变量取有限个离散值时,预测问题便成为分类问题。实际生活中,有很多问题的本质都是分类,如文本分类、图像识别等。
最大间隔分类器
在分类问题中,不同的模型会有不同的处理方式。支持向量机要求找到鲁棒性最高、稳定性最好的决策边界,这个边界与两侧最近的数据点保持最大距离,具有最强的容错性。
在这个决策边界中,位于红色和蓝色线上的数据点被称为支持向量。决策边界表示为(f(x)=w*x+b),其中(w)和(x)是向量。当(f(x)>0)时,(sgn(f(x))=+1);当(f(x)<0)时,(sgn(f(x))=-1)。
支持向量机详解
线性可分 SVM 与硬间隔最大化
我们要找到把下图中红蓝两色的图标点分开的最优分界线。令红色的图标点(=+1),蓝色的图标的点(=-1),直线(f(x)=w*x+b)。
间隔(M)的计算公式为:(M=\frac{2}{||w||})。
SVM 要求解能够正确划分训练数据集并且「几何间隔」最大的分离超平面。如下图所示,(w*x+b)即为分离超平面。
几何间隔
SVM 模型的「求解最大分割超平面问题」可以表示为约束最优化问题。通过拉格朗日乘子(\alpha_i)的引入,约束条件(y_i(w*x_i+b)\geq1)被融入到目标函数中,而不再是外部的约束条件。这使得我们可以用标准的优化方法来处理它。
对偶算法
求解线性可分支持向量机的最优化问题,我们很多时候会将它转化为对偶问题(dual problem)来求解,也就是应用「拉格朗日对偶性」。这样做有一些优点:
- 对偶问题往往更容易求解。
- 引入自然核函数,进而可以推广到非线性分类问题。
线性 SVM 与软间隔最大化
在实际应用中,完全线性可分的情况很少见。如下图就是一个典型的线性不可分的分类图。
要对其进行切分,有2种方案:
- 当C很大的时候,分错的点就会更少,但是过拟合的情况可能会比较严重。
- 当C很小的时候,分错的点可能会很多,不过可能由此得到的模型也会不太正确。
同样求解一个拉格朗日对偶问题,就能得到原问题的对偶问题的表达式。
非线性 SVM 与核函数
如果我们要处理的分类问题更加复杂,甚至不能像上面一样近似线性可分呢,这种情况下找到的超平面分错的程度太高不太可接受。对于这样的问题,一种解决方案是将样本从原始空间映射到一个更高维的特征空间(希尔贝特空间),使得样本在这个特征空间内线性可分,然后再运用 SVM 求解,如下图所示:
回忆一下之前得到的对偶问题表达式如下,做一点小小的改造,令:(x_i^Tx_j=k(s_i,x_j)),这个式子所做的事情就是将线性的空间映射到高维的空间,(x_i^Tx_j=k(s_i,x_j))有很多种右下是比较典型的两种,上面的是多项式核,下面的是高斯径向基核,高斯核甚至是将原始空间映射为无穷维空间,另外核函数有一些比较好的性质,比如说不会比线性条件下增加多少额外的计算量,等等,此处我们不深入。对于一个问题,不同的核函数可能会带来不同的结果,我们需要做一些尝试来支撑选择(关于这个部分,大家可以看最下方的 python 实现部分)。:
SVM 总结
不同的核函数需要指定不同的参数:
- 针对线性函数,只需要指定参数(C),它表示对不符合最大间距规则的样本的惩罚力度。
- 针对多项式核函数,除了参数(C)外,还需要指定degree,它表示多项式的阶数。
- 针对高斯核函数,除了参数(C)外,还需要指定gamma值,这个值对应的是高斯函数公式中(\frac{1}{2\sigma^2})的值。
实现代码
不同的核函数需要指定不同的参数。针对线性函数,只需要指定参数(C),它表示对不符合最大间距规则的样本的惩罚力度。针对多项式核函数,除了参数(C)外,还需要指定degree,它表示多项式的阶数。针对高斯核函数,除了参数(C)外,还需要指定gamma值,这个值对应的是高斯函数公式中(\frac{1}{2\sigma^2})的值。
先来看看线性函数
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm, datasets
iris = datasets.load_iris()
X = iris.data[:, :2] #只取前两维特征,方便可视化
y = iris.target
svc = svm.SVC(kernel='linear', C=1).fit(X, y)
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min) / 100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
plt.subplot(1, 1, 1)
Z = svc.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Paired)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('SVC with linear kernel')
plt.show()
结果如下,分成了三块,分离超平面为交界线
我们再使用多项式核函数,改成
svc = svm.SVC(kernel='poly', degree=3).fit(X, y)
结果如下
再换成高斯核函数,改成
svc = svm.SVC(kernel='rbf', C=1).fit(X, y)
结果如下
其中的C是错误项的惩罚参数C。它还控制平滑决策边界和正确分类训练点之间的权衡。
下面是c=10,100,1000的结果
gamma 值越大,SVM 就会倾向于越准确的划分每一个训练集里的数据,这会导致泛化误差较大和过拟合问题,先把gamma设置成1,
svc = svm.SVC(kernel='rbf', C=1, gamma=1).fit(X, y)
结果如下
下面是gamma参数改为10和100的结果,可以看到越来越拟合。
再把gamma加到1000的时候已经过拟合了。