日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

支持向量机—核函数源码分析(2)

發(fā)布時(shí)間:2024/9/20 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 支持向量机—核函数源码分析(2) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本代碼用的是徑向基核函數(shù),徑向基函數(shù)是一個(gè)采用向量作為自變量的函數(shù),能夠基于向量距離運(yùn)算輸出一個(gè)標(biāo)量。
所謂徑向基函數(shù) (Radial Basis Function 簡(jiǎn)稱(chēng) RBF), 就是某種沿徑向?qū)ΨQ(chēng)的標(biāo)量函數(shù)。 通常定義為空間中任一點(diǎn)x到某一中心xc之間歐氏距離的單調(diào)函數(shù) , 可記作 k(||x?xc||), 其作用往往是局部的 , 即當(dāng)x遠(yuǎn)離xc時(shí)函數(shù)取值很小。最常用的徑向基函數(shù)是高斯核函數(shù) ,形式為k(||x?xc||)=exp(?||X?XC||22σ2) 其中xc為核函數(shù)中心,σ為函數(shù)的寬度參數(shù) , 控制了函數(shù)的徑向作用范圍。——百度

其中σ是用戶定義的用于確定到達(dá)率,或者說(shuō)函數(shù)值跌落到0的速度參數(shù)。

# -*- coding: utf-8 -*- """ Created on Sun Oct 22 09:44:54 2017@author: LiLong """ from numpy import * from time import sleepdef 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,labelMatdef selectJrand(i,m):j=i while (j==i):j = int(random.uniform(0,m))return jdef clipAlpha(aj,H,L):if aj > H: aj = Hif L > aj:aj = Lreturn aj# 核轉(zhuǎn)換函數(shù) def kernelTrans(X, A, kTup): # X是所有的支持向量,A是數(shù)據(jù)集每個(gè)樣本向量,KTup是核函數(shù)的參數(shù)元組m,n = shape(X)K = mat(zeros((m,1))) # 構(gòu)建一個(gè)列向量if kTup[0]=='lin': K = X * A.T # 如果核函數(shù)是線性核函數(shù),elif kTup[0]=='rbf': # 如果是徑向基核函數(shù)for j in range(m):deltaRow = X[j,:] - AK[j] = deltaRow*deltaRow.TK = exp(K/(-1*kTup[1]**2)) # 計(jì)算高斯核函數(shù),注意元素間的除法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 = dataMatInself.labelMat = classLabelsself.C = Cself.tol = tolerself.m = shape(dataMatIn)[0]self.alphas = mat(zeros((self.m,1)))self.b = 0self.eCache = mat(zeros((self.m,2))) self.K = mat(zeros((self.m,self.m)))for i in range(self.m):self.K[:,i] = kernelTrans(self.X, self.X[i,:], kTup)def calcEk(oS, k):fXk = float(multiply(oS.alphas,oS.labelMat).T*oS.K[:,k] + oS.b)Ek = fXk - float(oS.labelMat[k])return Ekdef selectJ(i, oS, Ei): maxK = -1; maxDeltaE = 0; Ej = 0oS.eCache[i] = [1,Ei] validEcacheList = 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 = Ekreturn maxK, Ejelse: j = selectJrand(i, oS.m)Ej = calcEk(oS, j)return j, Ejdef updateEk(oS, k):Ek = calcEk(oS, k)oS.eCache[k] = [1,Ek]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 0eta = 2.0 * oS.K[i,j] - oS.K[i,i] - oS.K[j,j] # 不同于不使用核函數(shù)的代碼if eta >= 0: print "eta>=0"; return 0oS.alphas[j] -= oS.labelMat[j]*(Ei - Ej)/etaoS.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 0oS.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 = b1elif (0 < oS.alphas[j]) and (oS.C > oS.alphas[j]): oS.b = b2else: oS.b = (b1 + b2)/2.0return 1else: return 0def smoP(dataMatIn, classLabels, C, toler, maxIter,kTup=('lin', 0)): oS = optStruct(mat(dataMatIn),mat(classLabels).transpose(),C,toler, kTup)iter = 0entireSet = True; alphaPairsChanged = 0while (iter < maxIter) and ((alphaPairsChanged > 0) or (entireSet)):alphaPairsChanged = 0if entireSet: for i in range(oS.m): alphaPairsChanged += innerL(i,oS)print "fullSet, iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged)iter += 1else:nonBoundIs = 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 += 1if entireSet: entireSet = False elif (alphaPairsChanged == 0): entireSet = True print "iteration number: %d" % iterreturn oS.b,oS.alphasdef 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# 利用核函數(shù)進(jìn)行分類(lèi)的徑向基函數(shù)測(cè)試函數(shù) def testRbf(k1=1.3):dataArr,labelArr = loadDataSet('testSetRBF.txt')b,alphas = smoP(dataArr, labelArr, 200, 0.0001, 10000, ('rbf', k1)) # 核函數(shù)的類(lèi)型是高斯核函數(shù)datMat=mat(dataArr); labelMat = mat(labelArr).transpose()svInd=nonzero(alphas.A>0)[0]sVs=datMat[svInd] #得到支持向量labelSV = labelMat[svInd]; # 得到支持向量的標(biāo)簽print "there are %d Support Vectors" % shape(sVs)[0]m,n = shape(datMat)errorCount = 0for i in range(m): # 利用核函數(shù)進(jìn)行分類(lèi)# svs是所有的支持向量,datmat[i,:]是每個(gè)樣本數(shù)據(jù)kernelEval = kernelTrans(sVs,datMat[i,:],('rbf', k1)) predict=kernelEval.T * multiply(labelSV,alphas[svInd]) + bif sign(predict)!=sign(labelArr[i]): errorCount += 1print "the training error rate is: %f" % (float(errorCount)/m)dataArr,labelArr = loadDataSet('testSetRBF2.txt')errorCount = 0datMat=mat(dataArr); labelMat = mat(labelArr).transpose()m,n = shape(datMat)for i in range(m):kernelEval = kernelTrans(sVs,datMat[i,:],('rbf', k1))predict=kernelEval.T * multiply(labelSV,alphas[svInd]) + bif sign(predict)!=sign(labelArr[i]): errorCount += 1 print "the test error rate is: %f" % (float(errorCount)/m) testRbf()

