糖逗 发表于 2020-11-10 16:34:21

python实现SVM【软间隔】【SMO算法】

本帖最后由 糖逗 于 2020-11-10 16:39 编辑

参考书籍:《机器学习实战》

import numpy as np
from numpy import random

def loadDataSet(fileName):
    dataMat = []
    labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
      lineArr = line.strip().split('\t')
      dataMat.append(), float(lineArr)])
      labelMat.append(float(lineArr))
    return dataMat, labelMat

def selectJrand(i, m):
    j = i
    while(j == i):
      j = int(random.uniform(0, m))
    return j

def clipAlpha(aj, H, L):
    if aj > H:
      aj = H
    if L > aj:
      aj = L
    return aj


def smoSimple(dataMatIn, classLabels, C, toler, maxIter):
    dataMatrix = np.mat(dataMatIn)
    labelMat = np.mat(classLabels).transpose()
    b = 0; m,n = np.shape(dataMatrix)
    alphas = np.mat(np.zeros((m,1)))
    iter = 0
    while (iter < maxIter):
      alphaPairsChanged = 0
      for i in range(m):
            fXi = float(np.multiply(alphas,labelMat).T*(dataMatrix*dataMatrix.T)) + b
            Ei = fXi - float(labelMat)
            if ((labelMat*Ei < -toler) and (alphas < C)) or ((labelMat*Ei > toler) and (alphas > 0)):
                j = selectJrand(i,m)
                fXj = float(np.multiply(alphas,labelMat).T*(dataMatrix*dataMatrix.T)) + b
                Ej = fXj - float(labelMat)
                alphaIold = alphas.copy(); alphaJold = alphas.copy();
                if (labelMat != labelMat):
                  L = max(0, alphas - alphas)
                  H = min(C, C + alphas - alphas)
                else:
                  L = max(0, alphas + alphas - C)
                  H = min(C, alphas + alphas)
                if L==H: print("L==H"); continue
                eta = 2.0 * dataMatrix*dataMatrix.T - dataMatrix*dataMatrix.T - dataMatrix*dataMatrix.T
                if eta >= 0:
                  print("eta>=0"); continue
                alphas -= labelMat*(Ei - Ej)/eta
                alphas = clipAlpha(alphas,H,L)
                if (abs(alphas - alphaJold) < 0.00001):
                  print("j not moving enough"); continue
                alphas += labelMat*labelMat*(alphaJold - alphas)
                b1 = b - Ei- labelMat*(alphas-alphaIold)*dataMatrix*dataMatrix.T - labelMat*(alphas-alphaJold)*dataMatrix*dataMatrix.T
                b2 = b - Ej- labelMat*(alphas-alphaIold)*dataMatrix*dataMatrix.T - labelMat*(alphas-alphaJold)*dataMatrix*dataMatrix.T
                if (0 < alphas) and (C > alphas):
                  b = b1
                elif (0 < alphas) and (C > alphas):
                  b = b2
                else:
                  b = (b1 + b2)/2.0
                alphaPairsChanged += 1
                print("iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged))
      if(alphaPairsChanged == 0):
            iter += 1
      else:
            iter = 0
      print("iteration number: %d" % iter)
    return b,alphas


def calcWs(alphas,dataArr,classLabels):
    X = np.mat(dataArr); labelMat = np.mat(classLabels).transpose()
    m, n = np.shape(X)
    w = np.zeros((n,1))
    for i in range(m):
      w += np.multiply(alphas*labelMat,X.T)
    return w


dataArr, labelArr = loadDataSet(r"C:\...\testSet.txt")         
b, alphas = smoSimple(dataArr, labelArr, 0.6, 0.001, 40)   
ws = calcWs(alphas, dataArr, labelArr)   



import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
temp = pd.DataFrame(dataArr)
temp.columns = ["1", "2"]
temp["label"] = pd.array(labelArr)
temp["label"] = np.array(temp["label"]).astype(np.int)
xx = np.linspace(0, 10, 20)
yy = (-b - xx * ws) / ws
temp1 = pd.DataFrame()
temp1["xx"] = np.array(xx)
temp1["yy"] = np.array(yy.T)
sns.scatterplot(data = temp, x = "1", y = "2", hue = "label")
plt.plot(temp1['xx'], temp1['yy'])               
               

糖逗 发表于 2020-11-10 16:35:53

本帖最后由 糖逗 于 2020-11-10 16:40 编辑

参考文献:https://www.math.pku.edu.cn/teachers/ganr/course/pr2010/Ref/platt_smoTR.pdf
参考链接:https://zhuanlan.zhihu.com/p/27662928
https://www.jianshu.com/p/eef51f939ace
页: [1]
查看完整版本: python实现SVM【软间隔】【SMO算法】