文章标题

来源:互联网 发布:云科数据云一体机 编辑:程序博客网 时间:2024/05/17 07:59

参考python机器学习实战和统计学习编写SVM(软间隔)

SVM分类器的实现:二分类方式 软间隔线性分类器:通过调整C的大小,来决定对数据差错的容忍度,C越高代表容忍差错的能力越低 使用二次规划的算法 SMO 求解: 更新方式:外层循环找到不符合KTT条件的变量,内层循环找到在第一个变量确定条件下,第二个变量改变步长最大 的变量进行更新,同时更新偏置量b 最重要的两层循环。

#SVM的实现,主要是二次规划#首先读取数据from numpy import *def loadData(fileName):    retData=[]    retLabel=[]    fr=open(fileName)    for line in fr.readlines():        curLine=line.strip().split('\t')        retData.append([float(curLine[0]),float(curLine[1])])        retLabel.append(float(curLine[2]))    return mat(retData),mat(retLabel).T#因为实际上是针对一个变量的优化 另一个变量随之变化,两者之间满足线性关系,#所以所求值有一个#产生新的下标值#计算g(x)class op:    def __init__(self,dataSet,label,C,totel):        self.X=dataSet        self.label=label        self.C=C        self.tol=totel        self.numRow=shape(dataSet)[0]        self.alpha=mat(zeros([self.numRow,1]))        self.b=0        self.eCache=mat(zeros([self.numRow,2]))def calcEk(oS,k):    Ek=float(multiply(oS.alpha,oS.label).T*(oS.X*oS.X[k,:].T))-float(oS.label[k])+oS.b    return Ekdef selectJ(i,oS,Ei):    maxIndex=-1    matDelta=0    Ej=0    oS.eCache[i]=[1,Ei]    lenValid=nonzero(oS.eCache[:,0].A)[0]    if (len(lenValid))>1:        for j in lenValid:            if(i==j): continue            tempE=calcEk(oS,j)            miu=abs(Ei-tempE)            if miu>matDelta:                matDelta=miu                Ej=tempE                maxIndex=j        return maxIndex,Ej    else:        j=selectJrand(i,oS)        Ej=calcEk(oS,j)    return j,Ejdef selectJrand(i,oS):    j=i    while(j==i):        j=int(random.uniform(0,oS.numRow))    return jdef updateE(i,oS):    Ek=calcEk(oS,i)    oS.eCache[i]=[1,Ek]def clipAlpha(alpha,L,H):    if alpha<L:        alpha=L    if alpha>H:        alpha=H    return alphadef innerL(i,os):    Ei=calcEk(os,i)    if (os.label[i]*Ei<-os.tol and os.alpha[i]<os.C) or(os.label[i]*Ei>os.tol and os.alpha[i]>0):        j,Ej=selectJ(i,os,Ei)        alphaIold=os.alpha[i].copy()        alphaJold=os.alpha[j].copy()        if os.label[i]!=os.label[j]:            L=max(0,alphaJold-alphaIold)            H=min(os.C,os.C+alphaJold-alphaIold)        else:            L=max(0,alphaJold+alphaIold-os.C)            H=min(os.C,alphaJold+alphaIold)        if L==H: return 0        eta=2.0*(os.X[j,:]*os.X[j,:].T)-os.X[i,:]*os.X[i,:].T-os.X[i,:]*os.X[j,:].T        if eta>=0:return 0        os.alpha[j]-=os.label[j]*(Ei-Ej)/eta        os.alpha[j]=clipAlpha(os.alpha[j],L,H)        updateE(j,os)        if abs(alphaJold-os.alpha[j])<0.001:            return 0        os.alpha[i]+=os.label[i]*os.label[j]*(alphaJold-os.alpha[j])        updateE(i,os)        #更新b        b1=os.b-Ei-os.label[i]*(os.alpha[i]-alphaIold)*os.X[i,:]*os.X[i,:].T-os.label[j]*(os.alpha[j]-alphaJold)*os.X[j,:]*os.X[i,:].T        b2=os.b-Ej-os.label[i]*(os.alpha[i]-alphaIold)*os.X[j,:]*os.X[i,:].T-os.label[j]*(os.alpha[j]-alphaJold)*os.X[j,:]*os.X[j,:].T        if os.alpha[i]>0 and os.alpha[i]<os.C:            os.b=b1        elif os.alpha[j]>0 and os.alpha[j]<os.C:            os.b=b2        else:            os.b=(b1+b2)/2.0        return 1    else:        return 0def smoP(fileName,C,totel,maxItr):    data,label=loadData(fileName)    os=op(data,label,C,totel)    itr=0    entier=True    p=0    while itr<maxItr and(p>0 or entier):        p=0        if entier:            for i in range(os.numRow):                p+=innerL(i,os)        else:            nonBoundIs=nonzero((os.alpha.A>0)*(os.alpha.A<C))[0]            for i in nonBoundIs:                p+=innerL(i,os)        itr+=1        print(itr)        if entier:entier=False        elif p==0:entier=True    return os.alpha,os.balpha,b=smoP('testSet.txt',100000,0.001,40) 

SVM软间隔分类,主要在于调整C 的大小 one class SVM 主要是调整nu的大小 ,nu代表差错数据的比例,通过调整nu来控制超球面的大小,以及异常点的比例

#展示SVM结果def calcWs(alphas,data,label):    m,n=shape(data)    w=zeros([n,1])    for i in range(m):        w+=multiply(alphas[i]*label[i],data[i,:].T)    return wdata,label=loadData('testSet.txt')w=calcWs(alpha,data,label)newLabel=[]m=shape(data)[0]numLabel=[]for i in range(m):    r=data[i]*mat(w)+b    numLabel.append(r)    if abs(r-1)<0.01or abs(r+1)<0.01:        newLabel.append(0)    elif r>0 :        newLabel.append(1)    elif r<0:        newLabel.append(-1)x=arange(0.0,10,0.5)y=(-(w[0][0]*x+b))/w[1][0]y=array(y)[0]  import matplotlib.pyplot as pltcol=['ro','g+']Slabel=[-1,1]plt.subplot(121)for i in range(2):    index=[j for j in range(m) if newLabel[j]==Slabel[i]]    plt.plot(data[index,0],data[index,1],col[i])index=index=[j for j in range(m) if newLabel[j]==0]plt.plot(data[index,0],data[index,1],'b*')plt.plot(x,y,'b-')plt.show()plt.subplot(122)for i in range(2):    index=[j for j in range(m) if label[j]==Slabel[i]]    plt.plot(data[index,0],data[index,1],col[i])plt.plot(x,y,'b-')plt.show()

这里写图片描述

原创粉丝点击