码迷,mamicode.com
首页 > 其他好文 > 详细

支持向量分类方法

时间:2017-12-20 21:52:57      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:矩阵   差值   open   line   gpo   ==   smo算法   等于   pairs   

1. 普通的支持向量积分类方法

import numpy as np


# 加载数据
def loadData():
    DataMatrix = []
    LabelMatrix = []
    with open("testSet.txt") as fr:
        for line in fr.readlines():
            datas = line.strip().split(\t)
            DataMatrix.append([float(datas[0]), float(datas[1])])
            LabelMatrix.append(float(datas[2]))
    return DataMatrix, LabelMatrix


# 选择两个不同的alpha的下标i,j
def selectJrand(i, m):
    j = i
    while j == i:
        j = int(np.random.uniform(0, m))
    return j


# 调整大于H 小于L的aj值
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):
            # wxi+b  w=i从1到N aiyixi累加再乘上xi
            fxi = float(np.multiply(alphas, labelMat).T * (dataMatrix * dataMatrix[i, :].T)) + b
            # 预测值和真实值的差值
            Ei = fxi - float(labelMat[i])
            # alphas 在非边界上可以扩大或缩小
            if ((labelMat[i] * Ei < -toler) and (alphas[i] < C)) or ((labelMat[i] * Ei > toler) and (alphas[i] > 0)):
                j = selectJrand(i, m)
                fxj = float(np.multiply(alphas, labelMat).T * (dataMatrix * dataMatrix[j, :].T)) + b
                Ej = fxj - float(labelMat[j])
                alphaIold = alphas[i].copy()
                alphaJold = alphas[j].copy()
                # 调整alpha[j]到 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(H==L)
                    continue
                # #=K11+k22-2K12
                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
                alphas[j] -= labelMat[j] * (Ei - Ej) / eta
                # 对 alphasa[j]进行剪辑
                alphas[j] = clipAlpha(alphas[j], H, L)
                if (abs(alphas[j] - alphaJold) < 0.00001):
                    print("j not movving enough")
                    continue
                # a1,new=a1,old+y1y2(a2,old-a2,new)  把a2作为自变量
                alphas[i] += labelMat[j] * labelMat[i] * (alphaJold - alphas[j])
                # b1,new=bold-E1-y1K11(a1,new -a1,old)-y2K21(a2,new-a2,old)
                b1 = b - Ei - labelMat[i] * (alphas[i] - alphaIold) * dataMatrix[i, :] * dataMatrix[i, :].T - labelMat[
                                                                                                                  j] * (
                                                                                                                  alphas[
                                                                                                                      j] - alphaJold) * dataMatrix[
                                                                                                                                        i,
                                                                                                                                        :] * dataMatrix[
                                                                                                                                             j,
                                                                                                                                             :].T
                # b2,new=bold-E2-y1K12(a1,new-a1,old)-y2K22(a2,new-a2,old)
                b2 = b - Ej - labelMat[i] * (alphas[i] - alphaIold) * dataMatrix[i, :] * dataMatrix[j, :].T - labelMat[
                                                                                                                  j] * (
                                                                                                                  alphas[
                                                                                                                      j] - alphaJold) * dataMatrix[
                                                                                                                                        j,
                                                                                                                                        :] * dataMatrix[
                                                                                                                                             j,
                                                                                                                                             :].T
                if (0 < alphas[i]) and (C > alphas[i]):
                    b = b1
                elif (0 < alphas[j]) and (C > alphas[j]):
                    b = b2
                else:
                    b = (b1 + b2) / 2.0
                alphaPairsChanged += 1
                print(iter:%d i:%d,pairs change %d % (iter, i, alphaPairsChanged))
        if (alphaPairsChanged == 0):
            iter += 1
        else:
            iter = 0
        print(iteration number:%d % iter)
    return b, alphas


