赞
踩
#导入相关的库,这里的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]:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。