10- SVM支持向量机 (SVC) (机器学习)

news2024/9/21 22:49:06
  • 支持向量机(support vector machines,SVM)是一种二分类算法,它的目的是寻找一个超平面来对样本进行分割,分割的原则是间隔最大化,如果对应的样本特征少,一个普通的 SVM 就是一条线将样本分隔开,但是要求线到两个类别最近样本点的距离要最大。
  • 支持向量机模型:
from sklearn import svm
clf_linear = svm.SVC(kernel='linear')   # kernel = 'linear'
clf_linear.fit(X_train,y_train)
score_linear = clf_linear.score(X_test,y_test)

clf_poly = svm.SVC(kernel='poly')      # kernel = 'poly'
clf_poly.fit(X_train,y_train)
score_poly = clf_poly.score(X_test,y_test)
  • 网格搜索最佳参数:
svc = SVC()
params = {'C':np.logspace(-3,1,20),'kernel':['rbf','poly','sigmoid','linear']}
gc = GridSearchCV(estimator = svc,param_grid = params)
gc.fit(X_train_pca,y_train)


1.1 原理简介

支持向量机(support vector machines,SVM)是一种二分类算法,它的目的是寻找一个超平面来对样本进行分割,分割的原则是间隔最大化,如果对应的样本特征少,一个普通的 SVM 就是一条线将样本分隔开,但是要求线到两个类别最近样本点的距离要最大。

        就是在寻找一个最优的决策边界(上图中的两条虚线)来确定分类线b,所说的支持向量就是距离决策边界最近的点(上图中p1、p2、p3点,只不过边界穿过了这些点)。如果没有这些支持向量点,b线的位置就要改变,所以SVM就是根据这些支持向量点来最大化margin,来找到了最优的分类线(machine,分类器),这也是SVM分类算法名称的由来。

1.2 构建SVM目标函数

        接着上面的分类问题来分析,假设支持向量机最终要找的线是 \bg_white \small l_2,决策边界两条线是l_1l_3​,那么假设 l_2 ​的方程为 w^T.x+b=0,这里w表示 (w_1,w_2 )^T,x表示 (x_1,x_2 )^T,我们想要确定 l_2 直线,只需要确定w和b即可,此外,由于 l_1l_3 线是 l_24的决策分类边界线,一定与 l_2 是平行的,平行就意味着斜率不变,b变化即可,所以我们可以假设l_1线的方程为  w^T.x+b=cl_3 线的方程为 w^T.x+b=-c

 二维空间点 (x_1,y_1 ) 到直线 Ax+By+C=0 的距离公式为:

d=\frac{|Ax_1+By_1+C|}{\sqrt{(A^2+B^2 )}}

我们希望的是决策边界上的样本点到 l_2 ​直线的距离d越大越好。我们可以直接计算 l_1​ 或 l_3 ​上的点到直线 l_2 ​的距离,假设将空间点扩展到n维空间后,点 x_i=(x_1,x_2...x_n ) 到直线w^T.x+b=0(严格意义上来说直线变成了超平面)的距离为:

d=\frac{|w^T.x_i+b|}{||w||}

以上 ||w||=\sqrt{(w_1^2+w_2^2+...+w_n^2 )},读做“w的模”。

1.3 拉格朗日乘数法、KKT条件、对偶(扩展)

1.3.1 拉格朗日乘数法

拉格朗日乘数法主要是将有等式约束条件优化问题转换为无约束优化问题,拉格朗日乘数法如下:
假设 x=[x_1,x_2,...,x_n ] 是一个n维向量,f(x) 和 h(x) 含有x的函数,我们需要找到满足 h(x)=0 条件下 f(x) 最小值,如下:

L(x, \lambda )=f(x)+\lambda h(x)
拉格朗日函数转换成等式过程的证明涉及到导数积分等数学知识,参考文章:拉格朗日乘子法从0到1_代码简史的博客-CSDN博客

1.3.2 KKT条件

假设  x=[x_1,x_2,...,x_n ] 是一个n维向量,f(x)h(x)含有x的函数,我们需要找到满足 h(x)\leqslant 0条件下 f(x)最小值,我们可以考虑加入一个“松弛变量” a^2 让条件 h(x)\leqslant 0来达到等式的效果,即使条件变成 h(x)+a^2=0,这里加上 a^2的原因是保证加的一定是非负数,即: a^2\geqslant 0,但是目前不知道这个 a^2值是多少,一定会找到一个合适的 a^2值使 h(x)+a^2=0成立。
通过转换:
L(x, \lambda, a)=f(x)+\lambda(h(x)+a^2 )
但是上式中λ值必须满足λ≥0,由于L(x,\lambda,a)变成了有条件的拉格朗日函数,这里需要求 minL(x, \lambda, a)对应下的x值。

