svm

来源:互联网 发布:数据挖掘的作用和意义 编辑:程序博客网 时间:2024/06/05 21:55
  • 优点:泛化错误率低,计算开销不大,结果易解释
  • 缺点:对参数调节和核函数的选择敏感,原始分类器不加修改仅适用于处理二类问题。
  • 适用数据类型:数值型和标称型数据。

拉格朗日乘子法

求在约束条件gj(x1,x2,...,xn)=0的条件下,求f(x1,x2,...,xn)

引进拉格朗日乘子a;建立方程
L(x1,x2,...,xn,a1,a2,...,am)=f(x1,x2,...,xn)+mj=1ajgj(x1,x2,...,xn)

建立n+m个函数的无约束条件的极值,即分别对x1,x2,...,xn,a1,a2,...,an求导

KTT条件
gj(x1,x2,...,xn)=0或者gj(x1,x2,...,xn)<=0
或者gj(x1,x2,...,xn)>=0可以转化为小于号约束,等号约束

L(x,α)=f(x)+αigi(x)+βihi(x)
其中g是不等式约束,h是等式约束,那么KKT条件就是函数的最优值必定满足下面条件:

  1. L对各个x求导为0;
  2. h(x)=0;
  3. αigi(x)=0

构造分析器的原理
如果数据点离决策边界越远,’那么其最后的预测结果也就越可信。
支持向量(support vector):离分隔超平面最近的那些点。(距离:指垂直于直线的点与当前点的距离)

目标函数

min1/2WTW
s.t.yi(Wxi+b)>=1

后续公式推导

svm的一般流程

  1. 收集数据:可以使用任意方法。
  2. 准备数据:需要数值型数据。
  3. 分析数据:有助于可视化分隔超平面。
  4. 训练算法:svm的大部分时间都源自训练,该过程主要实现两个参数的调优。
  5. 测试算法:十分简单的计算过程就可以实现。
  6. 使用算法:几乎所有分类问题都可以使用SVM,值得一提的是,SVM 本身是一个二类分类器,对多类问题应用SVM需要对代码做一些修改。

SMO高效优化算法

from numpy import *import pylab as pldef loadDataSet():    dataMat = []    labelMat = []    fr = open('d:\\testSet.txt','r')    for line in fr:        lineArr = line.split('\t',3)        dataMat.append([float(lineArr[0]),float(lineArr[1])])        labelMat.append(float(lineArr[2]))    return dataMat,labelMat'''下一个函数3616£^0^1«1()有两个参数值,其中1是第一个&姊 &的下标,1(\是所有3中1^的数目。只要函数值不等于输人值1 ,函数就会进行随机选择。'''def selectJrand(i,m):    j = i;    while j==i :        j = random.randint(0,m-1)    return j#是用于调整大于H或小于L的alpha值def clipAlpha(aj,L,H):    if aj>H :        aj = H    if aj<H:        aj = H    return aj#数据集、类别标签、常数 、容错率和取消前最大的循环次数def smoSimple(dataMatIn ,classLabls ,C, toler, maxIter):    dataMatrix = mat(dataMatIn)     #比如之前有m个样例,每个样例有m个数据    labelMat = mat(classLabls).transpose()#生成一个1*m的矩阵    b = 0    m,n = shape(dataMatrix)    alphas = mat(zeros((m,1)))  #初始化为m行1列的矩阵,初始值为0    iter = 0    #当前的循环次数    while iter < maxIter:           alphaPairsChanged = 0 #标记是否有修改        for i in range(m):            fxi = float(multiply(alphas,labelMat).T * (dataMatrix*dataMatrix[i,:].T))+b            '''            multiply是numpy的ufunc函数,执行方法是对应元素相乘,而不是线性代数中的矩阵运算方式,类似于matlab中的点乘,当矩阵的维度不相同时,会根据一定的广播规则将维数扩充到一致的形式            * 就表示矩阵乘法            [i,:]是Numpy花式索引            .T就是进行轴对换而transpose则可以接收参数进行更丰富的变换            f(x)=W^T*x+b=sum(alphas(i)*yi*K(x,xi)) +b            w的值可以通过拉格朗日乘子法求偏导为0得到            '''            Ei = fxi - float(labelMat[i]) #误差            #是否可以继续优化            if ((labelMat[i]*Ei < -toler) and (alphas[i] <C)) or((labelMat[i]*Ei > toler) and (alphas[i] > 0)):                '''                原理解释:                labelMat[i]*Ei = (fxi - labelMat[i])*labelMat[i] = yi*(W^T*x+b) - 1                拉格朗日的约束条件是yi*(W^T*x+b) >= 1 且 alphas[i](1-yi*(W^T*x+b)) = 0                目标函数是最小化1/2*||w||^2+sum(1-alphas[i]*(yi(w^T*x+b)))                toler表示允许误差                如果labelMat[i]*Ei < -toler,那么表示离分界线太近,不符合,此时alphas[i]应该为C,使答案过大,从而调整                如果labelMat[i]*Ei > toler,那么表示离分界线太远,此时alphas[i]应该为0,符合约束条件alphas[i](1-yi*(W^T*x+b)) = 0                '''                j = selectJrand(i,m)    #随机选择第j个样本                fxj = float(multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[j,:].T)) + b                Ej = fxj - float(labelMat[j])# 误差                alphaIold = alphas[i].copy()    #拷贝,分配新的内存                alphaJold = alphas[j].copy()                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])                 '''                a1new y1 + a2new y2 =a1old y1 + a2old = xi                当y1 = y2 = 1,根据a1new的范围->a2new的范围,再与自身的范围进行比较                其余同理                '''                if L==H:                    print("L==H")                    continue                eta = 2.0 * dataMatrix[i,:]*dataMatrix[j,:].T - dataMatrix[i,:]*dataMatrix[i,:].T - dataMatrix[j,:]*dataMatrix[j,:].T                '''                eta = K11 + K22 - 2K12                推导见http://blog.csdn.net/willbkimps/article/details/54697698                '''                if eta >= 0: print("eta>=0"); continue                alphas[j] -= labelMat[j]*(Ei - Ej)/eta                alphas[j] = clipAlpha(alphas[j],H,L)  # 门限函数阻止alpha_j的修改量过大                #如果修改量很微小                if (abs(alphas[j] - alphaJold) < 0.00001): print("j not moving enough"); continue                # alpha_i的修改方向相反                alphas[i] += labelMat[j]*labelMat[i]*(alphaJold - alphas[j])                # 为两个alpha设置常数项b                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,alphasdataArr,labelArr = loadDataSet();b,alphas = smoSimple(dataArr,labelArr,0.6,0.001,40)

核函数

核函数:从某个特征空间到另外一个特征空间的映射。
经过空间转换之后,我们可以在高维空间中解决线性问题,等价于在低维空间中解决非线性问题。

设X是输入空间(欧氏空间或离散集合),Η为特征空间(希尔伯特空间),如果存在一个从X到Η的映射
φ(x): X→Η
使得对所有的x,y∈X,函数Κ(x,y)=φ(x)∙φ(y), 则称Κ(x,y)为核函数,φ(x)为映射函数,φ(x)∙φ(y)为x,y映射到特征空间上的内积。

0 0