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的更多相关文章

  1. SVM-非线性支持向量机及SMO算法

    SVM-非线性支持向量机及SMO算法 如果您想体验更好的阅读:请戳这里littlefish.top 线性不可分情况 线性可分问题的支持向量机学习方法,对线性不可分训练数据是不适用的,为了满足函数间隔大 ...

  2. 线性可分支持向量机--SVM(1)

    线性可分支持向量机--SVM (1) 给定线性可分的数据集 假设输入空间(特征向量)为,输出空间为. 输入 表示实例的特征向量,对应于输入空间的点: 输出 表示示例的类别. 线性可分支持向量机的定义: ...

  3. 统计学习:线性可分支持向量机(SVM)

    模型 超平面 我们称下面形式的集合为超平面 \[\begin{aligned} \{ \bm{x} | \bm{a}^{T} \bm{x} - b = 0 \} \end{aligned} \tag{ ...

  4. 机器学习算法整理(七)支持向量机以及SMO算法实现

    以下均为自己看视频做的笔记,自用,侵删! 还参考了:http://www.ai-start.com/ml2014/ 在监督学习中,许多学习算法的性能都非常类似,因此,重要的不是你该选择使用学习算法A还 ...

  5. 机器学习笔记:支持向量机(svm)

    支持向量机(svm)英文为Support Vector Machines 第一次接触支持向量机是2017年在一个在线解密游戏"哈密顿行动"中的一个关卡的二分类问题,用到了台湾教授写 ...

  6. 支持向量机的smo算法(MATLAB code)

    建立smo.m % function [alpha,bias] = smo(X, y, C, tol) function model = smo(X, y, C, tol) % SMO: SMO al ...

  7. 吴裕雄--天生自然python机器学习:基于支持向量机SVM的手写数字识别

    from numpy import * def img2vector(filename): returnVect = zeros((1,1024)) fr = open(filename) for i ...

  8. 机器学习之支持向量机—SVM原理代码实现

    支持向量机—SVM原理代码实现 本文系作者原创,转载请注明出处:https://www.cnblogs.com/further-further-further/p/9596898.html 1. 解决 ...

  9. 机器学习:Python中如何使用支持向量机(SVM)算法

    (简单介绍一下支持向量机,详细介绍尤其是算法过程可以查阅其他资) 在机器学习领域,支持向量机SVM(Support Vector Machine)是一个有监督的学习模型,通常用来进行模式识别.分类(异 ...

  10. 一步步教你轻松学支持向量机SVM算法之案例篇2

    一步步教你轻松学支持向量机SVM算法之案例篇2 (白宁超 2018年10月22日10:09:07) 摘要:支持向量机即SVM(Support Vector Machine) ,是一种监督学习算法,属于 ...

随机推荐

  1. Spring Boot内置的一些工具类

    1.断言Assert工具类 // 要求参数 object 必须为非空(Not Null),否则抛出异常,不予放行 // 参数 message 参数用于定制异常信息. void notNull(Obje ...

  2. 打造一个极度舒适的Chrome扩展项目开发环境

    大家好,我是 dom 哥.这是我关于 Chrome 扩展开发的系列文章,感兴趣的可以 点个小星星. Chrome 扩展能够提高浏览器的使用体验,通过自定义 UI 界面,监听浏览器事件,改变 Web 页 ...

  3. 生成式AI:未来的发展方向是什么?

    生成式AI的问世标志着人工智能领域迎来了一个全新时代的开启.今年,ChatGPT的面世引起了广泛的热议和关注,许多人认为这标志着人工智能领域进入了一个大规模探索的时代.然而,事实上,这只是生成式AI发 ...

  4. gho、wim、esd的区别

    本文介绍的仅仅是压缩格式上的区别,并不是一些个体错误理解的 "GHOST 镜像 = 带驱动的快速装机镜像",实际 ESD 格式和 WIM 格式,也一样是可以集成驱动做成二次封装的快 ...

  5. Android对接微信登录记录

    Android对接微信登录记录 - Stars-One的杂货小窝 Android项目要对接下微信登录,稍微记录下踩坑点 代码 1.添加依赖 implementation 'com.tencent.mm ...

  6. DVWA File Inclusion(文件包含)全等级

    File Inclusion(文件包含) 目录: File Inclusion(文件包含) 前言 PHP伪协议 1.Low get webshell 本地文件包含 远程文件包含 2.Medium 3. ...

  7. C#开源的一款友好的.NET SDK管理器

    前言 今天推荐一款由C#开源的.友好的.NET SDK管理器:Dots. 工具介绍 Dots 是一款 .NET SDK 管理器,可让您轻松安装.卸载和切换 .NET SDK.它是一款跨平台工具,可在 ...

  8. GOF23--23种设计模式(三)

    一.桥接模式 Java中的桥接模式(Bridge Pattern)是一种结构性设计模式,它将抽象部分和实现部分分离,使它们可以独立变化,同时通过桥接对象将它们连接起来. 这种模式将抽象与其实现解耦,使 ...

  9. java中synchronized和ReentrantLock的加锁和解锁能在不同线程吗?如果能,如何实现?

    java中synchronized和ReentrantLock的加锁和解锁能在不同线程吗?如果能,如何实现? 答案2023-06-21: java的: 这个问题,我问了一些人,部分人是回答得有问题的. ...

  10. 【好书推荐】《Python黑魔法指南》-附高清PDF版

    摘要:<Python 黑魔法手册.pdf >作者(明哥)是一个从事云计算多年的 Python 重度用户,它把自已多年的 Python 编码经验整理成小册子,没有长篇大论,半天就能全能掌握, ...