1 什么是支持向量机
支持向量机(Support Vector Machine,简称SVM )是一种用来解决二分类 问题的机器学习算法,它通过在样本空间中找到一个划分超平面 ,将不同类别的样本分开,同时使得两个点集(两个点集中的支持向量点) 到此平面的最小距离最大 ,### 使得两个点集中的边缘点(支持向量点)到此平面的距离最大---从而使其对误差的容忍度最大 ### 。之所以选择距离最大的超平面是因为距离最大的超平面具有最好的泛化性能。
2 支持向量机分类
1)硬间隔支持向量机
两个类别的样本之间存在着清晰的划分超平面 #### ,对于这种清晰线性可分的任务,我们学习一个线性分类器,
也称为硬间隔支持向量机;
2)软间隔支持向量机
当训练数据数据 #### 近似线性 ####可分时,也学习一个线性的分类器,即软间隔支持向量机;硬间隔支持向量机要求所有的样本均被最佳超平面正确划分,而软间隔支持向量机允许某些样本点不满足间隔大于等于1的条件,当然在最大化间隔的时候也要限制不满足间隔大于等于1的样本的个数使之尽可能的少。于是引入一个惩罚系数C>0,并对每个样本点(xi,yi)引入一个松弛变量(slack variables)ξ≥0
3)非线性支持向量机
当训练数据 #### 线性不可分 #### 时,我们可以通过使用 #### 核技巧 #### 及 #### 软间隔 #### 最大化, #### 学习非线性支持向量机。 原始样本空间中不存在一个能正确划分两类样本的超平面的情况,对于这样的问题可以通过将样本从原始空间映射到特征空间使得样本在映射后的特征空间里线性可分。
3 非线性问题(2.2,2.3)的解决方案
将向量进行维度升级:从低维-->到 高维,参数调试:w向量和常量b,最终会得到一个超平面将数据划分。升维的方式即是将线性方程:wx+b=0中的x编程g(x)函数(x为向量),关键问题是如何确定g()函数:
1)g()是无限维的
2)可以不知道无限维映射g(x)的显式表达式,只要知道一个核函数(Kernel Function):
K(x1,x2)=g(x1)的转置 * g(x2)
那么目标函数的优化式仍然可解
3) 常用核函数
a 高斯径向基函数核 Rbf
b 多项式核 Ploy
c Tanh核
d Linear核(线性核)
4 SVM小结
1)小样本方法,样本量比较少的情况下,有比较好的结果。 原因是:只与支持向量有关系
2)SVM天生适合处理二分类问题
3)二分类问题,按照从简单到复杂的程度可以分为:线性可分、近似线性可分、非线性可分、非线性可分也搞不定。
4) 近似线性可分与非线性可分具有本质区别,千万不能把近似线性可分理解为轻微的非线性。近似线性可分,针对的还是线性可分的问题, 只是由于数据集中个别样本的误差或错误,造成线性分割时个别点会分类判别错误,训练的结果得到的是一个线性分类器。 非线性可分,针对的是非线性分类问题,训练结果得到的是一个非线性分类器。
5) 针对具体问题如何选择线性分类、近似线性分类还是非线性分类?这其实是两个问题。 线性分类与近似线性分类不是非此即彼的对立关系,只是对分类准确性要求的程度差异。 惩罚系数 C>0 就反映了对于分类错误的惩罚程度,C值越大表示对于分类准确性的要求越高,C取无穷大就意味着要求严格线性可分、没有错误分类。选择线性分类模型,如果对训练样本或检验样本进行分类判断的错误率很高(score 低),就要考虑使用非线性模型进行分类了。
6)核函数的选择,这是一个非常复杂而且没有标准答案的问题。SVC() 和 NuSVC() 都提供了核函数 'linear','poly','rbf','sigmoid','precomputed' 可供选择。
7)推荐使用 'poly' 和'rbf' 核函数,优先选择 'poly' 多项式核函数。
8)使用 'poly' 核函数时,推荐选择 degree=2、degree=3 分别试试。
5 sklearn api
SVC 和 NuSVC 都可以使用核函数方法实现非线性分类,但参数设置有所区别。
对于多类别分类问题,通过构造多个"one-versus-one"的二值分类器逐次分类。
NuSVC() 类的主要参数:
kernel :
{'linear', 'poly', 'rbf', 'sigmoid', 'precomputed'},
default='rbf' 设定核函数,
'linear':线性核函数,
'poly':多项式核函数,
'rbf':高斯核函数,
'sigmoid':S形核函数,
'precomputed':自定义核。
默认值为 'rbf'
nu :float, default=0.5 训练错误率的上限,也即支持向量的百分比下限。默认值0.5,取值范围(0,1]。
degree :int, default=3 多项式核函数的次数,默认值为 3。其它核函数时不适用。
gamma :{'scale', 'auto'} or float, default='scale' 'rbf','poly' 和 'sigmoid' 核函数的参数选择方式。
coef0 :float, default=0.0 'poly' 和 'sigmoid' 核函数的参数。
class_weight :dict or 'balanced', default=None 特征变量的加权系数。用于为某个特征变量设权重,默认所有特征变量的权重相同。
probabilitybool:default=False 是否启用概率估计。默认值 False:不启用。
NuSVC() 类的参数有两类:
一类是针对模型训练的通用参数,对所有核函数都适用,例如 nu、tol、max_iter;
另一类是针对特定的核函数,只对某种核函数有效,并不适用于其它核函数, 例如 degree 只适用于 'poly'核函数,coef0 只适用于'poly' 和 'sigmoid' 核函数, 而且在 'poly' 和 'sigmoid' 核函数中的含义也不相同。
NuSVC() 类的主要方法:
1、 fit(X, y[, sample_weight]) 用样本集的数据(X,y)训练 SVM 模型。
2、get_params([deep]) 获取模型参数。注意不是指分类模型的系数,而是指kernel,
nu,class_weight等训练的设置参数。
3、decision_function(X) 由SVM模型计算 X 的决策函数值,即样本 X 到分离超平面的距离。注意不是分类判别结果。
4、 predict(X) 用训练好的 SVM 模型预测数据集 X 的分类判别结果,如0/1。
5、score(X,y[,sample_weight]) 评价指标,对训练样本集 X 的分类准确度。
6 实例
python
# skl_SVM_v1b.py
# Demo of nonlinear SVM by scikit-learn
# v1.0b: 线性可分支持向量机模型(SciKitLearn)
# Copyright 2021 YouCans, XUPT
# Crated:2021-05-15
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVC, NuSVC, LinearSVC
from sklearn.datasets import make_moons
# 数据准备:生成训练数据集,生成等高线网格数据
X, y = make_moons(n_samples=100, noise=0.1, random_state=27) # 生成数据集
x0s = np.linspace(-1.5, 2.5, 100) # 创建等差数列,从 start 到 stop,共 num 个
x1s = np.linspace(-1.0, 1.5, 100) # start, stop 根据 Moon 数据范围选择确定
x0, x1 = np.meshgrid(x0s, x1s) # 生成网格点坐标矩阵
Xtest = np.c_[x0.ravel(), x1.ravel()] # 返回展平的一维数组
# SVC 建模,训练和输出
modelSVM1 = SVC(kernel='poly', degree=3, coef0=0.2) # 'poly' 多项式核函数
modelSVM1.fit(X, y) # 用样本集 X,y 训练支持向量机 1
yPred1 = modelSVM1.predict(Xtest).reshape(x0.shape) # 用模型 1 预测分类结果
# NuSVC 建模,训练和输出
modelSVM2 = NuSVC(kernel='rbf', gamma='scale', nu=0.1) # 'rbf' 高斯核函数
modelSVM2.fit(X, y) # 用样本集 X,y 训练支持向量机 2
yPred2 = modelSVM2.predict(Xtest).reshape(x0.shape) # 用模型 2 预测分类结果
fig, ax = plt.subplots(figsize=(8, 6))
ax.contourf(x0, x1, yPred1, cmap=plt.cm.brg, alpha=0.1) # 绘制模型1 分类结果
ax.contourf(x0, x1, yPred2, cmap='PuBuGn_r', alpha=0.1) # 绘制模型2 分类结果
ax.plot(X[:, 0][y == 0], X[:, 1][y == 0], "bo") # 按分类绘制数据样本点
ax.plot(X[:, 0][y == 1], X[:, 1][y == 1], "r^") # XUPT
ax.grid(True, which='both')
ax.set_title("Classification of moon data by LinearSVM")
plt.show()
# 以上程序分别用SVC()类、NuSVC()类建模,并且使用了不同的核函数。
# 如果使用相同的核函数、模型参数, SVC()类、NuSVC()类的模型训练结果是一致的,但参数、属性和方法的定义存在差异。
# 图中分类结果的差异,不是使用SVC()类、NuSVC()类所导致的,而是使用不同的核函数和模型参数的结果。
# SVC()类、NuSVC()类的参数都有两种,一类是针对模型训练的通用参数,另一类是针对特定的核函数,只对某种核函数有效,并不适用于其它核函数。
# 例如,degree、coef0都是针对多项式核函数的专用参数,nu、gamma则是NuSVC()学习算法的通用参数。