机器学习实战之SVM

1 算法概述
典型传统的SVM跟Logistic一样也是一个二分类问题,就是训练一个决策面,使数据最大程度的分布在决策面两侧。如下图所示:
这里写图片描述
中间的那条线就是一个决策面。使得图中O数据集与×数据集分布在决策面两侧。
上图中的函数可以写成这里写图片描述,对于位于线上的点,y=0,位于线上方的点,属于1类,此时y>0,位于线下方的点,属于-1类,此时y<0。对于一个点集分类,当决策面里数据点越远,也就是说决策面离数据点的“间隔”越大,比如上图中点C到中间那条线的距离越大,那么分类的确信度就越高,为了使决策面的分类确信度越高,那必然就得最大化这个“间隔”。如下图所示:
图2
那么问题又来了,怎样使得这个Gap最大呢?这里引入一个函数间隔这里写图片描述,这里y是类别的标签,只有+1,与-1两种情况,所以,当数据点为1类时且远离决策面时,这里写图片描述将是一个较大的数,从而这里写图片描述也将是一个较大的数;当数据点为-1类且远离决策面时,这里写图片描述将是一个很大的负数,再乘上-1,最终的这里写图片描述结果也将是一个较大的数。所以如果要找到“间隔”Gap最大的点,就是要找到离决策面最近的数据点,也就是必须找到支持向量。这里引入一个几何间隔这里写图片描述,现在就是想这个几何间隔最大化,那么现在的目标函数就是这里写图片描述,可以转化成这里写图片描述,就是在这里写图片描述下,使得这里写图片描述最大。
2 通过SMO实现w,b的最优
工作原理:首先初始化两个alpha,然后每循环进行优化处理,一旦找到两个“合适”的alpha,就同时进行相同的修改,但方向相反。这里的“合适”指的是满足一定条件,即两个alpha必须在间隔边界之外,不在间隔边界上。

def smoSimple(dataMatIn, classLabels, C, toler, maxIter):
    dataMatrix = mat(dataMatIn); labelMat = mat(classLabels).transpose() #transpose()求转置的函数
    b = 0; m,n = shape(dataMatrix) # m,n=shape(A):求矩阵A的大小,m返回矩阵的行,n返回矩阵的列,这里m=100 n=2
    alphas = mat(zeros((m,1)))#初始化alphas,整个SVM的目的就是求最优化的alphas与常数b
    iter = 0
    while (iter < maxIter):
        alphaPairsChanged = 0
        for i in range(m):
            #.T是Numpy当中实现的矩阵转置的方法,[i,:]是Numpy花式索引
            #这句话的意思是对每个样本预测类别
            fXi = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[i,:].T)) + b
            Ei = fXi - float(labelMat[i])#误差
            #不管样本属于正间隔范围还是负间隔范围其alpha都需要优化
            if ((labelMat[i]*Ei < -toler) and (alphas[i] < C)) or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)):
                j = selectJrand(i,m) #随机选择第二个alpha
                fXj = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[j,:].T)) + b
                Ej = fXj - float(labelMat[j])
                alphaIold = alphas[i].copy(); alphaJold = alphas[j].copy();
                #将alpha控制在0与C之间,L,H分别为alpha的最小与最大值
                if (labelMat[i] != labelMat[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])
                #当L==H,则alpha已经到了边界,成为了支持向量,就跳出内循环
                if L==H: print "L==H"; continue
                #eta表示对alpha的修改量
                eta = 2.0 * dataMatrix[i,:]*dataMatrix[j,:].T - dataMatrix[i,:]*dataMatrix[i,:].T\
                      - dataMatrix[j,:]*dataMatrix[j,:].T
                if eta >= 0: print "eta>=0"; continue
                alphas[j] -= labelMat[j]*(Ei - Ej)/eta
                alphas[j] = clipAlpha(alphas[j],H,L)
                if (abs(alphas[j] - alphaJold) < 0.00001): print "j not moving enough"; continue
                alphas[i] += labelMat[j]*labelMat[i]*(alphaJold - alphas[j])#update i by the same amount as j
                                                                        #the update is in the oppostie direction
                b1 = b - Ei- labelMat[i]*(alphas[i]-alphaIold)*\
                      dataMatrix[i,:]*dataMatrix[i,:].T - \
                     labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[i,:]*dataMatrix[j,:].T
                b2 = b - Ej- labelMat[i]*(alphas[i]-alphaIold)*\
                      dataMatrix[i,:]*dataMatrix[j,:].T -\
                      labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[j,:]*dataMatrix[j,:].T
                if (0 < alphas[i]) and (C > alphas[i]): b = b1
                elif (0 < alphas[j]) and (C > alphas[j]): b = b2
                else: b = (b1 + b2)/2.0
                alphaPairsChanged += 1
                print "iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged)
        if (alphaPairsChanged == 0): iter += 1
        else: iter = 0
        print "iteration number: %d" % iter
    return b,alphas

求得最优化alphas系列 与b两组参数之后,就很容易计算权重向量,进而,得到分隔面。

def calcWs(alphas,dataArr,classLabels):
    X = mat(dataArr); labelMat = mat(classLabels).transpose()
    m,n = shape(X)
    w = zeros((n,1))
    for i in range(m):
        w += multiply(alphas[i]*labelMat[i],X[i,:].T)
    return w

3 复杂数据集上应用的核函数
对于线性不可分的数据,SVM选择用核函数处理。就是通过核函数,它可以事先在低维空间上计算,然后将数据映射到高维空间,实现分类效果,也就是说,在高维空间解决线性问题等价于在低维空间解决非线性问题。如下图所示
这里写图片描述
首先,我们定义一下核函数:如果原始特征内积是这里写图片描述,映射后为这里写图片描述,那么定义核函数为:这里写图片描述。(这里的这里写图片描述表示从原始输入空间X到内积特征空间F的映射)
在高维特征空间中对训练数据通过超平面进行分类,避免了直接在原输入空间中寻找非线性函数来进行分类。支持向量机的分类函数具有这样的性质:它是一组以支持向量为参数的非线性函数的线性组合,因此分类函数的表达式仅和支持向量的数量有关,而独立于空间的维度。
用核函数进行分类:这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值