热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

SVM–支持向量机

SVM--支持向量机SVM简介​支持向量机(supportvectormachines,SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使

SVM--支持向量机

SVM简介

​ 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;SVM还包括核技巧,这使它成为实质上的非线性分类器。SVM的的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最小化问题。SVM的的学习算法就是求解凸二次规划的最优化算法。


最大间隔和分类

​ 在做二分类时,我们希望找到一个超平面,将两者分开。这样的平面也许有很多,但怎么样找到那个最优的,就是我们需要考虑的问题了。一般的,我们可以认为一个点距离超平面的远近可以表示分类预测的置信度。所以,最优解应是”正中间”, 容忍性好, 鲁棒性高, 泛化能力最强.

而这个超平面方程,我们一般表示为

image-20221211083207201

超平面距离两支撑向量之和为,也就是间隔

image-20221211083348142

所以问题求解变成了找到w满足使得间隔最大

image-20221211083533868

由于后续计算方便,求解

最大值,也就等价于求解

最小值.当训练样本较少时,可以直接通过线性规划求解。但是一旦数据量增多,这种方法就不再适用。


对偶问题

此时,问题已经变成了求解满足如下条件的w和b

其本质是一个凸二次规划问题。

这时候就可以构造拉格朗日函数

image-20221211092431310

其约束范围为不等式,可以转化成KKT条件

image-20221211092551916

求解上诉问题,可以通过多种方式,如SMO,二次规划


拉格朗日乘子法

1.第一步:引入拉格朗日乘子 α_i≥0得到拉格朗日函数

image-20221211110008930

第二步:令L(w,b,α) 对w和b的偏导为零:

image-20221211110039696

第三步:w, b回代到第一步:

image-20221211110048535

最终形式

image-20221211110123729

根据KKT条件得

image-20221211110335599

到这里我们可以看到,只有在边缘的支撑向量 αi才不会为0,而在内部的都为0。大部分的训练样本都不需保留, 最终模型仅与支持向量有关.


SMO求解

​ SMO算法是一种启发式算法,基本思路是:如果所有变量的解都满足此最优化问题的KKT条件,那么这么最优化问题的解就得到了。

​ 求解步骤:

1.任意选取一对需要更行的变量αi和αj

2.将剩下的α当作定值,求解当前对偶问题,更新αi和αj

不断迭代更行,得到最优解。再将α反代,

img

此时,我们可以将问题看成一个一元二次的优化问题。由于α1y1+α2y2==c,两个变量之间相互联系,所以可以假设成最后是α2的优化问题,最终求出α2再反代回去解出α1。

由于

必须满足上图中的线段约束。假设L和H分别是上图中

所在的线段的边界。那么很显然我们有:

MommyTalk1670754965559

而对于L和H,我们也有限制条件如果是上面左图中的情况,则

MommyTalk1670755006688

则最终的αnew2α2new应该为:

MommyTalk1670755059889

最后:

image-20221211183842304

image-20221211183847874

image-20221211183854687


核函数

以上都是基于模型是线性可分的,那么,如果遇到线性不可分该怎么办呢?这时候核函数就应运而生。

原理:对于在低维线性不可分的数据,在映射到了高维以后,就变成线性可分的了。

核函数的关键在于设计核函数

Kernel(x,y)=<φ(x),φ(y)>=k(x,y)

常用的核函数有:

image-20221211140225801


软间隔与正则化


软间隔

​ 在现实生活中的数据往往是或本身就是非线性可分但是近似线性可分的,或是线性可分但是具有噪声的,以上两种情况都会导致在现实应用中,硬间隔线性支持向量机变得不再实用,所以软间隔,应运而生

软间隔,通俗来讲就是,使超平面既要尽可能的将数据类别分对,又要使得支持向量到超平面的间隔尽可能的大

ϵ

ϵ称为松弛变量


正则化

最大化间隔的同时, 让不满足约束的样本应尽可能少.

image-20221211141304594

其中C>0为惩罚参数;l_0/1是”0/1损失函数”


数据集简介

乳腺癌数据集一共有569个样本,30个特征,标签为二分类



















类型个数
良性 benign357
恶性 malignant212

代码实现

from sklearn.datasets import load_breast_cancer
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import train_test_split
import time
def dataset_loder():
cancers=load_breast_cancer()
data=cancers.data
label=cancers.target
label=np.array(label)
index=np.where(label==0)
label[index]=-1
return data,label
def weight(data,label,alphas):
data_mat=np.mat(data)
label_mat=np.mat(label).transpose()
w_mat=np.mat(np.zeros((1,data_mat.shape[1])))
for i in range(data_mat.shape[0]):
if alphas[i]>0:
w_mat+=label_mat[i]*alphas[i]*data_mat[i,:]
return w_mat.tolist()
def randPickj(i,m):
#i是alphai的i值,整数; m是alpha个数; j不能等于i
j=i
while j==i:
j=int(np.random.uniform(0,m))
return j
def clipAlpha(aj,H,L):
if aj>H:
aj=H
if aj aj=L
return aj
def plotBestFit(weights, b):
dataMat, labelMat = dataset_loder() # 加载样本特征、样本类别
dataArr = np.array(dataMat)
n = dataArr.shape[0] # n个样本
xcord1 = []
ycord1 = []
xcord2 = []
ycord2 = [] # 两个类别的样本的xy坐标值,x对应x1,y对应x2
# 将样本数据根据样本类别标签labelMat分别放入不同的坐标集中
for i in range(n):
if int(labelMat[i]) == 1: # 第i个样本是1类
xcord1.append(dataArr[i, 0]) # 第i个样本的x1值
ycord1.append(dataArr[i, 1]) # 第i个样本的x2值
else:
xcord2.append(dataArr[i, 0]) # 第i个样本的x1值
ycord2.append(dataArr[i, 1]) # 第i个样本的x2值
# 绘制两类样本的散点图
fig = plt.figure(figsize=(12, 8))
plt.scatter(xcord1, ycord1, c="red", s=50, label="label=1")
plt.scatter(xcord2, ycord2, c="blue", s=50, label="label=-1") # 继续在原图上作图
# 绘制决策边界
x = np.arange(-3.0, 25.0, 0.1)
y = (-b-weights[0][0] * x) / weights[0][1] # 由w1*x1+w2*x2+b=0得到x2(即y)=(-b-w1x1)/w2
x.shape = (len(x), 1)
y.shape = (len(x), 1)
plt.plot(x, y, color="darkorange", lineBoarder") # 继续在ax图上作图
plt.xlabel("X1", fOntsize=16)
plt.ylabel("X2", fOntsize=16)
plt.title("SMO BestFit", fOntsize=20, fOntweight="bold")
plt.legend() # 添加图标注解
plt.show()
def smo(data,label,c,toler,max_iter):
''''
c:软间隔的正则化的惩罚因子
toler:偏离KKT的容错率
max_iter:外层循环迭代次数
'''
'''
multiply:由于multiply是ufunc函数,
ufunc函数会对这两个数组的对应元素进行计算,因此它要求这两个数组有相同的大小(shape相同),
相同则是计算内积。如果shape不同的话,会将小规格的矩阵延展成与另一矩阵一样大小,再求两者内积。
'''
b=0
data_mat = np.mat(data)
label_mat = np.mat(label).transpose()
m,n=data_mat.shape
alphas = np.zeros((m,1))
iters = 0
while iters alphaPairsChanged = 0
for i in range(m):
# 计算第i个样本点的预测值gxi和预测误差Ei
#g(x)=ai yi x xiT+b
gxi=float(np.multiply(alphas,label_mat).transpose()*(data_mat*data_mat[i,:].transpose()))+b
Ei=gxi-label_mat[i]
"""检验第i个样本点是否满足KKT条件,若满足则会跳出本次内循环(不更新这个alphai),进行下一次内循环;
若不满足,看它是否是违反KKT条件超过容错率toler的点,若不是,则跳出本次内循环(不更新这个alphai),进行下一次内循环;
若是,则继续选择alphaj,计算gx,E,eta,进而求得aj解析解,进而求得ai解析解,进而更新b值"""
if (label_mat[i]*Ei<-toler and alphas[i]toler and alphas[i]>0):
j=randPickj(i,m)
gxj=float(np.multiply(alphas,label_mat).transpose()*(data_mat*data_mat[j,:].transpose()))+b
Ej=gxj-label_mat[j]
# 存储alpha初始值,用于后续计算
alphaIold = alphas[i].copy()
alphaJold = alphas[j].copy()
if label_mat[i]!=label_mat[j]:
L=max(0,alphas[j]-alphas[i])
H=min(c,c+alphas[j]-alphas[i])
else:
L = max(0, alphas[j] + alphas[i]-c)
H = min(c, alphas[j] + alphas[i])
if L==H:
continue
eta=data_mat[i,:]*data_mat[i,:].transpose()+data_mat[j,:]*data_mat[j,:].transpose()\
-2.0*data_mat[i,:]*data_mat[j,:].transpose()
if eta==0:
continue
alphas[j] = alphas[j] + label_mat[j] * (Ei - Ej) / eta
alphas[j] = clipAlpha(alphas[j], H, L)
if alphas[j]-alphaJold<0.00001:
continue
alphas[i]=alphas[i]+label_mat[i]*label_mat[j]*(alphaJold-alphas[j])
# 更新b值,根据alpha是否在0~C决定更新的b值
b1 = -Ei - label_mat[i] * (alphas[i] - alphaIold) * data_mat[i, :] * data_mat[i, :].transpose() \
- label_mat[j] * (alphas[j] - alphaJold) * data_mat[j, :] * data_mat[i, :].transpose() + b
b2 = -Ej - label_mat[i] * (alphas[i] - alphaIold) * data_mat[i, :] * data_mat[j, :].transpose() \
- label_mat[j] * (alphas[j] - alphaJold) * data_mat[j, :] * data_mat[j, :].transpose() + b
# 若ai或aj在(0,C)之间,则取b=bi或b=bj,若ai aj都不在(0,C)之间,取均值
if alphas[i] > 0 and alphas[i] b = b1
elif alphas[j] > 0 and alphas[j] b = b2
else:
b = (b1 + b2) / 2.0
alphaPairsChanged += 1 # 若进行到这里,说明ai aj经过了层层筛选(continue),已经被更新,于是内循环中alpha对更新次数+1
print("iter:{0}; i:{1}; alpha pair changed:{2};b:{3}".format(iters, i, alphaPairsChanged,b))
if alphaPairsChanged==0:
iters+=1
else:
iters=0
print ("iteration numer:%d" %iters)
return b,alphas
if __name__=="__main__":
c=0.1#惩罚因子
toler=0.001 #容错率
num_epoch=5
data,label=dataset_loder()
b,alphas=smo(data,label,c,toler,num_epoch)
print("b",b)
w=weight(data,label,alphas)
plotBestFit(w,b)

实验截图

Figure_1



推荐阅读
  • 支持向量机(SVM)算法综述
    支持向量机(Support Vector Machine, SVM)是由Cortes和Vapnik于1995年首次提出的一种机器学习算法。SVM在处理小样本、非线性及高维模式识别问题上表现出显著的优势,并广泛应用于函数拟合等其他机器学习任务中。 ... [详细]
  • 本文探讨了如何在Django中创建一个能够根据需求选择不同模板的包含标签。通过自定义逻辑,开发者可以在多个模板选项中灵活切换,以适应不同的显示需求。 ... [详细]
  • 在日常的开发与学习中,经常会遇到想要深入了解或复制的优秀网站。手动逐个文件保存不仅耗时费力,还可能遗漏重要资源。本文将介绍两款强大的工具——Teleport Ultra和wget命令行工具,帮助开发者轻松抓取目标网站的全部内容。 ... [详细]
  • Smali代码动态调试指南
    本文介绍了如何通过一系列具体步骤实现Smali代码的动态调试,包括环境搭建、工具安装及调试过程中的关键操作。 ... [详细]
  • 1、服务器配置信息① 主服务器IP:192.168.1.2② 从服务器IP:192.168.1.3③ 操作系统:主服务器:Win8,从服务器࿱ ... [详细]
  • 本文探讨如何在VueJS项目中通过配置vue.config.js文件实现多页面应用(MPA),特别是针对管理端和客户端的不同需求。 ... [详细]
  • 本文详细解析了Tomcat服务器的核心配置文件server.xml,包括其主要功能、结构组成及各标签的具体作用。 ... [详细]
  • 本文详细介绍了为何需要进行端口转发,尤其是从标准 HTTP 80 端口到 Tomcat 默认 8080 端口的必要性,以及如何通过 Nginx 实现这一功能。同时,还将探讨 Nginx 在不同场景下的多种端口转发策略。 ... [详细]
  • 本文探讨了URL在网络通信中的作用及其结构,重点介绍了如何在iOS中使用URLComponents类解析URL,并讨论了URL在应用间跳转和本地文件访问中的应用。 ... [详细]
  • MySQL 5.7 绿色版安装及 my.ini 配置详解
    本文主要针对最近因系统重装导致的MySQL配置问题,详细介绍了MySQL 5.7.24绿色解压版的安装步骤及my.ini配置文件的关键设置,帮助用户顺利完成数据库的安装与配置。 ... [详细]
  • Delphi 10.4.2 版本现已进入内测阶段,此次更新不仅增强了现有功能,还引入了多项新技术以提升用户体验。新版本将支持最新的MSIX应用打包格式,改善Windows 10应用商店的部署体验;同时,新增的VCL控件将带来更加现代的用户界面设计。 ... [详细]
  • 深入探讨配置文件的管理与优化
    尽管配置文件的重要性不言而喻,但其管理和安全性问题却常被忽视。本文将详细讨论配置文件的不同管理策略及其优缺点。 ... [详细]
  • 本文探讨了在 Node.js 环境下,如何在用户上传图片时自动为其添加水印的技术方案,包括静态和动态两种方式。静态方式会在上传时直接将水印嵌入图片,而动态方式则是在每次请求图片时实时添加水印。 ... [详细]
  • 针对Windows 7系统中出现的Microsoft Security Client OOBE程序错误,本文提供了详细的故障排查与解决步骤,包括系统日志分析及具体操作指南。 ... [详细]
  • 本文详细介绍了Android平台上的动态加载技术,包括其定义、分类及具体实现步骤。通过动态加载技术,开发者可以在不更新应用的情况下,向用户推送新的功能或修复bug,从而提升用户体验。 ... [详细]
author-avatar
想零的时候
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有