以上便是不等式约束优化问题的KKT(Karush-Kuhn-Tucker)条件,我们回到最开始要处理的问题上,根据③式可知,我们需要找到合适的x,λ,a值使L(x,λ,a)最小,但是合适的x,λ,a必须满足KKT条件

1.3.3 对偶问题

  对偶问题是我们定义的一种问题,对于一个不等式约束的原问题, 我们定义对偶问题为(对上面方程的求解等效求解下面方程),其实就是把min和max对调了一下,当然对应的变量也要变换。

1.4 最小化SVM目标函数

  通过推导我们知道SVM目标函数如下, 根据拉格朗日乘数法、KKT条件、对偶问题我们可以按照如下步骤来计算SVM目标函数最优的一组w值。
在这里插入图片描述

1.4.1 构造拉格朗日函数

将SVM目标函数转换为如下:
在这里插入图片描述
以上不等式转换成拉格朗日函数必须满足KKT条件:
在这里插入图片描述

1.4.2 对偶转换

由于原始目标函数 1/2 ||w||^2是个下凸函数,根据1.3.3中对偶问题可知 L(x,λ,a) 一定是强对偶问题,所以可以将a式改写成如下:

1.4.3 SMO算法求解

SMO(Sequential Minimal Optimization),序列最小优化算法,其核心思想非常简单:每次只优化一个参数,其他参数先固定住,仅求当前这个优化参数的极值。

1.4.4 计算分割线w和b的值

  • 我们可以知道获取了一组λ的值,我们可以得到一组w对应的值。假设我们有S个支持向量,以上b的计算可以使用任意一个支持向量代入计算即可,如果数据严格是线性可分的,这些b结果是一致的。
  • 对于数据不是严格线性可分的情况,参照后面的软间隔问题,一般我们可以采用一种更健壮的方式,将所有支持向量对应的b都求出,然后将其平均值作为最后的结果,最终求出b的结果。
  • 确定w和b之后,我们就能构造出最大分割超平面w^T.x+b=0,新来样本对应的特征代入后得到的结果如果是大于0那么属于一类,小于0属于另一类。

1.5 软间隔及优化

1.5.1 软间隔问题

  • 以上讨论问题都是基于样本点完全的线性可分,我们称为硬间隔。如果存在部分样本点不能完全线性可分,那么我们就需要用到软间隔,相比于硬间隔的苛刻条件,我们允许个别样本点出现在间隔带里面, 即我们允许部分样本点不满足约束条件。
  • 为了度量这个间隔软到何种程度,我们为每个样本引入一个“松弛变量”  \varepsilon_i, \varepsilon_i\geq 0(中文:克西)加入松弛变量后,我们的约束条件变成 y.(w^T.x_i+b)\geq 1-\epsilon,这样不等式就不会那么严格。

1.5.2 优化SVM目标函数

加入软间隔后我们的目标函数变成了:

其中C是一个大于0的常数,当C为无穷大,\epsilon_i必然无穷小,这样的话SVM就变成一个完全线性可分的SVM。如果C为有对应的值时,\epsilon_i对应的会有一个大于0的值,这样的SVM就是允许部分样本不遵守约束条件,接下来我们对新的目标函数h式求解最优化问题。

 1.5.3 SVM代码

from sklearn import svm
import numpy as np
def read_data(path):
   with open(path) as f :
      lines=f.readlines()
   lines=[eval(line.strip()) for line in lines]
   X,y=zip(*lines)
   X=np.array(X)
   y=np.array(y)
   return X,y

if __name__ == '__main__':
   X_train,y_train=read_data("./data/train_data")
   X_test,y_test=read_data("./data/test_data")

   #C对样本错误的容忍,这里就是SVM中加入松弛变量对应的C,
   model= svm.SVC(C=1.0)
   model.fit(X_train,y_train.ravel())
    #打印支持向量
   print(model.support_vectors_)
    #打印支持向量下标
   print(model.support_)

    #使用SVM应用到测试集,返回正确率
   score = model.score(X_test,y_test)
   print(score)

