机器学习:SVM的最朴素代码实现,第一个变量遍历样本获得,第二个变量随机选择
生活随笔
收集整理的這篇文章主要介紹了
机器学习:SVM的最朴素代码实现,第一个变量遍历样本获得,第二个变量随机选择
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- SVM的最樸素代碼實(shí)現(xiàn):
- 代碼實(shí)現(xiàn):
- 第一個(gè)變量遍歷樣本獲得,主要步驟如下:
- 第二個(gè)變量隨機(jī)選擇:
- 計(jì)算w:
- 其他:
SVM的最樸素代碼實(shí)現(xiàn):
算法簡(jiǎn)單步驟:
1、遍歷樣本作為第一個(gè)變量a1,根據(jù)舊的a和b求得誤差,滿足KKT條件換下一個(gè)樣本;不滿足,
2、不滿足的話,隨機(jī)選取第二個(gè)變量a2(不能和第一個(gè)相同);
3、根據(jù)解析式求得a2;
4、根據(jù)解析式求a2的約束上界和下界;
5、根據(jù)4的約束求得新的a2;
6、根據(jù)解析式求得a1;
7、根據(jù)解析式求得b;
8、返回到第一步根據(jù)新得a和b求誤差
代碼實(shí)現(xiàn):
第一個(gè)變量遍歷樣本獲得,主要步驟如下:
def smoSimple(dataMatIn, classLabels, C, toler, maxIter):"""簡(jiǎn)化版SMO算法:param dataMatIn: X:param classLabels: Y:param C: 懲罰參數(shù):param toler: 容錯(cuò)率:param maxIter: 最大循環(huán)次數(shù):return:"""dataMatrix = np.array(dataMatIn)# 備注針對(duì)行向量轉(zhuǎn)化為列向量需要添加[]labelMat = np.array([classLabels]).Tb = 0m,n = np.shape(dataMatrix) # m:=訓(xùn)練實(shí)例的個(gè)數(shù);n:=每個(gè)實(shí)例的維度alphas = np.zeros((m,1),dtype=float)# 迭代次數(shù)iter = 0while (iter < maxIter):alphaPairsChanged = 0 #alpha是否已經(jīng)進(jìn)行了優(yōu)化# 遍歷樣本點(diǎn)for i in range(m):# 在初始的alpha下計(jì)算每一個(gè)樣本點(diǎn)的預(yù)測(cè)值# w = alpha * y * x; f(x_i) = w^T * x_i + bw_ = np.dot(np.multiply(alphas,labelMat).T,dataMatrix)fXi = np.dot(w_, dataMatrix[i,:].T) + b # fXi = float(np.multiply(alphas,labelMat).T*dataMatrix*dataMatrix[i,:].T) + b # 計(jì)算預(yù)測(cè)值和實(shí)際值的誤差Ei = fXi - float(labelMat[i]) #得到誤差,如果誤差太大,檢查是否可能被優(yōu)化 # y[i]*g(x_i)-1 <0 and alphas[i] < C,這是違反KKT的情況# y[i]*g(x_i)-1 >0 and alphas[i] > 0,這個(gè)也是違反KKT的情況# 這里是簡(jiǎn)化處理,沒有選擇最嚴(yán)重的樣本點(diǎn),只要不滿足,就當(dāng)?shù)谝粋€(gè)變量找到了if ((labelMat[i]*Ei < -toler) and (alphas[i] < C)) or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)): #必須滿足約束# 隨機(jī)選擇第二個(gè)樣本點(diǎn)作為變量j = selectJrand(i,m)# 計(jì)算第二個(gè)樣本的預(yù)測(cè)值fXj = np.dot(np.multiply(alphas,labelMat).T,np.dot(dataMatrix,dataMatrix[j,:].T)) + b # fXj = float(np.multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[j,:].T)) + b# 計(jì)算第二個(gè)樣本的誤差Ej = fXj - float(labelMat[j])# alpha_i,alpha_j的舊值,教材中的α_1^old和α_2^oldalphaIold = alphas[i].copy(); alphaJold = alphas[j].copy() # 因?yàn)榇嬖诩s束,計(jì)算alpha_j的界if (labelMat[i] != labelMat[j]): # 兩者所在的對(duì)角線段端點(diǎn)的界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])# 假如alpha_j的上界=下界,退出本次選擇,選擇下一個(gè)樣本點(diǎn),# 因?yàn)閍lpha只有一個(gè)取值,假如alpha!=H就是無效的if L==H: print("L==H"); continue# 計(jì)算-dK# Eta = -(2 * K12 - K11 - K22),且Eta非負(fù),此處eta = -Eta則非正eta = 2.0 * np.dot(dataMatrix[i,:],dataMatrix[j,:].T) - np.dot(dataMatrix[i,:],dataMatrix[i,:].T) - np.dot(dataMatrix[j,:],dataMatrix[j,:].T)if eta >= 0: print("eta>=0"); continue# 根據(jù)解析式求alpha_jalphas[j] -= labelMat[j]*(Ei - Ej)/eta# 根據(jù)約束條件求得滿足約束的alpha_2alphas[j] = clipAlpha(alphas[j],H,L)#如果內(nèi)層循環(huán)通過以上方法選擇的α_2不能使目標(biāo)函數(shù)有足夠的下降,那么放棄α_1if (abs(alphas[j] - alphaJold) < 0.00001): print("j not moving enough"); continue# 根據(jù)解析式結(jié)果計(jì)算α_1alphas[i] += labelMat[j]*labelMat[i]*(alphaJold - alphas[j])# 根據(jù)解析式計(jì)算b,可以求出2個(gè)b,根據(jù)是否滿足KKT條件,如果兩者均0<a<C滿足KKT,b1 = b2# 如果a_1,a_2是0或者C,那么在b1,b2之間的b都是可行b,求他們均值就行了b1 = b - Ei- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i,:]*dataMatrix[i,:].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[i,:]*dataMatrix[j,:].Tb2 = b - Ej- labelMat[i]*(alphas[i]-alphaIold)*dataMatrix[i,:]*dataMatrix[j,:].T - labelMat[j]*(alphas[j]-alphaJold)*dataMatrix[j,:]*dataMatrix[j,:].Tif (0 < alphas[i]) and (C > alphas[i]): b = b1elif (0 < alphas[j]) and (C > alphas[j]): b = b2else: b = (b1 + b2)/2.0# 標(biāo)記一下該樣本修改alphaPairsChanged += 1print("iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged))# 假如所有的樣本都遍歷了一遍,沒有不滿足kkt的樣本點(diǎn),迭代次數(shù)加1if (alphaPairsChanged == 0): iter += 1# 只要一次迭代里面修改過alpha,就重復(fù)本次迭代else: iter = 0print("iteration number: %d" % iter)return b,alphas第二個(gè)變量隨機(jī)選擇:
def selectJrand(i,m):"""隨機(jī)從0到m挑選一個(gè)不等于i的數(shù):param i::param m::return:"""j=i #排除iwhile (j==i):j = int(np.random.uniform(0,m))return j計(jì)算w:
w是非必須計(jì)算的,因?yàn)樗褪莂lpha的組合而已。
def calcWs(alphas,dataArr,classLabels):"""根據(jù)支持向量計(jì)算分離超平面(w,b)的w參數(shù):param alphas:拉格朗日乘子向量:param dataArr:數(shù)據(jù)集x:param classLabels:數(shù)據(jù)集y:return: w=∑alphas_i*y_i*x_i"""X = np.array(dataArr); labelMat = np.array([classLabels]).transpose()m,n = np.shape(X)w = np.zeros((n,1))for i in range(m):w += np.multiply(alphas[i]*labelMat[i],X[i,:].T)return w其他:
def clipAlpha(aj,H,L):"""將aj剪裁到L(ow)和H(igh)之間:param aj::param H::param L::return:"""if aj > H:aj = Hif L > aj:aj = Lreturn ajdef loadDataSet(fileName):"""加載數(shù)據(jù)集:param fileName::return:"""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總結(jié)
以上是生活随笔為你收集整理的机器学习:SVM的最朴素代码实现,第一个变量遍历样本获得,第二个变量随机选择的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习:SVM训练,SMO算法描述,启
- 下一篇: 机器学习:SVM代码实现,朴素实现基础上