需要注意的就是核函數(shù)的應(yīng)用,和普通的Platt SMO有幾處不同,還有就是kernelTrans函數(shù)是如何利用核函數(shù)進(jìn)行分類(lèi)的,我手寫(xiě)了下代碼過(guò)程:

和代碼對(duì)應(yīng)起來(lái)就是高斯核函數(shù)的應(yīng)用過(guò)程。

運(yùn)行結(jié)果:

L==H fullSet, iter: 0 i:0, pairs changed 0 fullSet, iter: 0 i:1, pairs changed 1 fullSet, iter: 0 i:2, pairs changed 2 fullSet, iter: 0 i:3, pairs changed 3 fullSet, iter: 0 i:4, pairs changed 3 ..., fullSet, iter: 5 i:92, pairs changed 0 fullSet, iter: 5 i:93, pairs changed 0 j not moving enough fullSet, iter: 5 i:94, pairs changed 0 fullSet, iter: 5 i:95, pairs changed 0 fullSet, iter: 5 i:96, pairs changed 0 fullSet, iter: 5 i:97, pairs changed 0 fullSet, iter: 5 i:98, pairs changed 0 fullSet, iter: 5 i:99, pairs changed 0 iteration number: 6 there are 26 Support Vectors the training error rate is: 0.090000 the test error rate is: 0.180000

可以更換不同的k1參數(shù)以觀察測(cè)試錯(cuò)誤率,訓(xùn)練錯(cuò)誤率,支持向量個(gè)數(shù)隨k1的變化情況。
σ太小的話,支持向量變多;σ太大,其支持向量的數(shù)目少了很多,并且測(cè)試錯(cuò)誤率也在下降。所以σ值的設(shè)置在某處存在著最優(yōu)值,如果降低σ,那么訓(xùn)練錯(cuò)誤率就會(huì)降低,但是測(cè)試錯(cuò)誤率卻在上升。
支持向量機(jī)的數(shù)目存在一個(gè)最優(yōu)值。SVM的優(yōu)點(diǎn)在于它對(duì)數(shù)據(jù)的高效分類(lèi)。如果支持向量太少,就會(huì)得到一個(gè)很差的決策邊界;如果支持向量太多,也就相當(dāng)于每次都會(huì)利用整個(gè)數(shù)據(jù)集進(jìn)行分類(lèi),這種分類(lèi)方法稱(chēng)為k近鄰。

