文章标题

参考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 Ek
def 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,Ej
def selectJrand(i,oS):
    j=i
    while(j==i):
        j=int(random.uniform(0,oS.numRow))
    return j
def 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 alpha
def 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 0
def 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.b
alpha,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 w
data,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 plt
col=['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()

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值