1.5.4 网格搜索

        网格搜索就是手动给定模型中想要改动的所有参数,程序自动使用穷举法来将所有的参数或者参数组合都运行一遍,将对应得到的模型做K折交叉验证,将得分最高的参数或参数组合当做最佳结果,并得到模型。也就是说网格搜索用来获取最合适的一组参数。
        使用网格搜索由于针对每个参数下的模型需要做K折交叉验证最终导致加大了模型训练时间,所以一般我们可以在小的训练集中使用网格搜索找到对应合适的参数值,再将合适的参数使用到大量数据集中训练模型。例如:逻辑回归中使用正则项时,我们可以先用一小部分训练集确定合适的惩罚系数,然后将惩罚系数应用到大量训练集中训练模型。

1.6 SVM Hinge Loss 损失函数

        其实这里我们说SVM的损失主要说的就是上式中的松弛变量 \epsilon_i损失,当所有样本总的 \epsilon_i为0时那么就是一个完全线性可分的SVM;如果SVM不是线性可分,那么我们希望总体样本的松弛变量越小越好。

1.7 核函数

1.7.1 非线性SVM

        在前面SVM讨论的硬间隔和软间隔都是指的样本完全可分或者大部分样本点线性可分的情况。我们可以使用升维方式来解决这种线性不可分的问题,例如目前只有两个维度 x_1​ 、x_2​,我们可以基于已有的维度进行升维得到更多维度,例如:x_1 x_1 , x_1 x_2 , x_2 x_2​,这样我们可以将以上问题可以转换成高维可分问题。

1.7.2 核函数(Kernel Function)

假设原有特征有如下三个 x_1, x_2, x_3,那么基于三个已有特征进行两两组合(二阶交叉)我们可以得到如下更多特征,

[x_1 x_1 , x_1 x_2 , x_1 x_3 , x_2 x_1 , x_2 x_2 , x_2 x_3 , x_3 x_1 , x_3 x_2 , x_3 x_3 ]
        我们在训练模型时将以上组合特征可以参与到模型的训练中,其代价是运算量过大,比如原始特征有m个,那么二阶交叉的维度为 C_m^2 个,这种量级在实际应用中很难实现,那么有没有一种方式可以在升维的同时可以有效的降低运算量,在非线性SVM中,核函数就可以实现在升维的同时可以有效降低运算量。
        以上核函数叫做多项式核函数,常用的核函数有如下几种,不同的核函数的区别是将向量映射到高维空间时采用的升维方法不同,不过高维向量都是不需要计算出来的。
线性核函数:

K(x_i.x_j )={x_i}^T.x_j
多项式核函数:

K(x_i.x_j )=(\alpha ({x_i}^T.x_j )+c)^d         (α,c,d都是参数)
高斯核函数:

1.7.3 核函数在SVM中的应用

        在非线性SVM中,我们可以对原始特征进行升维,原有的超平面 w^T.x+b=0变成了 w^T.\varphi x+b=0,然后经过对偶处理目标函数。
        这样我们可以通过核函数将数据映射到高维空间,但是核函数是在低维上进行计算,而将实质上的分类效果表现在了高维空间上,来解决在原始空间中线性不可分的问题。

        在SVM中我们可以使用常用的核函数:线性核函数、多项式核函数、高斯核函数来进行升维解决线性不可分问题,应用最广泛的就是高斯核函数,无论是小样本还是大样本、高维或者低维,高斯核函数均适用,它相比于线性核函数来说,线性核函数只是高斯核函数的一个特例,线性核函数适用于数据本身线性可分,通过线性核函数来达到更理想情况。

        高斯核函数相比于多项式核函数,多项式核函数阶数比较高时,内部计算时会导致一些元素值无穷大或者无穷小,而在高斯核函数会减少数值的计算困难。
        综上,我们在非线性SVM中使用核函数时,先使用线性核函数,如果不行尝试换不同的特征,如果还不行那么可以直接使用高斯核函数。

from sklearn import svm
from sklearn import datasets
from sklearn.model_selection import train_test_split as ts
if __name__ == '__main__':
    #import our data
    iris = datasets.load_iris()
    X = iris.data
    y = iris.target

    #split the data to  7:3
    X_train,X_test,y_train,y_test = ts(X,y,test_size=0.3)
    print(y_test)
    # select different type of kernel function and compare the score

    # kernel = 'rbf'
    clf_rbf = svm.SVC(kernel='rbf')
    clf_rbf.fit(X_train,y_train)
    score_rbf = clf_rbf.score(X_test,y_test)
    print("The score of rbf is : %f"%score_rbf)

    # kernel = 'linear'
    clf_linear = svm.SVC(kernel='linear')
    clf_linear.fit(X_train,y_train)
    score_linear = clf_linear.score(X_test,y_test)
    print("The score of linear is : %f"%score_linear)
    
    # kernel = 'poly'
    clf_poly = svm.SVC(kernel='poly')
    clf_poly.fit(X_train,y_train)
    score_poly = clf_poly.score(X_test,y_test)
    print("The score of poly is : %f"%score_poly)
  • rbf:高斯核函数
  • linear:线性核函数
  • poly:多项式核函数
     

