摘要:本篇內(nèi)容為機器學習實戰(zhàn)第章支持向量機部分程序清單。支持向量機優(yōu)點泛化錯誤率低,計算開銷不大,結(jié)果易解釋。注以上給出的僅是簡化版算法的實現(xiàn),關于完整的算法加速優(yōu)化并應用核函數(shù),請參照機器學習實戰(zhàn)第頁。
本篇內(nèi)容為《機器學習實戰(zhàn)》第 6 章 支持向量機部分程序清單。所用代碼為 python3。
支持向量機
優(yōu)點:泛化錯誤率低,計算開銷不大,結(jié)果易解釋。
缺點:對參數(shù)調(diào)節(jié)和核函數(shù)的選擇敏感,原始分類器不加修改僅適用于處理二分類問題。
適用數(shù)據(jù)類型:數(shù)值型和標稱型數(shù)據(jù)。
1996 年,John Platt 發(fā)布了一個稱為SMO的強大算法,用于訓練 SVM。SMO表示序列最小優(yōu)化 (Sequential Minimal Optimization)。
SMO算法的工作原理是:每次循環(huán)中選擇兩個alpha進行優(yōu)化處理。一旦找到一對合適的alpha,那么就增大其中一個同時減小另一個。這里的“合適”是指兩個alpha必須要符合一定的條件,第一個條件是這兩個alpha必須要在間隔邊界之外,第二個條件是這兩個alpha還沒有進行過區(qū)間化處理或者不在邊界上。
應用簡化版 SMO 算法處理小規(guī)模數(shù)據(jù)集下面給出簡化版的SMO算法程序清單。
該SMO函數(shù)的偽代碼如下:
創(chuàng)建一個alpha向量并將其初始化為 0 向量
當?shù)螖?shù)小于最大迭代次數(shù)時(外循環(huán))
···對數(shù)據(jù)集中的每個數(shù)據(jù)向量(內(nèi)循環(huán)):
······如果該數(shù)據(jù)向量可以被優(yōu)化:
·········隨機選擇另外一個數(shù)據(jù)向量
·········同時優(yōu)化這兩個向量
·········如果兩個向量都不能被優(yōu)化,退出內(nèi)循環(huán)
···如果所有向量都沒被優(yōu)化,增加迭代數(shù)目,繼續(xù)下一次循環(huán)
# coding=utf-8 # import sys from numpy import * def loadDataSet(): dataMat = [] labelMat = [] fr = open("testSet.txt") for line in fr.readlines(): lineArr = line.strip().split(" ") dataMat.append([float(lineArr[0]), float(lineArr[1])]) labelMat.append(float(lineArr[2])) return dataMat, labelMat # i 是第一個 alpha 的下標, m 是所有 alpha 的數(shù)目 # 只要函數(shù)值不等于輸入值 i,函數(shù)就會進行隨機選擇 def selectJrand(i, m): j = i while (j == i): j = int(random.uniform(0, m)) return j # 用于調(diào)整大于 H 或小于 L 的 alpha 值 def clipAlpha(aj, H, L): if aj > H: aj = H if L > aj: aj = L return aj
在 python 提示符下,執(zhí)行代碼并得到結(jié)果:
>>> import svmMLiA >>> dataArr, labelArr = svmMLiA.loadDataSet() >>> labelArr [-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0]
可以看出,這里采用的類別標簽是 -1 和 1。
# 參數(shù):數(shù)據(jù)集,類別標簽,常數(shù)C,容錯率,退出前最大的循環(huán)次數(shù) def smoSimple(dataMatIn, classLabels, C, toler, maxIter): dataMatrix = mat(dataMatIn) # 由于轉(zhuǎn)置了類別標簽,我們得到的是一個列向量而不是列表 labelMat = mat(classLabels).transpose() b = 0 m,n = shape(dataMatrix) # 構(gòu)建一個 alpha 列矩陣,矩陣中元素都初始化為0 alphas = mat(zeros((m, 1))) # iter 變量存儲的是在沒有任何 alpha 改變的情況下便利數(shù)據(jù)集的次數(shù) # 當這個變量達到輸入值 maxIter 時,函數(shù)結(jié)束運行并退出 iter = 0 while(iter < maxIter): # 每次循環(huán)當中,將 alphaPairsChanged 先設為0,在對整個集合順序遍歷 # 變量 alphaPairsChanged 用于記錄 alpha 是否已經(jīng)進行優(yōu)化 alphaPairsChanged = 0 for i in range(m): # 計算 fXi,即我們預測的類別 fXi = float(multiply(alphas, labelMat).T * (dataMatrix*dataMatrix[i,:].T) + b) # 與真實值比對,計算誤差 Ei Ei = fXi - float(labelMat[i]) # 如果誤差很大,可以對該數(shù)據(jù)實例所對應的 alpha 值進行優(yōu)化 # 不論正間隔還是負間隔都會被測試 # 檢查 alpha 值,保證其不能等于 0 或 C if((labelMat[i]*Ei < -toler) and (alphas[i] < C) or (labelMat[i]*Ei > toler) and (alphas[i] > 0)): # 用輔助函數(shù) selectJrand 隨機選擇第二個 alpha 值,即 alpha[j] j = selectJrand(i,m) # 同樣計算誤差 fXj = float(multiply(alphas, labelMat).T * (dataMatrix*dataMatrix[j,:].T)) + b Ej = fXj - float(labelMat[j]) alphaIold = alphas[i].copy() alphaJold = alphas[j].copy() # 計算 L 和 H,調(diào)整 alpha 到 0 與 C 之間 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]) if L==H: print("L == H") continue # eta 是 alpha[j] 的最優(yōu)修改量 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 # 計算出一個新的 alpha[j],并進行調(diào)整 alphas[j] -= labelMat[j] * (Ei - Ej) / eta alphas[j] = clipAlpha(alphas[j], H, L) # 檢查 alpha[j] 是否有輕微改變,是的話則退出 for 循環(huán) if(abs(alphas[j] - alphaJold) < 0.00001): print("j not moving enough") continue # 對 alpha[i] 進行和 alpha[j] 同樣的改變 # 改變的大小一樣,方向正好相反 alphas[i] += labelMat[j] * labelMat[i] * (alphaJold - alphas[j]) # 對 alpha[i] 和 alpha[j] 進行優(yōu)化之后,給它們設置一個常數(shù)項 b 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(alphaPairsChanged == 0): iter += 1 else: iter = 0 print("iteration number: %d" % iter) return b, alphas
在 python 提示符下,執(zhí)行代碼并得到結(jié)果:
b, alphas = svmMLiA.smoSimple(dataArr, labelArr, 0.6, 0.001, 40)
再執(zhí)行:
>>> for i in range(100): ... if alphas[i] > 0.0: ... print(dataArr[i], labelArr[i]) ... [3.542485, 1.977398] -1.0 [7.108772, -0.986906] 1.0 [4.658191, 3.507396] -1.0 [7.40786, -0.121961] 1.0 [3.457096, -0.082216] -1.0 [5.286862, -2.358286] 1.0 [6.080573, 0.418886] 1.0 [6.543888, 0.433164] 1.0 [1.966279, -1.840439] -1.0
所輸出的數(shù)據(jù)點即為支持向量。
注:以上給出的僅是簡化版SMO算法的實現(xiàn),關于完整的SMO算法加速優(yōu)化并應用核函數(shù),請參照《機器學習實戰(zhàn)》第 99 頁。
不足之處,歡迎指正。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/42399.html
摘要:根據(jù)錯誤率決定是否回退到訓練階段,通過改變迭代的次數(shù)和步長等參數(shù)來得到更好的回歸系數(shù)。使用回歸方法進行分類所需做的是把測試集上每個特征向量乘以最優(yōu)化方法得來的回歸系數(shù),再將該乘積結(jié)果求和,最后輸入到函數(shù)即可。 本篇內(nèi)容為《機器學習實戰(zhàn)》第 5 章 Logistic 回歸程序清單。 書中所用代碼為 python2,下面給出的程序清單是在 python3 中實踐改過的代碼,希望對你有幫助。...
閱讀 3298·2021-11-15 11:37
閱讀 1119·2021-11-02 14:45
閱讀 3925·2021-09-04 16:48
閱讀 3606·2019-08-30 15:55
閱讀 783·2019-08-23 17:53
閱讀 1016·2019-08-23 17:03
閱讀 2060·2019-08-23 16:43
閱讀 2211·2019-08-23 16:22