手寫(xiě)識(shí)別問(wèn)題回顧

基于SVM的數(shù)字識(shí)別

  • 收集數(shù)據(jù):提供的文本文件
  • 準(zhǔn)備數(shù)據(jù):基于二值圖像構(gòu)造向量
  • 分析數(shù)據(jù):對(duì)圖像向量進(jìn)行目測(cè)
  • 訓(xùn)練算法:采用兩種不同的核函數(shù),并對(duì)徑向基核函數(shù)采用不同的設(shè)置來(lái)運(yùn)行SMO算法。
  • 測(cè)試算法:編寫(xiě)一個(gè)函數(shù)來(lái)測(cè)試不同的核函數(shù)并計(jì)算錯(cuò)誤率
  • 使用算法:一個(gè)圖像識(shí)別的完整應(yīng)用還需要一些圖像處理的知識(shí),這里不再介紹。
  • # -*- coding: utf-8 -*- """ Created on Sun Oct 22 09:44:54 2017""" # -*- coding: utf-8 -*- """ Created on Sun Oct 22 09:44:54 2017@author: LiLong """ from numpy import * from time import sleepdef 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,labelMatdef selectJrand(i,m):j=i while (j==i):j = int(random.uniform(0,m))return jdef clipAlpha(aj,H,L):if aj > H: aj = Hif L > aj:aj = Lreturn aj# 核轉(zhuǎn)換函數(shù) def kernelTrans(X, A, kTup): # X是所有的支持向量,A是數(shù)據(jù)集每個(gè)樣本向量,KTup是核函數(shù)的參數(shù)元組m,n = shape(X)K = mat(zeros((m,1))) # 構(gòu)建一個(gè)列向量if kTup[0]=='lin': K = X * A.T # 如果核函數(shù)是線性核函數(shù),elif kTup[0]=='rbf': # 如果是徑向基核函數(shù)for j in range(m):deltaRow = X[j,:] - AK[j] = deltaRow*deltaRow.TK = exp(K/(-1*kTup[1]**2)) # 計(jì)算高斯核函數(shù),注意元素間的除法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 = dataMatInself.labelMat = classLabelsself.C = Cself.tol = tolerself.m = shape(dataMatIn)[0]self.alphas = mat(zeros((self.m,1)))self.b = 0self.eCache = mat(zeros((self.m,2))) self.K = mat(zeros((self.m,self.m)))for i in range(self.m):self.K[:,i] = kernelTrans(self.X, self.X[i,:], kTup)def calcEk(oS, k):fXk = float(multiply(oS.alphas,oS.labelMat).T*oS.K[:,k] + oS.b)Ek = fXk - float(oS.labelMat[k])return Ekdef selectJ(i, oS, Ei): maxK = -1; maxDeltaE = 0; Ej = 0oS.eCache[i] = [1,Ei] validEcacheList = 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 = Ekreturn maxK, Ejelse: j = selectJrand(i, oS.m)Ej = calcEk(oS, j)return j, Ejdef updateEk(oS, k):Ek = calcEk(oS, k)oS.eCache[k] = [1,Ek]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 0eta = 2.0 * oS.K[i,j] - oS.K[i,i] - oS.K[j,j] # 不同于不使用核函數(shù)的代碼if eta >= 0: print "eta>=0"; return 0oS.alphas[j] -= oS.labelMat[j]*(Ei - Ej)/etaoS.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 0oS.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 = b1elif (0 < oS.alphas[j]) and (oS.C > oS.alphas[j]): oS.b = b2else: oS.b = (b1 + b2)/2.0return 1else: return 0def smoP(dataMatIn, classLabels, C, toler, maxIter,kTup=('lin', 0)): oS = optStruct(mat(dataMatIn),mat(classLabels).transpose(),C,toler, kTup)iter = 0entireSet = True; alphaPairsChanged = 0while (iter < maxIter) and ((alphaPairsChanged > 0) or (entireSet)):alphaPairsChanged = 0if entireSet: for i in range(oS.m): alphaPairsChanged += innerL(i,oS)print "fullSet, iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged)iter += 1else:nonBoundIs = 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 += 1if entireSet: entireSet = False elif (alphaPairsChanged == 0): entireSet = True print "iteration number: %d" % iterreturn oS.b,oS.alphasdef 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 wdef img2vector(filename):returnVect = zeros((1,1024))fr = open(filename)for i in range(32):lineStr = fr.readline()for j in range(32):returnVect[0,32*i+j] = int(lineStr[j])return returnVectdef loadImages(dirName): from os import listdirhwLabels = []trainingFileList = listdir(dirName) m = len(trainingFileList)trainingMat = zeros((m,1024))for i in range(m):fileNameStr = trainingFileList[i]fileStr = fileNameStr.split('.')[0] classNumStr = int(fileStr.split('_')[0])if classNumStr == 9: hwLabels.append(-1)else: hwLabels.append(1)trainingMat[i,:] = img2vector('%s/%s' % (dirName, fileNameStr))return trainingMat, hwLabels def testDigits(kTup=('rbf', 10)):dataArr,labelArr = loadImages('trainingDigits')b,alphas = smoP(dataArr, labelArr, 200, 0.0001, 10000, kTup)datMat=mat(dataArr); labelMat = mat(labelArr).transpose()svInd=nonzero(alphas.A>0)[0]sVs=datMat[svInd] labelSV = labelMat[svInd];print "there are %d Support Vectors" % shape(sVs)[0]m,n = shape(datMat)errorCount = 0for i in range(m):kernelEval = kernelTrans(sVs,datMat[i,:],kTup)predict=kernelEval.T * multiply(labelSV,alphas[svInd]) + bif sign(predict)!=sign(labelArr[i]): errorCount += 1print "the training error rate is: %f" % (float(errorCount)/m)dataArr,labelArr = loadImages('testDigits')errorCount = 0datMat=mat(dataArr); labelMat = mat(labelArr).transpose()m,n = shape(datMat)for i in range(m):kernelEval = kernelTrans(sVs,datMat[i,:],kTup)predict=kernelEval.T * multiply(labelSV,alphas[svInd]) + bif sign(predict)!=sign(labelArr[i]): errorCount += 1 print "the test error rate is: %f" % (float(errorCount)/m) testDigits(('rbf', 20))

    函數(shù)loadImages()是已經(jīng)被重構(gòu)為自身的一個(gè)函數(shù),參考:KNN識(shí)別手寫(xiě)體數(shù)字
    其中有一個(gè)很大的區(qū)別是。在前面的KNN識(shí)別手寫(xiě)體中直接應(yīng)用類(lèi)別標(biāo)簽,既數(shù)字向量對(duì)應(yīng)相應(yīng)的數(shù)字大小,而同支持向量機(jī)一起使用時(shí),類(lèi)別標(biāo)簽為-1或者+1,因此,一旦碰到數(shù)字9,則輸出類(lèi)別標(biāo)簽-1,否則輸出+1。因?yàn)檫@里只做二分類(lèi),因此除了1和9之外的數(shù)字都被去掉了。

    運(yùn)行結(jié)果:

    . . . fullSet, iter: 3 i:398, pairs changed 0 L==H fullSet, iter: 3 i:399, pairs changed 0 fullSet, iter: 3 i:400, pairs changed 0 L==H fullSet, iter: 3 i:401, pairs changed 0 iteration number: 4 there are 47 Support Vectors the training error rate is: 0.004975 the test error rate is: 0.016129

    嘗試不同的σ值,并嘗試線性核函數(shù),得到:

    偷了個(gè)懶,這里是機(jī)器學(xué)習(xí)實(shí)戰(zhàn)中的結(jié)果。分析:

  • σ取10左右時(shí)可以得到最小的測(cè)試錯(cuò)誤率

    • 數(shù)據(jù)的不同,特征數(shù)的不同,得到的最佳σ<script type="math/tex" id="MathJax-Element-816">σ</script>值就會(huì)不同
    • 最小的訓(xùn)練錯(cuò)誤率并不對(duì)應(yīng)于最小的支持向量數(shù)目
    • 線性核函數(shù)的效果并不是特別的糟糕。

    總結(jié)

    以上是生活随笔為你收集整理的支持向量机—核函数源码分析(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。