1.8 支持向量机SVM特点

1.8.1 抗干扰能力强

根据一些样本点,我们可以通过拉格朗日乘数法、KKT条件、对偶问题、SMO算法计算出支持向量机SVM的分类线 w^T.x+b=0

        我们可以看出SVM在训练过程中找到的是两类点的分割线,计算样本中有少量异常点,在训练模型时依然能很正确的找到中间分割线,因为训练SVM时考虑了全量数据,确定这条线的b时只与支持向量点(边界上的点)有关。同样在测试集中就算有一些样本点是异常点也不会影响其正常分类,SVM具有抗干扰能力强的特点。
        此外,由于训练SVM需要所有样本点参与模型训练,不然不能缺点这条线,所以当数据量大时,SVM训练占用内存非常大。这时SVM模型的缺点。

1.8.2 二分类及多分类

        SVM同样支持多分类,我们可以将一个多分类问题拆分成多个二分类问题,例如有A,B,C三类,我们使用SVM训练时可以训练3个模型,第一个模型针对是A类和不是A类进行训练。第二个模型针对是B类和不是B类进行训练。第三个模型针对是C类和不是C类进行训练。这样可以解决多分类问题。

1.9 网格搜索最佳参数

svc = SVC()
params = {'C':np.logspace(-3,1,20),'kernel':['rbf','poly','sigmoid','linear']}
gc = GridSearchCV(estimator = svc,param_grid = params)
gc.fit(X_train_pca,y_train)
print('网格搜索最佳参数:',gc.best_params_)   #  {'C': 3.79269019073,'kernel':'rbf'}
print('模型得分是:',gc.score(X_test_pca,y_test))   # 0.883720930232
y_pred = gc.predict(X_test_pca)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/343322.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小红书穿搭博主推广费用是多少?

小红书作为一个种草属性非常强的平台,商业价值是有目共睹的。很多爱美的女性都会在小红书上被种草某个商品,所以很多服装品牌都会在小红书上布局推广。 穿搭作为小红书的顶梁柱类目,刷小红书就能总是看到好看的穿搭博主分享美美的衣服&#…

【优化】Nginx设置浏览器缓存

