#导入相关的库,这里的copy模块是为了后面做深拷贝用的
import numpy as np
import copy
import matplotlib.pyplot as plt
#读入本地的数据,读出来的数据格式都是列表形式的
def load_data(filename):
dataset=[]
labelset=[]
f=open(filename)
for line in f.readlines():
new_line=line.strip().split()
dataset.append([float(new_line[0]),float(new_line[1])])
labelset.append(int(new_line[2]))
return dataset,labelset
#随机在0到m之间选择一个整型数,用来进行一对alpha值的更新,SMO算法的思想是每次选取两个不同的alpha进行更新
def select_j(i,m):
"""parameter:i 表示第一个选定的alpha,对应第i行数据
m 表示数据集的总数
"""
j=-1
while(j==i):
j=int(np.random.uniform(0,m))
return j
#用来限定alpha值的上下限
def regular(H,L,a):
if a>H:
a=H
if a<L:
a=L
return a
#简化版的SMO算法的实现,最终返回模型需要的参数alpha和b,这里后面我直接紧接着根据alpha也把w求出来了。
#注意:自己亲测试过,简化版的算法实现起来确实稍显简单,但缺点是速度比较慢,这一点你可以在与后面的完整版
#实现进行比较一下就深有体会了。但是本人觉得最大的缺点并不是这个,二是这个模型很难拟合的比较理想,试过狠多参数
#c基本都是同样的结果,这一点我觉得可能是与完整版SMO算法在实现上的最大缺陷了。
#之所以称为简化版最主要的简化就是在于第二个alpha的选定上,是从第一个alpha所对应的样本除外的其他样本中随机选取一个alpha
def simple_SMO(data,label,C,toler,max_iters):
"""C:对于线性SVM来说,C是在调参时唯一需要调节的参数了,也是非常重要的参数,它的目的在于使得分离间隔尽可能大的同时也要保证
误分类点的个数尽可能少,调节二者平衡的重要参数。
toler:容错率,这是自己定义的误差范围,它的由来是由KKT条件决定的,本身的kkT是有三个约束条件,但是在用于程序判断时可以等效成
通过容错率来进行判断的两个条件,这个在于自己给定,无需进行调节。
max_iter:最大循环次数,用于控制外围的循环,防止无限制循环
"""
#整篇数据操作均把它转换成矩阵的形式,方便统一进行运算
data=np.mat(data)
label=np.mat(label).transpose()
m,n=np.shape(data)
alphas=np.mat(np.zeros((m,1)))
b=0
iter=0
while(iter<max_iters):
alpha_pairs_changed=0
for i in range(m):
Fxi=float(np.multiply(alphas,label).T*(data*data[i].T))+b
Ei=Fxi-float(label[i])
if ((label[i]*Ei<-toler) and (alphas[i]<C)) or ((label[i]*Ei>toler) and (alphas[i]>0)):#由kkt条件确定的,具体公式推导可见博客https://blog.csdn.net/youhuakongzhi/article/details/86660281
j=select_j(i,m)
Fxj=float(np.multiply(alphas,label).T*(data*data[j].T))+b
Ej=Fxj-float(label[j])
alphaIold=copy.deepcopy(alphas[i])#深拷贝
alphaJold=copy.deepcopy(alphas[j])
if label[i]!=label[j]:
SVM的完整实现代码及解释
最新推荐文章于 2024-07-04 23:13:55 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)