机器学习05-支持向量机_1
来源:互联网 发布:私人订制软件 编辑:程序博客网 时间:2024/05/21 08:40
支持向量机
分隔超平面
如下图是一组线性可分的二维点,我们可以通过我们可以使用梯度下降算法找到将测试数据进行区分的直线,由于测试数据区分度很高,因此我们可能找到不止一条合适的分割线即多组权值((w0,w1,w2),(w0’,w1’,w2’)….),这个时候我们如何判定最合适的分割线?同理扩展到3维,n维都存在这个问题。
因此我们引入分隔超平面的概念,通过确认一个分隔训练集的平面,使得所有训练集合数据尽量的远离该平面,这个平面称之为分隔超平面,对于二维数据超平面为一维的一条直线,对于三维数据超平面为二维平面,对于n维数据超平面为n-1维的面。确定超平面后对于给定数据点如果离超平面的距离越远则最终得到的预测结果越可信。
通过利用支持向量来确定分隔超平面,支持向量指离分隔超平面最近的点,使得支持向量到分隔面的距离最大化,就能找到最优的分隔超平面。
分隔超平面最优化问题
依据前两章的做法定义超平面表达式
当P大于0.5时,特征属于y=1的分类,反之属于y=0的分类。在支持向量机中我们将logistics做了一个变形,定义
对于超平面
间隔函数
需要求数据点到超平面的距离,我们定义
公式中
上面的公式比较难于理解,这里有另外一种理解方式:定义两个平面
图片来源
我们要实现的目标是使得H1、H2到超平面的距离尽量远即:
这里的式(1)和式(2)为了方便计算可以统一写成
拉格朗日方法
为了求解我们的约束方程,需要引入拉格朗日函数,拉格朗日函数是用于求解多元函数在收到一个或多个约束条件时的极值问题的方法。使用拉格朗日函数可将一个n个变量和k个约束条件的最优化问题转换为n+k个变量的n+k个变量方程组。比如:要求
拉格朗日乘法所得的极值会包含原问题的所有极值点,但并不保证每个极值点都是原问题的极值点。
使用拉格朗日方法求解我们的方程得到:
要求解
我们先求
推导公式可以参见 参考链接
关于离群问题
很多情况下给定的训练数据不是完全线性可分的,可能存在离群点,即y=-1的点对应的特征值很接近超平面甚至超出了超平面进入到y=1的类别中,这些点会影响超平面的移动甚至会导致超平面最终无解。我们引入了一个松弛变量
我们的超平面转变为:
最优值:
这里的C表示离群点对结果影响的权重值(当C=
最终得到:
这里可以看到增加松弛变量和惩罚系数后我们的解表达式不变,只是
==这里的推导详见底部的引用链接 smo.pdf 文档==
优化过程
这里的目的是在代码实现前,先看一下算法的优化问题和回归问题。
超平面
算法实现
支持向量机的实现都是参见<<机器学习实战>>里面的代码。测试数据详见参考里的 svnTestSet.txt
简单版本的实现代码:
'''Created on Nov 4, 2010Chapter 5 source file for Machine Learing in Action@author: Peter'''from numpy import *from time import sleepdef 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,labelMatdef 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 jdef clipAlpha(aj,H,L): if aj > H: aj = H if L > aj: aj = L return ajdef 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): #下面两行源自公式 aixiyi x + b - y >= 0 使得点能够在H1 和 H2之外 fXi = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[i,:].T)) + b Ei = fXi - float(labelMat[i])#if checks if an example violates KKT conditions #判断是否在误差区间,如果超过误差区间则需要作调整 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(); ## Two Lagrange Multiplier 问题 smo.pdf 里面也有详细解释 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 # (x1 - x2)^2 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])#update i by the same amount as j #the update is in the oppostie direction 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,alphasdef calcWs(alphas,dataArr,classLabels): X = mat(dataArr); labelMat = mat(classLabels).transpose() m,n = shape(X) w = zeros((n,1)) for i in range(m): w += multiply(alphas[i]*labelMat[i],X[i,:].T) return wdataMat, labelMat = loadDataSet("svnTestSet.txt")b,result = smoSimple(dataMat, labelMat, 0.6, 0.001, 40)result:>>> bmatrix([[-3.73850318]])>>> alphas[alphas>0]matrix([[ 0.1516457 , 0.14693547, 0.06334441, 0.00565379, 0.35627179]])#这里可以看到,一共找到五个支持向量
核函数
考虑如下分布图,在这种case下我们无法通过上面的松弛变量和惩罚参数来进行优化,这个时候我们就需要将这种无法区分的训练数据通过我们核函数(kernel函数)将数据转换为易于分类器理解的形式。通过核函数我们将我们特征数据从一个特征空间转换到另外一个特征空间,在新的空间下我们能很方便的利用smo算法对数据进行处理(另外一种理解是从低维度转换到高纬度)。
当一个不可分的低维数据通过Kernel转到到高维之后的视角:
==径向基核函数==是目前使用最广泛的Kernel函数,当然还有其他类型的Kernel函数(也可以自己指定自己的核函数)例如:多项式核函数,线性核函数
径向基核函数
径向基函数能够基于变量距离运算输出一个标量,这个距离可以是<0,0>向量与其他向量距离,径向基函数的高斯版本:
这个公式可以理解为将原始空间映射为无穷维空间。
核函数代码:
def kernelTrans(X, A, kTup): #calc the kernel or transform data to a higher dimensional space m,n = shape(X) K = mat(zeros((m,1))) if kTup[0]=='lin': K = X * A.T #linear kernel elif kTup[0]=='rbf': for j in range(m): deltaRow = X[j,:] - A K[j] = deltaRow*deltaRow.T K = exp(K/(-1*kTup[1]**2)) #divide in NumPy is element-wise not matrix like Matlab else: raise NameError('Houston We Have a Problem -- \ That Kernel is not recognized') return Kclass optStruct: def __init__(self,dataMatIn, classLabels, C, toler, kTup): # Initialize the structure with the parameters self.X = dataMatIn self.labelMat = classLabels self.C = C self.tol = toler self.m = shape(dataMatIn)[0] self.alphas = mat(zeros((self.m,1))) self.b = 0 self.eCache = mat(zeros((self.m,2))) #first column is valid flag self.K = mat(zeros((self.m,self.m))) for i in range(self.m): self.K[:,i] = kernelTrans(self.X, self.X[i,:], kTup)
参考:
http://blog.csdn.net/v_july_v/article/details/7624837
http://blog.pluskid.org/?p=685
http://blog.sina.com.cn/s/blog_4298002e010144k8.html
https://zh.wikipedia.org/wiki/%E6%8B%89%E6%A0%BC%E6%9C%97%E6%97%A5%E4%B9%98%E6%95%B0
ftp://www.ai.mit.edu/pub/users/tlp/projects/svm/svm-smo/smo.pdf 或 http://oe7d0gss7.bkt.clouddn.com/smo.pdf
http://cs229.stanford.edu/notes/cs229-notes3.pdf
http://oe7d0gss7.bkt.clouddn.com/svnTestSet.txt
- 机器学习05-支持向量机_1
- 机器学习-支持向量机
- 机器学习--支持向量机
- 机器学习-支持向量机
- 【机器学习】支持向量机
- 机器学习-支持向量机
- 机器学习-学习笔记 支持向量机
- 机器学习作业-支持向量机简介
- 机器学习之支持向量机
- 从机器学习到支持向量机
- 机器学习之支持向量机
- 机器学习 支持向量机(SVM)
- 机器学习到支持向量机
- Stanford机器学习--- 支持向量机SVM
- 机器学习5支持向量机
- 机器学习之支持向量机(svm)
- 机器学习系列之支持向量机
- 【机器学习】支持向量机SVM
- 【c++】二叉树的线索化
- 多线程三
- CC2538知识
- 特征点匹配——使用基础矩阵、单应性矩阵的RANSAC算法去除误匹配点对
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)F. Cyclic Cipher
- 机器学习05-支持向量机_1
- OpenMV 机器视觉模块 简介
- Android使用Java反射机制,被调用的类多出未定义的field
- DualPivotQuicKSort
- 带色彩恢复的多尺度视网膜增强算法(MSRCR)的原理、实现及应用。
- 【Day26】include require include_once require_once 的区别深度总结
- FOF管理系列之五:你适合投什么样的FOF产品?
- SpringMVC-1.认识及配置
- log4j使用