【优化】Nginx设置浏览器缓存 设置缓存 d代表天 h代表小时 -1代表不设置缓存 location ^~ / {root /www/wwwroot/com;index index.html index.htm;location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|svg)${expires 30d;error_log /dev/null;access_log /dev/null;}if ($…

【成为架构师课程系列】怎样进行概念架构(Conceptual Architecture)?

目录 前言 什么是概念架构 概念架构阶段的3个步骤 初步设计 高层分割 分层式概念服务架构 Layer:逻辑层 Tier: 物理层 按通用性分层 技术堆叠 考虑非功能需求 【禅与计算机程序设计艺术:更多阅读】 前言 胜兵先胜而后求战,败兵先站而后求胜。…

HTTPSHandler SSL Error

我在服务器ubuntu中,尝试使用pip3,但是出现下面的报错 ImportError: cannot import name HTTPSHandler 通过查询资料,发现报错的原因是,该pip3.5中没有安装好openssl. 我尝试在python3.5中使用import ssl, 确实是会显示下面的报错…

推广传单制作工具

临近节日如何制作推广活动呢?没有素材制作满减活动宣传单怎么办?小编教你如何使用在线设计工具乔拓云,轻松设计商品的专属满减活动宣传单,不仅设计简单,还能自动生成活动分享链接,只需跟着小编下面的设计步…

动态规划,这将是你见过最详细的讲解

文章目录一、为什么要讲动态规划呢?二、什么是动态规划三、感受一下递归算法、备忘录算法、动态规划递归算法带备忘录的递归解法(自定向下)自底向上的动态规划四、动态规划的解题套路1. 穷举分析2. 确定边界3. 确定最优子结构4. 写出状态转移…

sql 优化

sql 优化1. mysql 基础架构1.1 mysql 的组成2. mysql 存储引擎2.1MyISAM2.2 InnoDB2.3 MyISAM 和 InnoDB 的对比3. mysql 索引3.1 Hash 索引3.2 B-Tree 索引3.3 BTree 索引3.4 R-Tree 索引3.5 Full-Text 索引4. sql 优化4.1 避免 select *4.2 避免在where子句中使用or来连接条件…

PTA L1-046 整除光棍(详解)

前言:内容包括四大模块:题目,代码实现,大致思路,代码解读 题目: 这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由1组成的数字,比如1、11、111、1111等。传说任何一个光棍都能被…

【数据库】sql函数和多表关联查询

目录 一,SQL函数 1,聚合函数 1, count函数 2, AVG函数 3, SUM函数 4, MAX函数 5, MIN函数 6,数据分组——GROUP BY 7,限定组的结果,HAVING 8&#x…

在线支付系列【23】支付宝开放平台产品介绍

有道无术,术尚可求,有术无道,止于术。 文章目录前言支付产品App 支付手机网站支付电脑网站支付新当面资金授权当面付营销产品营销活动送红包会员产品App 支付宝登录人脸认证信用产品芝麻 GO芝麻先享芝麻免押芝麻工作证安全产品交易安全防护其…

Centos7上Docker安装

文章目录1.Docker常识2.安装Docker1.卸载旧版本Docker2.安装Docker3.启动Docker4.配置镜像加速前天开学啦~所以可以回来继续卷了哈哈哈,放假在家效率不高,在学校事情也少点(^_−)☆昨天和今天学了学Docker相关的知识,也算是简单了解了下&…

设计模式C++实现12:抽象工厂模式

参考大话设计模式; 详细内容参见大话设计模式一书第十五章,该书使用C#实现,本实验通过C语言实现。 抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们…

Python之字符串精讲(下)

前言 今天继续讲解字符串下半部分,内容包括字符串的检索、大小写转换、去除字符串中空格和特殊字符。 一、检索字符串 在Python中,字符串对象提供了很多用于字符串查找的方法,主要给大家介绍以下几种方法。 1. count() 方法 count() 方法…

CHAPTER 5 Jenkins SonarQube

Jenkins & SonarQube5.1 安装SonarQube1. 下载镜像2. 导出到其他服务器3. 准备工作4. docker-compose文件5. 启动容器5.2 登录SonarQube1.登录2. 安装中文语言插件3. 安装其他插件5.3 部署扫描器sonar-scanner1. 部署sonar-scanner2. 新建项目3. 扫描代码4. 查看报告5.4 Je…

Prometheus 的介绍和安装

介绍 Prometheus 是一个开源的监控和报警系统,最初由SoundCloud于2012年创建,随着越来越多的公司采用Prometheus以及非常活跃的社区,Prometheus于2016年加入云原生基金会,成为Kubernetes之后的第二个托管项目,并于2018年毕业。 特点 通过PromQL来对基于指标名称和键值对…

独立产品灵感周刊 DecoHack #047 - 安卓手机上最有用的APP

本周刊记录有趣好玩的独立产品设计开发相关内容,每周发布,往期内容同样精彩,感兴趣的伙伴可以点击订阅我的周刊。为保证每期都能收到,建议邮件订阅。欢迎通过 Twitter 私信推荐或投稿。💻 产品推荐 1. Bouncer Tempor…

算法训练营 day45 动态规划 0-1背包理论 分割等和子集

算法训练营 day45 动态规划 0-1背包理论 分割等和子集 0-1背包理论 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 在下面的讲解中&…

python 使用 thrift 教程

一、前言:   Thrift 是一种接口描述语言和二进制通信协议。以前也没接触过,最近有个项目需要建立自动化测试,这个项目之间的微服务都是通过 Thrift 进行通信的,然后写自动化脚本之前研究了一下。 需要定义一个xxx.thrift的文件&…

【C++】十分钟带你入门C++

目录零 内容概括一 C关键字二 命名空间2.1 命名空间定义2.2 命名空间的使用三 C输入和输出四 缺省参数4.1 缺省参数的概念4.2 缺省参数分类五 函数重载5.1 函数重载的概念六 引用6.1 引用概念6.2 引用特性6.3 常引用6.4 使用场景6.5 效率比较6.6 引用和指针的区别七 内联函数7.…

最简易的教程 -一篇文章教会你 用Python打包文件

前言 嗨嗨,好久不见,我是 我叫 … emmm你们好 我是一堆英文字母(名字乱打的不好yi shi ~) 看到文章的人多不多,我不知道 ,招呼我还是要打一个的 👍 今天文章很简单,打包改图标 用…