机器学习方法总结(四)

支持向量机

1.简介

    支持向量机(SVM)是一种二分类模型,它的基本形式是定义在特征空间上的间隔最大的线性分类器,这也是它区别于感知机的原因,如果加上核技巧,SVM实际上就变成了一种非线性分类器。它的学习策略是:间隔最大化;求解算法是:凸二次规划的最优化算法。根据数据分布形式分为:线性可分支持向量机、线性支持向量机、非线性向量机。

   核函数:当输入空间X为欧式空间或离散空间,特征空间H为希尔伯特空间时,核函数表示将输入从输入空间映射到特征空间得到的特征向量之间的内积,即存在一个从X到H的映射\phi (x):X\rightarrow H,使得对所有x,z\in X,函数K(x,z)满足条件:

K(x,z)=\phi (x)\cdot \phi (z),则称K(x,z)为核函数,\phi (x)为映射函数。

2.优缺点

  • 优点:泛化错误率低、计算开销小、结果容易解释、分类效果好且可向高维映射、样本少时仍有效。
  • 缺点:对参数调节和核函数的选择敏感、对大规模数据效果不好、对缺失数据敏感。

3.原理及推导

     函数间隔:一般可用被分类点到分割平面的符号是否一致来判断是否分类正确,所以函数间隔表示为:

                                                                        \widehat{\gamma }=y_{i}(w\cdot x_{i}+b)        

    几何间隔:由于函数间隔受参数w和b的影响,当它们成比例增加此时平面没有变但是所得到的函数距离增加了,为了表示真实的间隔,我们定义几何间隔为:\gamma =y_{i}(\frac{w}{||w||})\cdot x_{i}+\frac{b}{||w||})

     模型目标:寻找几何间隔最大的分离超平面:

                                                                       max_{w,b}:\frac{\widehat{\gamma}}{||w||}

                                                      s.t. :\widehat{\gamma }\leq y_{i}(w\cdot x_{i}+b),i=1,2......N

    由于函数间隔不影响最优化问题的解,所以我们设函数间隔为1, 问题变为求||w||,最优化问题转换为:

                                                                      min_{w,b}:\frac{{1}}{2}||w||^{2}

                                                      s.t.:0\leq y_{i}(w\cdot x_{i}+b)-1,i=1,2......N

    为了求解上式中的最优化问题,应用拉格朗日对偶性将原始问题转换为对偶问题,这样做的原因在于:对偶问题更容易求解、可以自然的引入核函数,首先构建拉格朗日函数,对此为每个等式约束引进拉格朗日乘子:\alpha _{i}\geq 0,i=1,2......N,拉格朗日函数变为:

                                                                  max_{\alpha }min_{w,b}:L(w,b,\alpha )  

                                                   L(w,b,\alpha )=\frac{1}{2}||w||^{2}-\sum_{N}^{i=1}\alpha _{i}y_{i}(w\cdot x_{i}+b)+\sum_{N}^{i=1}\alpha _{i}

                                                                      \alpha =(\alpha _{1},\alpha _{2}......\alpha _{N})^{T}

     用拉格朗日函数对w和b进行求偏导置零然后转换为以下的最优化问题:

                                                          min_{\alpha }: \frac{1}{2}\sum_{i=1}^{N}\sum_{j=1}^{N}\alpha _{i}\alpha _{j}y _{i}y _{j}(x _{i}\cdot x _{j})-\sum_{i=1}^{N}\alpha _{i}

                                                                     s.t.:\sum_{i=1}^{N}\alpha _{i}y_{i}=0;\alpha _{i}\geq 0

    对于线性可分数据集来说,如果能得到对偶最优化问题的解\alpha *,那由刚刚偏导为零(自己算下)所得到的等式就可以算出w和b:

                                                                          w^{*}=\sum \alpha _{i}^{*}y_{i}x_{i}

                                                                    b^{*}=y_{j}-\sum \alpha _{i}^{*}y_{i}(x_{i}*x_{j})

    求得分离超平面:

                                                                           w^{*}\cdot x+b^{*}=0

    分类决策参数为:

                                                                     f(x)=sign(w^{*}\cdot x+b^{*})

    当存在一些有不能满足函数间隔大于等于1的样本点时,可以对每个样本引进一个松弛变量,将上述推导的约束条件改为:

                                                                       y_{i}(w\cdot x_{i}+b)\geq 1-\varepsilon _{i}

    将目标函数改为:

                                                                           \frac{1}{2}||w||_{2}+C\sum \varepsilon _{i}

    其中C>0是惩罚参数,由具体问题决定,即保证间隔尽量大和分类尽量准确两个目标之间的权重调节。

