机器学习-线性分类-支持向量机SVM-SMO算法代码实现-15
1. alpha2 的修剪

if y1 != y2 :
α1 - α2 = k # 不用算k的具体大小
if k > 0: # 上图的左 下这条线
α2 的区间 (0, c-k)
k < 0 : # 上图的左 下这条线
α2 的区间 (-k, C)
所以:
L = max(0, -k) # k>0 还是<0 都统一表达了
H = min(c, c-k)
else:
y1 = y2 右边的图 同理
2.参考
参考:https://zhuanlan.zhihu.com/p/49331510

非支撑向量:
alpha=0

间隔上的支撑向量:
0<alpha<c

间隔之内:
alpha=c and 0< ei <1

上面的三种都是正确分类的;
错误分类的:

alpha=c and ei > 1
yi(wxi+b) = 1-ei < 0 使负的 预测的与实际的符号相反
3. 代码实现
"""
算法思想:
创建一个alpha向量 并初始化为0
当迭代次数小于 最大迭代次数(外层循环):
遍历α中的每一个αi(内层循环):
如果该αi可以被优化:
随机选择另一个αj
同时优化 αi aj
如果αi aj优化完毕退出内层循环
"""
import numpy
import numpy as np
import random
import matplotlib.pyplot as plt
def load_data(filename):
X = []
y = []
fr = open(filename)
for line in fr.readlines():
x1, x2, y_true = line.strip().split("\t")
X.append([float(x1), float(x2)])
y.append(float(y_true))
fr.close()
return numpy.array(X), np.array(y)
def show_data(filename, line=None):
X, y = load_data("./testSet.txt")
class_1_index = np.where(y == -1) # -1 负样本的索引
X_class_1 = X[class_1_index, :].reshape(-1, 2) # 负样本对应的X取出
class_2_index = np.where(y == 1) # +1 正样本的索引
X_class_2 = X[class_2_index, :].reshape(-1, 2) # 正样本对应的X取出
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.scatter(X_class_1[:, 0], X_class_1[:, 1], c="r", label="$-1$")
ax.scatter(X_class_2[:, 0], X_class_2[:, 1], c="g", label="$+1$")
plt.legend()
if line is not None:
alphas, b = line
x = np.linspace(1, 8, 50)
w = np.sum(alphas*y[:, np.newaxis]*X, axis=0)
# w1*x1 + w2*x2 +b = 0 # 或者 +1 -1
y = np.array([(-b - w[0]*x[i]) / w[1]for i in range(50)])
y1 = np.array([(1 -b - w[0]*x[i]) / w[1]for i in range(50)])
y2 = np.array([(-1 -b - w[0]*x[i]) / w[1]for i in range(50)])
ax.plot(x, y, "b-")
ax.plot(x, y1, "b--")
ax.plot(x, y2, "b--")
plt.show()
def smo_simple(dataArr, yArr, C, toler, maxIter):
numSample, numDim = dataArr.shape # 100行 2列
# 初始化
b = 0
alphas = np.zeros((numSample, 1))
iterations = 0 # 迭代次数
while iterations < maxIter:
alphaPairsChanged = 0
for i in range(numSample):
# 针对对i个样本给出预测值 这里没有使用核函数变换
# fXi= wXi+b
# alphas * y * X * Xi +b Xi为一条样本
fXi = np.sum(alphas * yArr[:, np.newaxis] * dataArr * dataArr[i, :]) + b
# Ei 为误差
Ei = fXi - yArr[i]
"""
kkt 约束条件:
yi*(wXi+b) >= 1 且alpha=0 远离边界 正常分类的 ----条件1
yi*(wXi+b) = 1 且0<alpha<c 边界上面
yi*(wXi+b) < 1 且 alpha=c 两条边界之间 ----条件2
# 0 <= alphas[i] <= C 已经在边界上的 alpha不能再优化
Ei = fXi - yArr[i] 两边都 乘以 yArr[i]
yArr[i]*Ei = yArr[i]*fXi - 1 # 偏差
如果 yArr[i]*Ei < -toler alpha应该为C 如果<C 就需要优化 ----对应条件2
如果 yArr[i]*Ei > toler alpha应该为0 如果>0 就需要优化 ----对应条件1
"""
if ( (yArr[i]*Ei < -toler) and (alphas[i] < C) ) or ( (yArr[i]*Ei > toler) and (alphas[i] > 0)):
# 进入这里 说明需要优化alpha[i] 我们在随机取一条alpha[j] j!=i
j = selectJrand(i, numSample)
fXj = np.sum(alphas * yArr[:, np.newaxis] * dataArr * dataArr[j, :]) + b
Ej = fXj - yArr[j]
# 先复制一份old alphaI alphaJ
alphaIold = alphas[i].copy()
alphaJold = alphas[j].copy()
# 根据 yArr[i] yArr[j] 是否同号 计算 L H
if yArr[i] != yArr[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:
print("L == H")
continue
# 计算 eta, eta是alpha[j]的最大修正量 eta == 0 则 continue
# eta = K(1,1)+K(2,2) - 2K(1,2)
eta = (np.sum(dataArr[i,:] * dataArr[i, :]) +
np.sum(dataArr[j, :] * dataArr[j, :]) -
2 * np.sum(dataArr[i,:] * dataArr[j, :]))
if eta == 0:
continue
# 计算新的alphas[j]
alphas[j] = alphaJold + yArr[j]*(Ei - Ej) / eta
# 修剪新的alphas[j]
alphas[j] = clipAlpha(alphas[j], H, L)
# 新的alphas[j] 与 alphaJold 如果改动量很小 则 contine 退出
if abs(alphaJold - alphas[j]) < 0.00001:
continue
# 更新 alphas[i]
alphas[i] = alphaIold + yArr[i] * yArr[j] * (alphaJold - alphas[j])
# 计算参数b
bi = b - Ei - yArr[i] * (alphas[i] - alphaIold) * np.sum(dataArr[i, :] * dataArr[i, :]) - \
yArr[j] * (alphas[j] - alphaJold) * np.sum(dataArr[i, :] * dataArr[j, :])
bj = b - Ej - yArr[i] * (alphas[i] - alphaIold) * np.sum(dataArr[i, :] * dataArr[j, :]) - \
yArr[j] * (alphas[j] - alphaJold) * np.sum(dataArr[j, :] * dataArr[j, :])
if 0<alphas[i]<C:
b = bi
elif 0<alphas[j]<C:
b = bj
else:
b = (bi+bj)/2
# 走到这里说明 alpha b 更新了
alphaPairsChanged += 1
# 输出
print(f"iter: {iterations}, i: {i}, pairs changed: {alphaPairsChanged}")
if alphaPairsChanged ==0:
iterations += 1
else:
iterations =0
return b, alphas
def selectJrand(i, numSample):
j = i
while j == i:
j = int(random.uniform(0, numSample))
return j
def clipAlpha(aj, H, L):
if aj > H:
return H
if aj < L:
return L
return aj
if __name__ == '__main__':
X, y = load_data("./testSet.txt")
C = 0.6
toler = 0.001
maxIter = 40
b, alphas = smo_simple(X, y, C, toler, maxIter)
print(b)
print(alphas)
show_data("./testSet.txt", line=(alphas, b))

4. 优缺点
任何算法都有其优缺点,支持向量机也不例外。
支持向量机的优点是:
由于SVM是一个凸优化问题,所以求得的解一定是全局最优而不是局部最优。
不仅适用于线性线性问题还适用于非线性问题(用核技巧)。
拥有高维样本空间的数据也能用SVM,这是因为数据集的复杂度只取决于支持向量而不是数据集的维度,这在某种意义上避免了“维数灾难”。
理论基础比较完善(例如神经网络就更像一个黑盒子)。
支持向量机的缺点是:
二次规划问题求解将涉及m阶矩阵的计算(m为样本的个数), 因此SVM不适用于超大数据集。(SMO算法可以缓解这个问题)
只适用于二分类问题。(SVM的推广SVR也适用于回归问题;可以通过多个SVM的组合来解决多分类问题
机器学习-线性分类-支持向量机SVM-SMO算法代码实现-15的更多相关文章
- SVM-非线性支持向量机及SMO算法
SVM-非线性支持向量机及SMO算法 如果您想体验更好的阅读:请戳这里littlefish.top 线性不可分情况 线性可分问题的支持向量机学习方法,对线性不可分训练数据是不适用的,为了满足函数间隔大 ...
- 线性可分支持向量机--SVM(1)
线性可分支持向量机--SVM (1) 给定线性可分的数据集 假设输入空间(特征向量)为,输出空间为. 输入 表示实例的特征向量,对应于输入空间的点: 输出 表示示例的类别. 线性可分支持向量机的定义: ...
- 统计学习:线性可分支持向量机(SVM)
模型 超平面 我们称下面形式的集合为超平面 \[\begin{aligned} \{ \bm{x} | \bm{a}^{T} \bm{x} - b = 0 \} \end{aligned} \tag{ ...
- 机器学习算法整理(七)支持向量机以及SMO算法实现
以下均为自己看视频做的笔记,自用,侵删! 还参考了:http://www.ai-start.com/ml2014/ 在监督学习中,许多学习算法的性能都非常类似,因此,重要的不是你该选择使用学习算法A还 ...
- 机器学习笔记:支持向量机(svm)
支持向量机(svm)英文为Support Vector Machines 第一次接触支持向量机是2017年在一个在线解密游戏"哈密顿行动"中的一个关卡的二分类问题,用到了台湾教授写 ...
- 支持向量机的smo算法(MATLAB code)
建立smo.m % function [alpha,bias] = smo(X, y, C, tol) function model = smo(X, y, C, tol) % SMO: SMO al ...
- 吴裕雄--天生自然python机器学习:基于支持向量机SVM的手写数字识别
from numpy import * def img2vector(filename): returnVect = zeros((1,1024)) fr = open(filename) for i ...
- 机器学习之支持向量机—SVM原理代码实现
支持向量机—SVM原理代码实现 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/9596898.html 1. 解决 ...
- 机器学习:Python中如何使用支持向量机(SVM)算法
(简单介绍一下支持向量机,详细介绍尤其是算法过程可以查阅其他资) 在机器学习领域,支持向量机SVM(Support Vector Machine)是一个有监督的学习模型,通常用来进行模式识别.分类(异 ...
- 一步步教你轻松学支持向量机SVM算法之案例篇2
一步步教你轻松学支持向量机SVM算法之案例篇2 (白宁超 2018年10月22日10:09:07) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...
随机推荐
- 28、错误error
1.是什么? 在实际的项目中,我们希望通过程序的错误信息快速定位问题,但是又不喜欢错误处理:代码就会很冗余又啰嗦.Go语言没有提供类似Java.C#语言中的try...catch异常处理方法,而是通过 ...
- 87 GB 模型种子,GPT-4 缩小版,超越ChatGPT3.5,多平台在线体验
瞬间爆火的Mixtral 8x7B 大家好,我是老章 最近风头最盛的大模型当属Mistral AI 发布的Mixtral 8x7B了,火爆程度压过Google的Gemini. 缘起是MistralAI ...
- 使用create-vue创建vue3项目
create-vue是vue3新的脚手架搭建项目工具,底层构建工具使用vite,而不是vue-cli的webpack. 但不是说你不能用以前的vue create命令来创建vue3项目,你完全可以用v ...
- Oracle重做、归档日志
日志文件 oracle日志文件分为两种: 重做日志文件(redo),或者称为"在线重做日志" 归档日志文件(arch),或者称为"归档重做日志" 在线重做日志文 ...
- 如何有效应对员工违规使用U盘的情况?
在面对员工违规使用U盘的挑战时,华企盾DSC数据防泄密系统提供了一套综合而高效的解决方案. 通过系统的U盘加密功能,我们能够防止未经授权的U盘访问,确保敏感数据不会被非法传输.这一层保护不仅是基础性的 ...
- 解密数据可视化软件、BI软件和数字孪生软件的不同
在现代企业和科技领域,数据起着至关重要的作用.为了更好地管理和理解数据,不同类型的软件工具应运而生,其中包括数据可视化软件.BI(Business Intelligence)软件和数字孪生软件.虽然它 ...
- django token 认证 简单记录
class User(AbstractUser): username = models.CharField( max_length=20, unique=True, primary_key=True, ...
- Mybatis之TypeHandler使用教程
引言 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 ...
- 在xml中比较运算符
SQL 中,可以使用比较运算符来比较两个值,如使用小于运算符 < 比较两个值大小.但是,在 SQL 查询中,有时候需要将小于运算符 < 用于 XML 或 HTML 语法中,这会导致语法冲突 ...
- LeetCode DFS、BFS篇(102、200、111、752)
102. 二叉树的层序遍历 给你一个二叉树,请你返回其按 层序遍历 得到的节点值. (即逐层地,从左到右访问所有节点). 示例: 二叉树:[3,9,20,null,null,15,7], 3 / 9 ...