# 画图
def plotThePicture(VectDoc, alphas, b):
    import matplotlib.pyplot as plt
    DataMatrix, LabelMatrix = loadData()
    dataArra = np.array(DataMatrix)
    n = np.shape(dataArra)[0]
    xcord1 = []
    ycord1 = []
    xcord2 = []
    ycord2 = []
    xcord3 = []
    ycord3 = []
    for i in range(n):
        if i not in VectDoc:
            if int(LabelMatrix[i]) == 1.0:
                xcord1.append(dataArra[i][0])
                ycord1.append(dataArra[i][1])
            else:
                xcord2.append(dataArra[i][0])
                ycord2.append(dataArra[i][1])
        else:
            xcord3.append(dataArra[i][0])
            ycord3.append(dataArra[i][1])
    w = np.array(calcWs(alphas, dataArra, LabelMatrix))
    x = np.arange(-2.0, 10.0, 0.1)
    # fxi = float(np.multiply(alphas, labelMat).T * (dataMatrix * dataMatrix[i, :].T)) + b
    # for j in range(len(x)):
    s = b[0][0]
    t1 = w[0][0]
    t2 = w[1][0]
    y = np.array((-s - t1 * x) / t2)[0]
    # xnew = np.mat(np.array([x[j], x[j]]))
    # yu = (xnew * w) + b
    # y.append(np.array(yu)[0][0])
    # y = (x * w) + b
    # 画出支持向量所在的直线
    y1 = np.array((1 - s - t1 * x) / t2)[0]
    y2=np.array((-1-s-t1*x)/t2)[0]

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c="red", marker=s)
    ax.scatter(xcord2, ycord2, s=30, c=green)
    ax.scatter(xcord3, ycord3, s=30, c="blue", marker=*)
    ax.plot(x, y)
    ax.plot(x,y1)
    ax.plot(x,y2)
    plt.xlabel(x1)
    plt.ylabel(y1)
    plt.show()


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):
        if alphas[i] > 0.0:
            w += np.multiply(alphas[i] * labelMat[i], x[i, :].T)
    return w


dataMatrix, LabelMatrix = loadData()
b, alphas = smoSimple(dataMatrix, LabelMatrix, 0.6, 0.001, 40)
print(b)
print(- * 20)
# print(alphas[alphas !=0])
VectorDoc = []
for i in range(100):
    if alphas[i] > 0.0:
        print(dataMatrix[i], LabelMatrix[i],alphas[i])
        VectorDoc.append(i)

plotThePicture(VectorDoc, alphas, b)

 2.完整的SMO分类

  最小最优化(SMO)算法,就是要求解 凸二次规划的对偶问题                        

                           技术分享图片

                          技术分享图片

                              技术分享图片   ,i =1,2,...,N

     在这个问题中变量是拉格朗日乘子,一个变量技术分享图片对应于一个样本点 技术分享图片 ,变量的总数等于训练样本容量N

   SMO 算法是一种启发式算法,如果所有变量的解都满足此最优化问题的KKT条件,那么这个最优化问题的解得到了,因为KKT条件是该问题最优化问题的充分必要条件,否则,选择两个变量,固定其他变量,针对这两个变量构建一个二次规划问题,则这个二次规划问题关于两个变量的解应该更接近原始二次规划问题的解,因为这会使得原始二次规划问题的目标函数值变的更小,子问题中有两个变量,一个是违反KKT条件最严重的哪一个,另一个是|Ei-Ej|约束条件最大的哪一个    

         其实子问题中只有一个自由变量   假设技术分享图片为两个变量, 技术分享图片固定,那么由约束条件 可知

                                                           技术分享图片

如果其中一个确定,那么另一个也确定

 

# 完整版SMO算法
import numpy as np