4.核函数

    常用核函数有:

  • 多项式核函数:k(x,z)=(x\cdot z+1)^{^{p}}
  • 高斯径向核函数:k(x,z)=e^{-\frac{|x-z|^{2}}{2\sigma ^{2}}}
  • 字符串核函数
  • 拉普拉斯核函数

5.SMO

    SMO(sequential minimal optimization)序列最小优化算法是为了解决传统SVM在训练样本数量过大的情况下出现无法求解的情况,也是目前SVM的主要实现方法。SMO的求解问题是在前面提到的基础上有了不等式约束即:

                                                       min_{\alpha }: \frac{1}{2}\sum_{i=1}^{N}\sum_{j=1}^{N}\alpha _{i}\alpha _{j}y _{i}y _{j}(x _{i}\cdot x _{j})-\sum_{i=1}^{N}\alpha _{i}

                                                                     s.t.:\sum_{i=1}^{N}\alpha _{i}y_{i}=0;C\leq \alpha _{i}\geq 0

    对于等式约束的优化问题,可以应用拉格朗日乘子法去求取最优值;如果含有不等式约束,可以应用KKT条件去求取,它的基本思路是:我们要让所有变量的解满足KTT条件,所以可以选出两个变量,固定其他变量,针对这两个变量构建二次规划问题,这两个变量一个是违反KTT最严重的那一个(即遍历一遍选取),另一个由约束条件决定(能有足够大的变化),因此原文题就被分解成了多个双变量的子问题,通过迭代找到\alpha的解。

6.实现

