机器学习实战python实例(2)SVM与核函数

来源:互联网 发布:焊接软件那个好 编辑:程序博客网 时间:2024/05/19 16:33

前两篇博客涉及到的SVM还只是一个线性分类器,如果在二维情况下遇到如下的情况,线性分类器的效果就不会很好了这里写图片描述
这个时候我们就需要一个叫做核函数的东西,简单来说它的最大作用就是把低维数据映射到高维数据,具体可以看前面推荐的一篇文章http://www.thebigdata.cn/JieJueFangAn/12661.html中核函数的部分,这里借用两张图来演示效果
这里写图片描述这里写图片描述
这样我们就能分割开了,一个比较通俗的理解是:一个物体当你一个属性无法描述清楚时,就多增加几个属性来描述它,在无限个属性之内总能够描述清楚,而如何增加属性来描述它呢,需要的是核函数。

在之前的代码中,我们相当于使用了线性核函数(X*Xi.T),而这次为了分类如图的数据,我们需要使用径向基函数得高斯版本这里写图片描述
我们需要把之前涉及到线性核函数的部分替换掉,并且增加一部分用来计算和保存核函数
在前两篇的SVM.py中添加以下部分

def kernelTrans(X, A, kTup):    m, n = shape(X)    K = mat(zeros((m, 1)))    if kTup[0] == 'lin':        K = X * A.T    elif kTup[0] == 'rbf':        for j in xrange(m):            deltaRow = X[j, :] - A            K[j] = deltaRow * deltaRow.T        K = exp(K / (-1 * kTup[1] ** 2))    else:        raise NameError('Houston We Have a Problem -- That Kernel is not recognized')    return K

在SVM.py中修改以下部分:

class optStruct:    def __init__(self, dataMatIn, classLabels, C, toler, kTup):        self.X = dataMatIn        self.labelMat = classLabels        self.C = C        self.tol = toler        self.m = shape(dataMatIn)[0]        self.alphas = mat(zeros((self.m, 1)))        self.b = 0        self.eCache = mat(zeros((self.m, 2)))        self.K = mat(zeros((self.m, self.m)))        for i in xrange(self.m):            self.K[:, i] = kernelTrans(self.X, self.X[i, :], kTup)def innerL(i, oS):    Ei = calcEk(oS, i)    if ((oS.labelMat[i] * Ei < -oS.tol) and (oS.alphas[i] < oS.C))\            or ((oS.labelMat[i] * Ei > oS.tol) and (oS.alphas[i] > 0)):        j, Ej = selectJ(i, oS, Ei)        alphaIold = oS.alphas[i].copy()        alphaJold = oS.alphas[j].copy()        if oS.labelMat[i] != oS.labelMat[j]:            L = max(0, oS.alphas[j] - oS.alphas[i])            H = min(oS.C, oS.C + oS.alphas[j] - oS.alphas[i])        else:            L = max(0, oS.alphas[j] + oS.alphas[i] - oS.C)            H = min(oS.C, oS.alphas[j] + oS.alphas[i])        if L == H:            print "L == H"            return 0        eta = 2.0 * oS.K[i, j] - oS.K[i, i] - oS.K[j, j]        if eta >= 0:            print "eta >= 0"            return 0        oS.alphas[j] -= oS.labelMat[j] * (Ei - Ej) / eta        oS.alphas[j] = clipAlpha(oS.alphas[j], H, L)        updateEk(oS, j)        if abs(oS.alphas[j] - alphaJold) < 0.00001:            print "j not moving enough"            return 0        oS.alphas[i] += oS.labelMat[j] * oS.labelMat[i] * (alphaJold - oS.alphas[j])        updateEk(oS, i)        b1 = oS.b - Ei - oS.labelMat[i] * (oS.alphas[i] - alphaIold) * oS.K[i, i] \                - oS.labelMat[j] * (oS.alphas[j] - alphaJold) * oS.K[i, j]        b2 = oS.b - Ej - oS.labelMat[i] * (oS.alphas[i] - alphaIold) * oS.K[i, j] \                - oS.labelMat[j] * (oS.alphas[j] - alphaJold) * oS.K[j, j]        if 0 < oS.alphas[i] < oS.C:            oS.b = b1        elif 0 < oS.alphas[j] < oS.C:            oS.b = b2        else:            oS.b = (b1 + b2) / 2.0        return 1    else:        return 0def calcEk(oS, k):    fXk = float(multiply(oS.alphas, oS.labelMat).T * oS.K[:, k]) + oS.b    Ek = fXk - float(oS.labelMat[k])    return Ek

再加入一个函数来测试训练的分类器的效果

def testRbf(k1=1.3):    dataArr, labelArr = loadDataSet("testSetRBF.txt")    b, alphas = smoP(dataArr, labelArr, 200, 0.0001, 10000, ('rbf', k1))    dataMat = mat(dataArr)    labelMat = mat(labelArr).transpose()    svInd = nonzero(alphas.A > 0)[0]    sVs = dataMat[svInd]    labelSV = labelMat[svInd]    print "there are %d Support Vectors" % shape(sVs)[0]    m, n = shape(dataMat)    errorCount = 0    for i in xrange(m):        kernelEval = kernelTrans(sVs, dataMat[i, :], ('rbf', 1))        predict = kernelEval.T * multiply(labelSV, alphas[svInd]) + b        if sign(predict) != sign(labelMat[i]):            errorCount += 1    print "the training error rate is: %f" % (float(errorCount) / m)    dataArr, labelArr = loadDataSet("testSetRBF2.txt")    dataMat = mat(dataArr)    labelMat = mat(labelArr).transpose()    m, n = shape(dataMat)    errorCount = 0    for i in xrange(m):        kernelEval = kernelTrans(sVs, dataMat[i, :], ('rbf', 1))        predict = kernelEval.T * multiply(labelSV, alphas[svInd]) + b        if sign(predict) != sign(labelMat[i]):            errorCount += 1    print "the test error rate is: %f" % (float(errorCount) / m)

直接调用SVM.testRbf(),错误率在10%左右,为了方便我画出了支持向量

def showRBF(dataArr, labelArr, alphas):    for i in xrange(len(labelArr)):        if labelArr[i] == -1:            plt.plot(dataArr[i][0], dataArr[i][1], 'or')        elif labelArr[i] == 1:            plt.plot(dataArr[i][0], dataArr[i][1], 'Dg')    dataMat = mat(dataArr)    svInd = nonzero(alphas.A > 0)[0]    sVs = dataMat[svInd]    for i in xrange(shape(sVs)[0]):        plt.plot(dataArr[i][0], dataArr[i][1], 'ob')    plt.show()

这里写图片描述

测试数据请下载http://download.csdn.net/detail/xiaonannanxn/9620023

0 0
原创粉丝点击