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