机器学习实战_06支持向量机

来源:互联网 发布:网络语call是什么意思 编辑:程序博客网 时间:2024/04/30 18:10

提前写的总结~~~
SVM它本质上即是一个分类方法,用w^T+b定义分类函数,于是求w、b,为寻最大间隔,引出1/2||w||^2,继而引入拉格朗日因子,化为对拉格朗日乘子a的求解(求解过程中会涉及到一系列最优化或凸二次规划等问题),如此,求w.b与求a等价,而a的求解可以用一种快速学习算法SMO。
至于核函数,是为处理非线性情况,若直接映射到高维计算恐维度爆炸,故在低维计算,等效高维表现。

1.SVM简介

1.1 什么是支持向量机

支持向量机(Support vector machine)通常用在机器学习 (Machine learning)。是一种监督式学习 (Supervised Learning)的方法,主要用在统计分类 (Classification)问题和回归分析 (Regression)问题上。

支持向量机属于一般化线性分类器,也可以被认为是提克洛夫规范化(Tikhonov Regularization)方法的一个特例。这族分类器的特点是他们能够同时最小化经验误差与最大化几何边缘区,因此支持向量机也被称为最大边缘区分类器。现在多简称为SVM。

1.2 监督式学习

监督式学习(英语:Supervised learning),是一个机器学习中的方法,可以由训练资料中学到或建立一个模式(函数 / learning model),并依此模式推测新的实例。训练资料是由输入物件(通常是向量)和预期输出所组成。函数的输出可以是一个连续的值(称为回归分析),或是预测一个分类标签(称作分类)。
这里写图片描述
2.支持向量 (Support Vector)

2.1什么是support vector

这里写图片描述
如图所示,支持向量 (Support Vector)是指在训练集 (Training data set)中,在分类时给予最多信息的点集合,被红色框围起来的这四个训练资料点就被称之为支持向量机。
支持向量就是与分类边界距离最近的训练资料点。从支持向量机的最佳化问题可以推导出一个重要性质:支持向量机的分类边界可由支持向量决定,而与其他资料点无关。这也是它们称为“支持向量”的原因。

3.超平面(hyperplane)

3.1什么是hyperplane

支持向量机建构一个或多个高维(甚至是无限多维)的超平面来分类资料点,这个超平面即为分类边界。直观来说,好的分类边界要距离最近的训练资料点越远越好,因为这样可以减低分类器的泛化误差。在支持向量机中,分类边界与最近的训练资料点之间的距离称为间隔(margin);支持向量机的目标即为找出间隔最大的超平面来作为分类边界。

这里写图片描述

通过一个n-1维的超平面分开数据点,通常这个被称为线性分类器。有很多分类器都符合这个要求。

这里写图片描述

但是我们还希望找到分类最佳的平面,即使得属于两个不同类的数据点间隔最大的那个面,该面亦称为最大间隔超平面。如果能够找到这个面,那么这个分类器就称为最大间隔分类器。

这里写图片描述

这里写图片描述

这里写图片描述
样本属于两个类,用该样本训练svm得到的最大间隔超平面。在超平面上的样本点也称为支持向量。

4. 代码设计
svm本身是一个二类分类器

SMO算法,最小序列优化。
SMO算法是将大优化问题分解为多个小优化问题来求解的。 这些小优化问题往往很容易求解, 并且对它们进行顺序求解的结果与将它们作为整体来求解的结果是完全一致的。在结果完全相同的同时,SMO算法的求解时间短很多。

SMO算法的目标是求出一系列的alpha和b,一旦求出了这些alpha 和 b,就很容易计算出权重向量w,并得到分隔超平面。

SMO算法的工作原理是:每次循环中选择两个alpha进行优化处理。一旦找到一对合适的alpha,那么就增大其中一个同时减小另一个。
这里所谓的“合适” 就是指两个alpha必须要符合一定的条件, 条件之一就是这两个alpha必须要在间隔边界之外, 而其第二个条件则是这两个alpha值还没有进行过区间化处理或者不在边界上。

简化版SMO算法伪代码

创建一个α向量并向其初始化为0向量当迭代次数小于最大迭代次数时(外循环)     对数据集中的每个数据向量(内循环):          如果该向量可以被优化:               随机选择另一个数据向量               同时优化这两个向量               如果两个向量都不能被优化,退出内循环     如果所有向量都没被优化,增加迭代次数,继续下一次循环

辅助函数

# 读取文件def loadDataSet(fileName):    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# 随机选择第二个alpha,i是第一个alpha的下标,m是所有alpha的数目def selectJrand(i,m):    j=i #we want to select any J not equal to i    while (j==i):        j = int(random.uniform(0,m))    return j#用于调整大于H或者小于L的alpha值def clipAlpha(aj,H,L):    if aj > H:         aj = H    if L > aj:        aj = L    return aj

简化版SMO主要代码

def smoSimple(dataMatIn, classLabels, C, toler, maxIter):    dataMatrix = mat(dataMatIn)    labelMat = mat(classLabels).transpose()    b = 0; m,n = shape(dataMatrix)    alphas = mat(zeros((m,1)))    iter = 0    while (iter < maxIter):        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])      # 如果误差很大,则对当前对应的alpha值进行优化            if ((labelMat[i]*Ei < -toler) and (alphas[i] < C)) or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)):                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,将alpha[j]调整到0到C之间。如果L和H相等,则不做任何改变                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]的最优修改量                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                alphas[j] = clipAlpha(alphas[j],H,L)                if (abs(alphas[j] - alphaJold) < 0.00001): print "j not moving enough"; continue                alphas[i] += labelMat[j]*labelMat[i]*(alphaJold - alphas[j])                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 (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 changed %d" % (iter,i,alphaPairsChanged)        if (alphaPairsChanged == 0): iter += 1        else: iter = 0        print "iteration number: %d" % iter    return b,alphas