概述
支持向量机(SVM)功能非常强大,应用广泛,在深度学习诞生之前,广泛的应用于手写识别数字和人脸识别
在监督学习中,它可以解决线性,非线性二分类以及多分类,普通,概率连续型变量的回归
也可以用于无监督学习中支持向量聚类和异常值检测
SVM如何进行分类
简单解释就是:在数据分布中找到一个超平面作为决策边界,使模型在数据上的分类误差尽量小,尤其是在未知数据集上的泛化五误差小
超平面
定义:一个空间的超平面是比该空间少一个维度的子空间
比如一个三维空间,那么它的超平面就是在该空间内的一个二维平面;一个二维平面,那么它的超平面就是该平面内的一条一维直线
决策边界的边际
我们将超平面作为决策边界,但是在一个分类中我们可能有多个决策边界(也就是说可以找到多个超平面使数据集的分类达到最好),我们应该怎么样找到那个可以在未知的数据集上最可能表现优异的边界呢?
我们引入决策边界的边际
下面拿二分类中二维平面的超平面——一维直线作为例子讲解
我们将超平面平移——也就是平行线(例子)平移,让它刚好碰到两个分类中最近的数据——这样会出现两条新的线——我们把这两条直线的距离叫做决策边界的边际
通过严格的数学证明,我们可以得出以下结论:
拥有更大边际的决策边界在分类中的泛化误差更小,所以SVM就是通过找到边际最大的决策边际,来对数据进行分类的分类器
线性SVM决策过程
我们来看到这个数据集:
from sklearn.datasets import make_blobs
from sklearn.svm import SVC
import matplotlib.pyplot as plt
import numpy as np
X, y = make_blobs(n_samples=60, centers=2, random_state=0, cluster_std=0.6)
# 创建数据集
# 可视化
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap="rainbow")
# 刻度
plt.xticks([])
plt.yticks([])
plt.show()
然后我们开始绘制决策边界:
# 首先要有散点图
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap="rainbow")
ax = plt.gca() # 获取当前的子图,如果不存在,则创建新的子图
xlim = ax.get_xlim() # 获取当前的刻度
ylim = ax.get_ylim() # 默认创建(0.0, 1.0)范围内的横纵坐标
# 要画决策边界,必须要有网格
axisx = np.linspace(xlim[0], xlim[1], 30)
axisy = np.linspace(ylim[0], ylim[1], 30)
axisy, axisx = np.meshgrid(axisy, axisx)
# 将特征向量转换为特征矩阵的函数
# 核心是将两个特征向量广播,以便获取y.shape * x.shape这么多个坐标点的横坐标和纵坐标
xy = np.vstack([axisx.ravel(), axisy.ravel()]).T
# 获取y.shape * x.shape这么多个坐标点
# 其中ravel()是降维函数,vstack能够将多个结构一致的一维数组按行堆叠起来
# xy就是已经形成的网络,它是遍布在整个画布上的密集的点
# 使用支持向量机进行模型训练——也就是找到决策边界的过程
clf = SVC(kernel="linear").fit(X, y)
P = clf.decision_function(xy).reshape(axisx.shape)
# 重要接口decision_function,返回每个输入的样本所对应的到决策边界的距离
# 然后再将这个距离转换为axisx的结构
# 画决策边界和平行于决策边界的超平面
ax.contour(axisx, axisy, P, colors="k", levels=[-1, 0, 1], alpha=0.5, linestyles=["--", "-", "--"])
ax.set_xlim(xlim)
ax.set_ylim(ylim)
plt.show()
对于上面的代码我们可以粗略的理解为绘制超平面和决策边界的边际的过程,只是为了可视化所以代码比较长
我们可以看到三条线,中间实线就是超平面,两旁的虚线就是决策边界的边际
如果在非线性的图中,我们使用线性SVM来找超平面,得到的结果就不对了
比如这组数据:
很明显我们需要的决策边界应该是一个圆环,但是如果我们使用上面的代码,我们只能得到以下bad的决策边界
这时候我们应该给数据多加一个维度,在更高的维度找到合适的超平面
clf = SVC(kernel="linear").fit(X, y)
这时线性的SVC已经无法满足了,所以我们应该要更换核函数了
核函数
选用不同的核函数,可以解决不同数据分布下的寻找超平面问题。
核函数的选择由kernel参数和其他一些参数控制
四个核函数:
- linear:线性核函数
- poly:多项式核函数
- sigmoid:双曲正切核函数
- rbf:高斯径向核函数
相关参数:(后面列的核函数说明该核函数可以使用该参数)
- gamma : poly sigmoid rbf 浮点数默认“auto”
- degree : poly 核函数的指数
- coef0 : poly sigmoid 浮点数 默认0.0
可以知道rbf核函数在线性和非线性数据的表现都不错,所以我们选择核函数时首先选择的是高斯径向核函数
一般结论:
- 线性核函数(linear, ploy——degree=1),尤其是多项式核函数在高次项计算非常缓慢
- rbf, 多项式核函数不擅长处理量纲不统一的数据
这里就体现了数据预处理和特征工程的重要性!
软间隔与硬间隔
当两组数据完全线性可分,就是可以找到一个决策边界使得训练集上的分类误差为0,那么这两组数据是存在“硬间隔”的,当两组数据找不到那么一个决策边界使得其分类误差为0,但是误差较小,则说他们存在“软间隔”
参数C
当数据为软间隔时,我们的决策边界就不是追求最大的边际了,因为这会导致被分错的样本更多,我们使用参数C来权衡正确分类率和决策边界的边际最大这两个目标,找出最佳的结果
- C:浮点数,默认1,必须大于等于0
通常我们使用网格搜索来确定这一系列参数的最佳取值
感谢您的耐心阅读!