svm核函数_机器学习实战:支持向量机(SVM)(五)在复杂数据上应用核函数

ac452df5e307b86c6f61527c9b9da107.png

一起探索机器学习

Machine learning

SVM

CSDN:

https://blog.csdn.net/weixin_45814668知乎:

https://www.zhihu.com/people/qiongjian0427Git:

https://github.com/qiongjian/Machine-learning/

运行环境:anaconda—jupyter notebook

Python版本:Python3

  648504be693b0e4c4b63fbc22abc23f7.png

利用核函数将数据映射到高维空间

824658558c531389e9449e3531589a21.png


 如上图所示,数据点处于一个圆中,人类的大脑能够意识到这一点,而对于分类器而言,它只能识别分类器的结果是大于0还是小于0。如果只在x和y轴构成的坐标系中插入直线进行分类的话,我们并不会得到理想的结果。我们或许可以对圆中的数据进行某种形式的转换,从而得到某些新的变量来表示数据。 将数据从一个特征空间转换到另一个特征空间,在新空间下,我们可以很容易利用已有的工具对数据进行处理,这个过程叫做从一个特征空间到另一个特征空间的映射。通常情况下,映射会将低维特征空间映射到高维特征空间。 这种从某个特征空间到另一个特征空间的映射是通过核函数来实现的。我们可以把核函数想象成一个包装器(wrapper)或者是接口(interface),它能把数据从某个很难处理的形式转换成为另一个较容易的处理的形式。 SVM优化中一个特别好的地方就是,所有的运算都可以写成内积(inner product,也称点积)的形式。向量的内积使之两个向量相乘,之后得到单个标量或者数值。我们可以把内积运算替换成核函数,而不必做简化处理。将内积替换成核函数的方式被称为核技巧(kernel trick)或者核“变电”(kernel substation)。  593e0fee5695076b6b5339554bf2f0f2.png

径向基核函数

‍径向基函数是SVM中常用的一个核函数。径向基函数是一个采用向量作为自变量的函数,能够基于向量距离运算输出一个标量。这个距离可以使从<0,0>向量或者其他向量开始计算的距离。径向基函数的高斯版本的具体公式为:

775719c1081941bffc6d71dd18540205.png

σ 是用户定义的用于确定到达率或者说函数值跌落到0的速度参数。
代码如下:
import matplotlib.pyplot as pltimport numpy as npimport randomdef kernelTrans(X, A, kTup):     m,n = np.shape(X)    K = np.mat(np.zeros((m,1)))    if kTup[0]=='lin': K = X * A.T       elif kTup[0]=='rbf':        for j in range(m):            deltaRow = X[j,:] - A            K[j] = deltaRow*deltaRow.T        K =np.exp(K/(-1*kTup[1]**2))     else: raise NameError('Houston We Have a Problem -- That Kernel is not recognized')    return Kclass optStruct:    def __init__(self,dataMatIn, classLabels, C, toler, kTup):         self.X = dataMatIn        self.labelMat = classLabels        self.C = C        self.tol = toler        self.m = np.shape(dataMatIn)[0]        self.alphas = np.mat(np.zeros((self.m,1)))        self.b = 0        self.eCache = np.mat(np.zeros((self.m,2)))         self.K = np.mat(np.zeros((self.m,self.m)))        for i in range(self.m):                            #计算所有数据的核K            self.K[:,i] = kernelTrans(self.X, self.X[i,:], kTup)

  ec22917cdcfb4b2f55c366ab420eb5d3.png

对innerL()和calcEk()函数进行修改

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].T - 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]) and (oS.C > oS.alphas[i]): oS.b = b1        elif (0 < oS.alphas[j]) and (oS.C > oS.alphas[j]): oS.b = b2        else: oS.b = (b1 + b2)/2.0        return 1    else: return 0
  6af21649eb43b6a00df6c44e1a5be040.png

在测试中使用核函数

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

用到的前面的函数

def loadDataSet(fileName):#打开文件并逐行解析    dataMat = []; labelMat = []    fr = open(fileName)    for line in fr.readlines():                                             lineArr = line.strip().split('\t')        dataMat.append([float(lineArr[0]), float(lineArr[1])]) #添加数据        labelMat.append(float(lineArr[2]))                      #添加标签    return dataMat,labelMat

def smoP(dataMatIn, classLabels, C, toler, maxIter, kTup = ('lin',0)):     oS = optStruct(np.mat(dataMatIn), np.mat(classLabels).transpose(), C, toler, kTup)      iter = 0    entireSet = True; alphaPairsChanged = 0        #如果迭代字数大于最大迭代数,或者遍历完整个集合还没有找到一对i和j可以优化,那么退出迭代    while (iter < maxIter) and ((alphaPairsChanged > 0) or (entireSet)):        alphaPairsChanged = 0        if entireSet:   #遍历所有的值            for i in range(oS.m):                        alphaPairsChanged += innerL(i,oS)  #innerL第二个选择alpha                print("fullSet, iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged))            iter += 1        else:#遍历非边界值            nonBoundIs = np.nonzero((oS.alphas.A > 0) * (oS.alphas.A < C))[0]            for i in nonBoundIs:                alphaPairsChanged += innerL(i,oS)                print("non-bound, iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged))            iter += 1                if entireSet: entireSet = False         elif (alphaPairsChanged == 0): entireSet = True          print("iteration number: %d" % iter)    return oS.b,oS.alphas

def calcEk(oS, k):    fXk = float(np.multiply(oS.alphas,oS.labelMat).T*(oS.K[:,k])) + oS.b    Ek = fXk - float(oS.labelMat[k])    return Ekdef selectJ(i, oS, Ei):#选择第二个alpha    maxK = -1; maxDeltaE = 0; Ej = 0    oS.eCache[i] = [1,Ei]      validEcacheList = np.nonzero(oS.eCache[:,0].A)[0]#构建一个非零表    if (len(validEcacheList)) > 1:        for k in validEcacheList:            if k == i: continue             Ek = calcEk(oS, k)            deltaE = abs(Ei - Ek)            if (deltaE > maxDeltaE):                maxK = k; maxDeltaE = deltaE; Ej = Ek        return maxK, Ej    else:           j = selectJrand(i, oS.m)        Ej = calcEk(oS, j)    return j, Ej#辅助函数1,随机选择一个整数def selectJrand(i, m):#i是alpha下标,m是alpha个数    j = i                                     while (j == i):        j = int(random.uniform(0, m))    return j#辅助函数2,调整大于H或小于L的alpha值def clipAlpha(aj,H,L):    if aj > H:        aj = H    if L > aj:        aj = L    return aj

def updateEk(oS, k):#计算误差值并返回缓存中    Ek = calcEk(oS, k)    oS.eCache[k] = [1,Ek]
  a099b84e0a98a30f0ff129157908c1a9.png

运行结果

de0ad8c3c2cbaecaae50627b2fe7d06b.png


      训练集错误率为9%,测试集错误率都是18%,训练耗时1.7s,26个支持向量。

可以尝试更换不同的K1参数以观察测试错误率、训练错误率、支持向量个数随k1的变化情况。 降低k1,训练集错误率低,但是测试集错误率高。 SVM的优点在于它能对数据进行高效分类。如果支持向量太少,就可能会得到一个很差的决策边界;如果支持向量太多,也就相当于每次都利用整个数据集进行分类,这种分类方法称为k近邻。 —— E N D ——

闹钟一响就起

走了就不回头

开开心心

3edd15215e4887fcaca7f73ab3a6a328.png

ID:qiongjian0427


关注我,一起学习机器学习~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值