class optStruct:
    # dataMatrix 数据数据矩阵
    # classLabels 类别标签
    # C 惩罚参数
    # toler表示错误率
    # alphas表示前置系数
    # b 表示常数项
    # eCache缓存误差 第一列表示eCache是否有效,第二列给出的是实际的E值
    def __init__(self, dataMatrix, classLabels, C, toler):
        self.x = dataMatrix
        self.labelMat = classLabels
        self.C = C
        self.tol = toler
        self.m = np.shape(dataMatrix)[0]
        self.alphas = np.mat(np.zeros((self.m, 1)))
        self.b = 0
        self.eCache = np.mat(np.zeros((self.m, 2)))

    # 随机选择一个j
    def selectJrand(self, i, m):
        j = i
        while j != i:
            j = int(np.random.uniform(0, m))
        return j

    #  计算预测值与真实值的误差
    def calcEk(self, k):
        fxk = float(np.multiply(self.alphas, self.labelMat).T * (self.x * self.x[k, :].T)) + self.b
        Ek = fxk - float(self.labelMat[k])
        return Ek

    # 内循环选择一个j 选择条件 |Ei-Ej|的值最大
    def selectJ(self, i, Ei):
        maxK = -1;
        maxDeltaE = 0;
        Ej = 0
        self.eCache[i] = [1, Ei]
        # 返回有效元素所在的index序列号
        validEcacheList = np.nonzero(self.eCache[:, 0].A)[0]
        if (len(validEcacheList)) > 1:
            for k in validEcacheList:
                if k == i: continue
                Ek = self.calcEk(k)
                deltaE = np.abs(Ei - Ek)
                if (deltaE > maxDeltaE):
                    maxK = k
                    maxDeltaE = deltaE
                    Ej = Ek
            return maxK, Ej
        else:  # 如果是第一次循环  随机选择一个j
            j = self.selectJrand(i, self.m)
            Ej = self.calcEk(j)
            return j, Ej

    # 把先相应数据存入缓存
    def updateEk(self, k):
        Ek = self.calcEk(k)
        self.eCache[k] = [1, Ek]

    def innerL(self, i):
        Ei = self.calcEk(i)
        # yi(w*xi+b)>=1-u
        # 违反KKT条件 的一个alphas
        # 列出所有的KKT条件   1.  ai=0---->yig(xi)>=1
        #                     2.0<ai<C-->yig(xi)=1
        #                     3. ai=C-->yig(xi)<=1
        # 一般首先遍历所有满足 2. 条件的样本点,即在间隔边界上的支持向量,检验他们是否满足KKT条件,如果读满足,则遍历整个训练集看是否满足KKT条件
        if ((self.labelMat[i] * Ei < -self.tol) and (self.alphas[i] < self.C)) or (
                    (self.labelMat[i] * Ei > self.tol) and (self.alphas[i] > 0)):
            j, Ej = self.selectJ(i, Ei)
            alphaIold = self.alphas[i].copy()
            alphaJold = self.alphas[j].copy()
            if (self.labelMat[i] != self.labelMat[j]):
                L = max(0, self.alphas[j] - self.alphas[i])
                H = min(self.C, self.C + self.alphas[j] - self.alphas[i])
            else:
                L = max(0, self.alphas[j] + self.alphas[i] - self.C)
                H = min(self.C, self.alphas[j] + self.alphas[i])
            if L == H: print(H==L); return 0
            eta = 2.0 * self.x[i, :] * self.x[j, :].T - self.x[i, :] * self.x[i, :].T - self.x[j, :] * self.x[j, :].T
            if eta >= 0: print(eta>=0);return 0
            self.alphas[j] -= self.labelMat[j] * (Ei - Ej) / eta
            self.alphas[j] = self.clipAlpha(self.alphas[j], H, L)
            self.updateEk(j)
            if (np.abs(self.alphas[j] - alphaJold) < 0.00001):
                print(j not moving enough)
                return 0
            # 更新alphas i
            self.alphas[i] += self.labelMat[i] * self.labelMat[j] * (alphaJold - self.alphas[j])
            self.updateEk(i)
            b1 = self.b - Ei - self.labelMat[i] * (self.alphas[i] - alphaIold) * self.x[i, :] * self.x[i, :].T -                  self.labelMat[j] * (self.alphas[j] - alphaJold) * self.x[i, :] * self.x[j, :].T
            b2 = self.b - Ej - self.labelMat[i] * (self.alphas[i] - alphaIold) * self.x[i, :] * self.x[j, :].T -                  self.labelMat[j] * (self.alphas[j] - alphaJold) * self.x[j, :] * self.x[j, :].T
            if (self.alphas[i] > 0) and (self.alphas[i] < self.C):
                self.b = b1
            elif (self.alphas[j] > 0) and (self.alphas[j] < self.C):
                self.b = b2
            else:
                self.b = (b1 + b2) / 2.0
            return 1
        else:
            return 0

    # 修剪
    def clipAlpha(self, aj, H, L):
        if aj > H:
            aj = H
        if L > aj:
            aj = L
        return aj