#基本模型是在特征空间中寻找间隔最大化的分离超平面的线性分类器
#(1)当训练样本线性可分时,通过硬间隔最大化,学习一个线性分类器,即线性可分支持向量机;
#(2)当训练数据近似线性可分时,引入松弛变量,通过软间隔最大化,学习一个线性分类器,即线性支持向量机;
#(3)当训练数据线性不可分时,通过使用核技巧及软间隔最大化,学习非线性支持向量机
#为了什么需要间隔最大化,线性可分支持向量机利用间隔最大化求得最优分离超平面,此时的解是唯一的,且此时的超平面鲁棒性和泛化性最强
#为什么需要求对偶问题:一者对偶问题往往更容易求解;二者可以自然的引入核函数,进而推广到非线性分类问题。
#优点:样本较少时有效,可以解决高维问题和非线性问题,有较高的泛化能力,可以避免神经网络的局部最优
#缺点:对缺失值比较敏感,对于非线性问题没有通用解法,必须谨慎使用kernelfunction
#SVM没有处理缺失值的策略(决策树有)。而SVM希望样本在特征空间中线性可分,
#所以特征空间的好坏对SVM的性能很重要。缺失特征数据将影响训练结果的好坏
#在sklearn库中,SVM采用sklearn.svm.SVC设置的参数
#kernel function :默认是rbf,可以是‘linear’(线性), ‘poly’(多项式), ‘rbf’, ‘sigmoid’, ‘precomputed’
#degree :多项式poly函数的维度,默认是3,选择其他核函数时会被忽略。
#gamma : ‘rbf’,‘poly’ 和‘sigmoid’的核函数参数。默认是’auto’,则会选择1/n_features
#coef0 :核函数的常数项。对于‘poly’和 ‘sigmoid’有用。
#probability :是否采用概率估计?.默认为False
#shrinking :是否采用shrinking heuristic方法,默认为true
#tol :停止训练的误差值大小,默认为1e-3
#cache_size :核函数cache缓存大小,默认为200
#class_weight :类别的权重,字典形式传递。设置第几类的参数C为weight*C(C-SVC中的C)
#verbose :允许冗余输出?
#max_iter :最大迭代次数。-1为无限制。
#decision_function_shape :‘ovo’, ‘ovr’ or None, default=None3
#random_state :数据洗牌时的种子值,int值
#主要调节的参数有:C、kernel、degree、gamma、coef0。
#如果能够将低纬空间的特征向量映射到高维空间,那么这些映射后的特征线性可分的可能性更大
#【记住这里只能说是可能性更大,并不能保证映射过去一定线性可分】,由此我们可以构造映射函数,
#但问题随之而来了,维度扩大,那么随之而言的计算成本就增加了,模型效果好了,但是可用性降低,那也是不行的。
#于是有人提出了核函数的概念,可以在低维空间进行高维度映射过后的计算,使得计算花销大为降低
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm
from numpy.random import rand
//在这里首先用一些随机数做了一个线性可分问题的可视化
np.random.seed(8)#保证每次产生的随机数都相同
a=rand(5)
print(a)
#线性可分
array = np.random.randn(20,2)
#np.r_是按列连接两个矩阵,就是把两矩阵上下相加,要求列数相等,类似于pandas中的concat()。
#np.c_是按行连接两个矩阵,就是把两矩阵左右相加,要求行数相等,类似于pandas中的merge()。
X=np.r_[array-[3,3],array+[3,3]]
y = [0]*20+[1]*20
clf = svm.SVC(kernel='linear')
clf.fit(X,y)
x1_min, x1_max = X[:,0].min(), X[:,0].max(),
x2_min, x2_max = X[:,1].min(), X[:,1].max(),
xx1, xx2 = np.meshgrid(np.linspace(x1_min, x1_max), np.linspace(x2_min, x2_max))
#numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)在指定的间隔内返回均匀间隔的数字
# 得到向量w  : w_0x_1+w_1x_2+b=0
w = clf.coef_[0]
print(w)
f = w[0]*xx1 + w[1]*xx2 + clf.intercept_[0]+1 # 加1后才可绘制 -1 的等高线 [-1,0,1] + 1 = [0,1,2]
plt.contour(xx1, xx2, f, [0,1,2], colors = 'r') # 绘制分隔超平面、H1、H2
plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.Paired) 
plt.scatter(clf.support_vectors_[:,0],clf.support_vectors_[:,1],color='k') # 绘制支持向量点
plt.show()
print(X,y)

//接下来是在鸢尾花数据集上做一个非线性分类示例
from sklearn import datasets
iris=datasets.load_iris()
X = iris.data
y = iris.target
print (iris.target_names)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=1/3)
from sklearn.preprocessing import StandardScaler
scaler=StandardScaler()
X_train_std=scaler.fit_transform(X_train)#fit_transform()先拟合数据,再标准化 
X_test_std=scaler.transform(X_test)## transform()数据标准化
from sklearn.grid_search import GridSearchCV#网格搜索算法是一种通过遍历给定的参数组合来优化模型表现的方法
#GridSearchCV,它存在的意义就是自动调参,只要把参数输进去,就能给出最优化的结果和参数。
#但是这个方法适合于小数据集,一旦数据的量级上去了,很难得出结果。
param_grid = {'C':[1e1,1e2,1e3, 5e3,1e4,5e4],
              'gamma':[0.0001,0.0008,0.0005,0.008,0.005,]}
clf = GridSearchCV(svm.SVC(kernel='rbf',class_weight='balanced'),param_grid,cv=10)
clf = clf.fit(X_train_std,y_train)
print (clf.best_params_,'\n',\
       clf.best_estimator_)
clf.score(X_test_std,y_test)
y_pred = clf.predict(X_test_std)
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
print(classification_report(y_test,y_pred,target_names=iris.target_names))
print(confusion_matrix(y_test,y_pred,labels=range(iris.target_names.shape[0])))
             precision    recall  f1-score   support

     setosa       1.00      1.00      1.00        18
 versicolor       1.00      1.00      1.00        15
  virginica       1.00      1.00      1.00        17

avg / total       1.00      1.00      1.00        50

[[18  0  0]
 [ 0 15  0]
 [ 0  0 17]]

    

猜你喜欢

转载自blog.csdn.net/qq_38593211/article/details/81204724