支持向量分类方法

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()
时间: 2024-08-28 14:47:23

支持向量分类方法的相关文章

【机器学习基础】支持向量回归

引言 这一小节介绍一下支持向量回归,我们在之前介绍的核逻辑回归使用表示定理(Representer Theorem),将逻辑回归编程Kernel的形式,这一节我们沿着这个思路出发,看看如何将回归问题和Kernel的形式结合起来. Kernel Ridge Regression 上次介绍的表示定理告诉我们,如果我们要处理的是有L2的正则项的线性模型,其最优解是数据zn的线性组合.我们可以将这样的线性模型变成Kernel的形式. 既然我们知道这样带有L2-Regularizer的线性回归模型的最佳解

机器学习实战读书笔记(四)基于概率论的分类方法:朴素贝叶斯

4.1 基于贝叶斯决策理论的分类方法 朴素贝叶斯 优点:在数据较少的情况下仍然有效,可以处理多类别问题 缺点:对于输入数据的准备方式较为敏感 适用数据类型:标称型数据 贝叶斯决策理论的核心思想:选择具有最高概率的决策. 4.2 条件概率 4.3 使用条件概率来分类 4.4 使用朴素贝叶斯进行文档分类 朴素贝叶斯的一般过程: 1.收集数据 2.准备数据 3.分析数据 4.训练算法 5.测试算法 6.使用算法 朴素贝叶斯分类器中的另一个假设是,每个特征同等重要. 4.5 使用Python进行文本分类

《机器学习实战》学习笔记:基于朴素贝叶斯的分类方法

概率是许多机器学习算法的基础,在前面生成决策树的过程中使用了一小部分关于概率的知识,即统计特征在数据集中取某个特定值的次数,然后除以数据集的实例总数,得到特征取该值的概率. 目录: 一.基于贝叶斯理论的分类方法 二.关于朴素贝叶斯的应用场景 三.基于Python和朴素贝叶斯的文本分类 1.准备数据 2.训练算法 3.测试算法 四.小结 以下进入正文: 一.基于贝叶斯理论的分类方法 假设有两类数据组成的数据集如下: 其中,假设两个概率分布的参数已知,并用p1(x,y)表示当前数据点(x,y)属于类

第四章:基于概率论的分类方法: 朴素贝叶斯

本章内容□使用概率分布进行分类□学习朴素贝叶斯分类器□解析RSS源数据口使用朴素贝叶斯来分析不同地区的态度 前两章我们要求分类器做出艰难决策,给出“该数据实例属于哪一类”这类问题的明确答案.不过,分类器有时会产生错误结果,这时可以要求分类器给出一个最优的类别猜测结果,同时给出这个猜测的概率估计值.       概率论是许多机器学习算法的基础,所以深刻理解这一主题就显得十分重要.第3章在计算特征值取某个值的概率时涉及了一些概率知识,在那里我们先统计特征在数据集中取某个特定值的次数,然后除以数据集的

机器学习四 -- 基于概率论的分类方法:朴素贝叶斯

基于概率的分类方法:朴素贝叶斯 贝叶斯决策理论 朴素贝叶斯是贝叶斯决策理论的一部分,所以在讲解朴素贝叶斯之前我们先快速简单了解一下贝叶斯决策理论知识. 贝叶斯决策理论的核心思想:选择具有最高概率的决策.比如我们毕业选择就业方向,选择C++方向的概率为0.3,选择Java的概率为0.2,选择机器学习的概率为0.5.那么我们就把这样的一位毕业生就业方向归类为机器学习方向. 条件概率 什么是条件概率?事件A在另一个事件B已知发生条件下的发生概率,记为P(A|B),读作“在B条件下A的概率”. 例子1:

tensorflow实现基于LSTM的文本分类方法

tensorflow实现基于LSTM的文本分类方法 作者:u010223750 引言 学习一段时间的tensor flow之后,想找个项目试试手,然后想起了之前在看Theano教程中的一个文本分类的实例,这个星期就用tensorflow实现了一下,感觉和之前使用的theano还是有很大的区别,有必要总结mark一下 模型说明 这个分类的模型其实也是很简单,主要就是一个单层的LSTM模型,当然也可以实现多层的模型,多层的模型使用Tensorflow尤其简单,下面是这个模型的图  简单解释一下这个图

[茶思]资产的分类方法

资产类别(asset class),是指一群具有相似特性或遵循相同监管规定的投资品.这一定义中,未指明"相似"是多么相似,也未说明"特性"或"监管规定"具体指什么,因为显然按照不同角度以及不同的标准,资产类别可以有多种具体的定义和分类方法. 为什么要考虑资产分类这一问题? 资产分类是投资研究中的一个必要过程. 首先,通过聚类,对研究范围进行简化,更容易抓住主线逻辑. 第二,通过找出投资标的之间的相似性,可以对投资标的的性质以及价格驱动因素有初步的

js中字符串支持正则表达式的方法

设一个字符串var myName = "fangming";则支持正则表达式的方法有:split(分割),replace(替换),search(查找),match(元素参数的数组)console.log(myName.split(/N/i));console.log(myName.replace(/G/i,"a"));console.log(myName.search(/N/i));console.log(myName.match(/I/i));

关于 JavaFX ——我对通过代码写 UI界面的层级式分类方法

前言:在我的另一篇文章“我对 Java 标志符的命名方法”中有提到:对于返回控件的方法我是使用类似:W_borderPane() 的方式编写的. 现在我提出一种通过代码编写 UI 界面的层级式分类方法: 示例代码: // 根容器 private static BorderPane W_borderPaneBasis(){ // 创建 BorderPane _borderPaneBasis = new BorderPane(); // #自我定义 _borderPaneBasis.setBackg