def smop(dataMatin, classLabels, C, toler, maxIter, kTup=(lin, 0)):
    os = optStruct(np.mat(dataMatin), np.mat(classLabels).transpose(), C, toler)
    iter = 0
    entireSet = True
    alphaPairsChanged = 0
    while (iter < maxIter) and ((alphaPairsChanged > 0) or (entireSet)):
        alphaPairsChanged = 0
        # 遍历所有的值
        if entireSet:
            for i in range(os.m):
                alphaPairsChanged += os.innerL(i)
            print(fullSet,iter:%d i:%d ,pairs changed %d % (iter, i, alphaPairsChanged))
            iter += 1
        else:
            # 遍历非边界值
            nonBoundIs = np.nonzero((os.alphas.A > 0) * (os.alphas.A < os.C))[0]
            for i in nonBoundIs:
                alphaPairsChanged += os.innerL(i)
                print(non-bound,iter:%d i:%d,pairs changed %d % (iter, i, alphaPairsChanged))
            iter += 1
        if entireSet:
            entireSet = False
        elif alphaPairsChanged == 0:
            entireSet = True
    print(iteration number:%d % iter)
    return os.b, os.alphas


def loadData():
    DataMatrix = []
    LabelMatrix = []
    with open("testSet.txt") as fr:
        for line in fr.readlines():
            datas = line.strip().split(\t)
            DataMatrix.append([float(datas[0]), float(datas[1])])
            LabelMatrix.append(float(datas[2]))
    return DataMatrix, LabelMatrix


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):
        if alphas[i] > 0.0:
            w += np.multiply(alphas[i] * labelMat[i], x[i, :].T)
    return w


def plotThePicture(VectDoc, alphas, b):
    import matplotlib.pyplot as plt
    DataMatrix, LabelMatrix = loadData()
    dataArra = np.array(DataMatrix)
    n = np.shape(dataArra)[0]
    xcord1 = []
    ycord1 = []
    xcord2 = []
    ycord2 = []
    xcord3 = []
    ycord3 = []
    for i in range(n):
        if i not in VectDoc:
            if int(LabelMatrix[i]) == 1.0:
                xcord1.append(dataArra[i][0])
                ycord1.append(dataArra[i][1])
            else:
                xcord2.append(dataArra[i][0])
                ycord2.append(dataArra[i][1])
        else:
            xcord3.append(dataArra[i][0])
            ycord3.append(dataArra[i][1])
    w = np.array(calcWs(alphas, dataArra, LabelMatrix))
    x = np.arange(-2.0, 10.0, 0.1)
    # fxi = float(np.multiply(alphas, labelMat).T * (dataMatrix * dataMatrix[i, :].T)) + b
    # for j in range(len(x)):
    s = b[0][0]
    t1 = w[0][0]
    t2 = w[1][0]
    y = np.array((-s - t1 * x) / t2)[0]
    # xnew = np.mat(np.array([x[j], x[j]]))
    # yu = (xnew * w) + b
    # y.append(np.array(yu)[0][0])
    # y = (x * w) + b
    # 画出支持向量所在的直线
    y1 = np.array((1 - s - t1 * x) / t2)[0]
    y2 = np.array((-1 - s - t1 * x) / t2)[0]

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c="red", marker=s)
    ax.scatter(xcord2, ycord2, s=30, c=green)
    ax.scatter(xcord3, ycord3, s=30, c="blue", marker=*)
    ax.plot(x, y)
    ax.plot(x, y1)
    ax.plot(x, y2)
    plt.xlabel(x1)
    plt.ylabel(y1)
    plt.show()


dataArra, LabelArra = loadData()
b, alphas = smop(dataArra, LabelArra, 0.6, 0.001, 100)
print(b)
print(- * 20)
print(alphas[alphas > 0])

VectorDoc = []
for i in range(100):
    if alphas[i] > 0.0:
        print(dataArra[i], LabelArra[i], alphas[i])
        VectorDoc.append(i)

plotThePicture(VectorDoc, alphas, b)
np.nonzero()

 

支持向量分类方法

标签:矩阵   差值   open   line   gpo   ==   smo算法   等于   pairs   

原文地址:http://www.cnblogs.com/09120912zhang/p/8075662.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!