机器学习算法之三——分类(四)

1 SVM基本理论

   支持向量机SVM(support vector mac),分类的基本思想是利用最大间隔分类,找到空间中的一个超平面,离这个超平面最近的点叫支持向量,点到超平面的距离叫间隔。如果要处理非线性问题,是通过核函数将特征向量映射到高维空间。从而变成线性可分的。

1.1 几何间隔

    我们假设超平面的判别式:\omega^Tx+b=0

样本到超平面的几何间隔:r=\frac{\omega^T x+b}{||\omega||}\omega表示权重向量,b表示偏移向量,||\omega||表示\omega的内积||\omega|| = \sqrt{\omega_0^2 + \omega_1^2 +...+\omega_n^2}

1.2 最大化间隔

    我们已经知道如何去求数据点到超平面的距离,那么就可以找出支持向量,并计算支持向量的间隔,我们把支持向量x的间隔定义为:

r =\frac{\omega^T x+b}{\|w\|}=\left\{\begin{array}{ll}{\frac{1}{\|w\|}} & {\text { if } : y =h\left(x\right)=+1} \\ {-\frac{1}{\|w\|}} & {\text { if } y =h\left(x\right)=-1}\end{array}\right.

我们可以把这个公式想象为两个平面,\omega^T x+b =1 & \omega^T x+b =-1,支持向量就在这两个平面上,如果\omega^T x+b >1则被分为1类;如果\omega^T x+b <-1,则被分为-1类。我们现在要做的就是最大化这两个平面的间隔p = \frac{2}{||\omega||},我们要通过找到最优的w,b来最大化p。

最大化p值的条件限制:\left\{\begin{array}{l}{\max _{w, b} \frac{2}{\|w\|}} \\ {y_{i}\left(w^{T} x_{i}+b\right) \geqslant 1,(i=1, \ldots, n)}\end{array}\right.,为了计算方便\left\{\begin{array}{l}{\max _{w, b} \frac{1}{2\|w\|}^2} \\ {y_{i}\left(w^{T} x_{i}+b\right) \geqslant 1,(i=1, \ldots, n)}\end{array}\right.

这种式子通常用拉格朗日来求解:L(w, b, \alpha)=\frac{1}{2} w^{T} w-\sum_{i=1}^{n} \alpha_{i}\left[y_{i}\left(w^{T} x_{i}+b\right)-1\right]我们的目标变为:\min _{w, b} \max _{\alpha \geqslant 0} L(w, b, \alpha)

根据凸优化和对偶可以变为:\max _{\alpha \geqslant 0} \min _{w, b} L(w, b, \alpha)

       求导带入得:

w=\sum_{i=1}^{n} \alpha_{i} y_{i} x_{i}

用一个正支持向量xs得到b:

b =1-w^{T} x_{s}

1.3 松弛变量

    问题似乎已经解决了,但是这里有个假设:数据必须是百分之百可分的。但是实际中的数据几乎都不那么“干净”,或多或少都会存在一些噪点。为此下面我们将引入了松弛变量来解决这种问题,引入松弛变量允许一些数据处于分隔面错误的一侧:

\left\{\begin{array}{l}{\min _{w, b} \frac{1}{2}\|w\|^{2}+C \sum_{i=1}^{n} \xi_{i}} \\ {y_{i}\left(w^{T} x_{i}+b\right) \geqslant 1-\xi_{i} \quad, \xi_{i} \geqslant 0, \quad(i=1, \ldots, n)}\end{array}\right.

其中的C是用于控制“最大化间隔”和“保证大部分的点的函数间隔都小于1”这两个目标的权重。对上式化解得:

\begin{array}{l}{W(\alpha)=\sum_{i=1}^{n} \alpha_{i}-\frac{1}{2} \sum_{i=1}^{n} \sum_{j=1}^{n} \alpha_{i} \alpha_{j} y_{i} y_{j} x_{i}^{T} x_{j}} \\ {\sum_{i=1}^{n} \alpha_{i} y_{i}=0,0 \leqslant \alpha_{i} \leqslant C(i=1, \ldots, n)}\end{array}

在不可分情况下,对应的KKT条件为:\alpha_{i}\left[y_{i}\left(w^{T} x_{i}+b\right)-1+\xi_{i}\right]=0,(i=1, \ldots, n)

1.4 核函数

    上面的讨论都是在线性可分的情况下,非线性可分的数据SVM通过核函数来求解。核函数是两个向量在隐式映射后的空间中的内积,将数据从输入空间的非线性转变到特征空间,特征空间具有更高甚至无限的维度,从而使得数据在该空间中被转换成线性可分的。核函数有Sigmoid核、线性核、多项式核和高斯核等,其中高斯核和多项式核比较常用,两种核函数均可以把低维数据映射到高维数据。高斯核的公式如下,σ是达到率,即函数值跌落到0的速度参数:

K\left(x_{1}, x_{2}\right)=\exp \left(\frac{-\left\|x_{1}-x_{2}\right\|^{2}}{2 \sigma^{2}}\right)

其他常用的核函数的表达式如下表:

2 运行实例    

# -*- coding:utf-8 -*-
from sklearn import svm
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
 
#define converts(字典)
def Iris_label(s):
    it={b'Iris-setosa':0, b'Iris-versicolor':1, b'Iris-virginica':2 }
    return it[s]
 
 
#读取数据集
path='D:/ML/SVM/Iris.data'
data=np.loadtxt(path, dtype=float, delimiter=',', converters={4:Iris_label} )
#converters={4:Iris_label}中“4”指的是第5列:将第5列的str转化为label(number)
#print(data.shape)
 
#划分数据与标签
x,y=np.split(data,indices_or_sections=(4,),axis=1) #x为数据,y为标签
x=x[:,0:2]
train_data,test_data,train_label,test_label =train_test_split(x,y, random_state=1, train_size=0.7,test_size=0.3) #sklearn.model_selection.
#print(train_data.shape)
 
#训练svm分类器
classifier=svm.SVC(C=2,kernel='rbf',gamma=20,decision_function_shape='ovr') # ovr:一对多策略
classifier.fit(train_data,train_label.ravel()) #ravel函数在降维时默认是行序优先
 
'''#计算svc分类器的准确率
print("训练集:",classifier.score(train_data,train_label))
print("测试集:",classifier.score(test_data,test_label))'''
 
#OR直接调用accuracy_score方法计算准确率
tra_label=classifier.predict(train_data) #训练集的预测标签
tes_label=classifier.predict(test_data) #测试集的预测标签
print("训练集:", accuracy_score(train_label,tra_label) )
print("测试集:", accuracy_score(test_label,tes_label) )
 
'''#查看决策函数
print('train_decision_function:\n',classifier.decision_function(train_data)) # (90,3)
print('predict_result:\n',classifier.predict(train_data))'''
 
#绘制图形
#确定坐标轴范围
x1_min, x1_max=x[:,0].min(), x[:,0].max() #第0维特征的范围
x2_min, x2_max=x[:,1].min(), x[:,1].max() #第1维特征的范围
x1,x2=np.mgrid[x1_min:x1_max:200j, x2_min:x2_max:200j ] #生成网络采样点
grid_test=np.stack((x1.flat,x2.flat) ,axis=1) #测试点
#指定默认字体
matplotlib.rcParams['font.sans-serif']=['SimHei']
#设置颜色
cm_light=matplotlib.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])
cm_dark=matplotlib.colors.ListedColormap(['g','r','b'] )
 
grid_hat = classifier.predict(grid_test)       # 预测分类值
grid_hat = grid_hat.reshape(x1.shape)  # 使之与输入的形状相同
 
plt.pcolormesh(x1, x2, grid_hat, cmap=cm_light)     # 预测值的显示
plt.scatter(x[:, 0], x[:, 1], c=y[:,0], s=30,cmap=cm_dark)  # 样本
plt.scatter(test_data[:,0],test_data[:,1], c=test_label[:,0],s=30,edgecolors='k', zorder=2,cmap=cm_dark) #圈中测试集样本点
plt.xlabel('长度', fontsize=13)
plt.ylabel('宽度', fontsize=13)
plt.xlim(x1_min,x1_max)
plt.ylim(x2_min,x2_max)
plt.title('鸢尾花SVM二特征分类')
plt.show()

       fname:文件路径。

  dtype:数据类型。float、str等。

  delimiter:分隔符。‘,’。

  converters:将数据列与转换函数进行映射的字典。eg:{1:fun},含义是将第2列对应转换函数进行转换。

  usecols:选取数据的列。

classifier=svm.SVC(C=0.8,kernel='rbf',gamma=20,decision_function_shape='ovr') 

kernel='linear'时,为线性核,C越大分类效果越好,但有可能会过拟合(defaul C=1)。

 kernel='rbf'时(default),为高斯核,gamma值越小,分类界面越连续;gamma值越大,分类界面越“散”,分类效果越好,但有可能会过拟合。

decision_function_shape='ovr'时,为one v rest,即一个类别与其他类别进行划分,

decision_function_shape='ovo'时,为one v one,即将类别两两之间进行划分,用二分类的方法模拟多分类的结果。

发布了30 篇原创文章 · 获赞 17 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/selinaqqqq/article/details/89468151