【人工智能】SVM 分类器的设计与应用(QDU)

  • 【人工智能】Astar算法求解8数码问题(QDU)
  • 【人工智能】利用α-β搜索的博弈树算法编写一字棋游戏(QDU)
  • 【人工智能】Fisher 线性分类器的设计与实现(QDU)
  • 【人工智能】感知器算法的设计实现(QDU)
  • 【人工智能】SVM 分类器的设计与应用(QDU)
  • 卷积神经网络 CNN 框架的实现与应用(写的比较水,就没放上)

实验目的

  1. 熟悉 SVM 的基本设计原理。
  2. 掌握 SVM 的使用方法。
  3. 利用 SVM 实现人脸识别。

实验原理

SVM

支持向量机(support vector machines)是一种二分类模型,它的目的是寻找一个超平面来对样本进行分割,分割的原则是间隔最大化,最终转化为一个凸二次规划问题来求解。由简至繁的模型包括:

  • 当训练样本线性可分时,通过硬间隔最大化,学习一个线性可分支持向量机;(也称硬间隔 SVM或线性可分 SVM)
  • 当训练样本近似线性可分时,通过软间隔最大化,学习一个线性支持向量机;(也称软间隔 SVM或线性不可分 SVM)
  • 当训练样本线性不可分时,通过核技巧和软间隔最大化,学习一个非线性支持向量机;(也称核函数或非线性 SVM)

间隔最大化准则

“间隔最大化”是用于确定最优超平面的方法,其要求找到一个超平面能够将训练样本没有错误地分开,并且两类训练样本中离超平面最近的样本与超平面之间的距离是最大的,则我们把这个超平面称作最优分类超平面(Optimal Seperating Hyperplanc),简称最优超平面(Optimal Hyperplanc)。两类样本中离分类面最近的样本到分类面的距离之和称作分类间隔(margin),最优超平面也称作最大间隔超平面。

上述“间隔最大化准则”是SVM的基本思想,在训练样本具有不同特征的情况下会有所不同,下面的硬间隔和软间隔中会有体现。

硬间隔 SVM (线性可分 SVM)

硬间隔部分可以通过下图来理解:

【人工智能】SVM 分类器的设计与应用(QDU)_第1张图片

给定一组数据 ( x ( 1 ) , y ( 1 ) ) , ( x ( 2 ) , y ( 2 ) , … , ( x ( m ) , y ( m ) ) {(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)},…,(x^{(m)},y^{(m)})} (x(1),y(1)),(x(2),y(2),,(x(m),y(m)), 其中 x ( i ) x^{(i)} x(i) d d d维列向量 x ( i ) ∈ R d x^{(i)}∈R^d x(i)Rd y ( i ) y^{(i)} y(i)是一个数 y ( i ) ∈ { − 1 , + 1 } y^{(i)}∈\{−1,+1\} y(i){1,+1} 。如果两类样本线性可分,即存在一个超平面 w ⊤ x + b = 0 w^⊤x+b=0 wx+b=0 将两类样本分隔开,这样可以得到:
{ w ⊤ x ( i ) + b > 0 , i f y ( i ) = + 1 w ⊤ x ( i ) + b < 0 , i f y ( i ) = − 1 \begin{cases} w^⊤x^{(i)}+b>0, && if && y^{(i)} = +1 \\ w^⊤x^{(i)}+b<0, && if && y^{(i)} = -1 \\ \end{cases} {wx(i)+b>0,wx(i)+b<0,ifify(i)=+1y(i)=1
将两个式子合并成一个式子后才方便后续的一些计算,所以合并可得:
y ( i )   s i g n ( w ⊤ x ( i ) + b ) = 1     ⟺     y ( i ) ( w ⊤ x ( i ) + b ) > 0 ( 1.1 ) y^{(i)}\space sign(w^⊤x^{(i)}+b)=1\space\space\space⟺\space\space\space y^{(i)}(w^⊤x^{(i)}+b)>0 \tag{$1.1$} y(i) sign(wx(i)+b)=1      y(i)(wx(i)+b)>0(1.1)
对于任意的 ζ > 0 ζ>0 ζ>0 ( 1.1 ) (1.1) (1.1) 式等价于 y ( i ) ( ζ w ⊤ x ( i ) + ζ b ) > 0 y^{(i)}(ζw^⊤x^{(i)}+ζb)>0 y(i)(ζwx(i)+ζb)>0,则说明 ( w , b ) (w,b) (w,b) 具有放缩不变性,为了后面优化方便,令 m i n ∣ w ⊤ x + b ∣ = 1 min|w^⊤x+b|=1 minwx+b=1,即:
{ w ⊤ x ( i ) + b ≥ + 1 , i f y ( i ) = + 1 w ⊤ x ( i ) + b ≤ − 1 , i f y ( i ) = − 1 \begin{cases} w^⊤x^{(i)}+b≥+1, && if && y^{(i)} = +1 \\ w^⊤x^{(i)}+b≤-1, && if && y^{(i)} = -1 \\ \end{cases} {wx(i)+b+1,wx(i)+b1,ifify(i)=+1y(i)=1
( 1.1 ) (1.1) (1.1) 式就转化为
y ( i ) ( w ⊤ x ( i ) + b ) ≥ 1 ( 1.2 ) y^{(i)}(w^⊤x^{(i)}+b)≥1 \tag{$1.2$} y(i)(wx(i)+b)1(1.2)
要实现间隔最大化(不知道大家能不能理解“间隔最大化”的目的?目的是得到最优分类面,即 w ∗ w^* w b ∗ b^* b),就需要先表示出间隔。刚刚也提到了间隔就是两类样本中距离分类面最近的样本的距离和,通过类似于平面中点到直线的距离公式可以类比得到 d d d维中间隔为离分类面最近的正样本点到分类面和离分类面最近的负样本点到分类面的距离之和,或者可以理解为上图中两条虚线的距离,即 1 ∣ ∣ w ∣ ∣ + 1 ∣ ∣ w ∣ ∣ = 2 ∣ ∣ w ∣ ∣ \frac{1}{||w||}+\frac{1}{||w||} = \frac{2}{||w||} w1+w1=w2。( ∣ ∣ w ∣ ∣ ||w|| w w w w的二范数)

因此,线性SVM的优化目标为:
max ⁡ w , b 2 ∣ ∣ w ∣ ∣     ⟹     min ⁡ w , b 1 2 ∣ ∣ w ∣ ∣ 2 \max \limits_{w,b} \frac{2}{||w||}\space\space\space ⟹\space\space\space \min \limits_{w,b} \frac{1}{2}||w||^2 \\ w,bmaxw2      w,bmin21w2

s . t .        y ( i ) ( w ⊤ x ( i ) + b ) ≥ 1 ,       i = 1 , 2 , … , m ( 1.3 ) s.t. \space\space\space\space\space\space y^{(i)}(w^⊤x^{(i)}+b)≥1,\space\space\space\space\space i=1,2,…,m \tag{$1.3$} s.t.      y(i)(wx(i)+b)1,     i=1,2,,m(1.3)

这是一个凸二次规划(convex quadratic programming)问题,可用现成的二次规划问题优化方法求解(如:Interior point method、Active set method、Gradient projection method等),但是现有求解方法都比较低效,尤其是在处理大数量的训练样本时。所以现实中一般采用对偶算法(dual algorithm),通过求解原始问题(primal problem)的对偶问题(dual problem),来获得原始问题的最优解。这样做的优点,一是对偶问题往往更容易求解,二是能自然地引入核函数,进而高效地解决高维非线性分类问题。

有关问题的转化了解即可。

原始的优化问题 ( 1.3 ) (1.3) (1.3) 式与对偶问题的转换关系如下,

在这里插入图片描述

由拉格朗日乘子法,注意这里有 m m m 个样本,于是为每条约束引入拉格朗日乘子 α i ≥ 0 \alpha_i≥0 αi0 ( 1.3 ) (1.3) (1.3) 式的拉格朗日函数为:
L ( w , b , α ) = 1 2 ∣ ∣ w ∣ ∣ 2 + ∑ i = 1 m α i ( 1 − y i ( w T x i + b ) ) ( 2.1 ) L(w,b,\alpha)=\frac{1}{2}||w||^2+\sum_{i=1}^m \alpha_i(1-y_i(w^Tx_i+b)) \tag{$2.1$} L(w,b,α)=21w2+i=1mαi(1yi(wTxi+b))(2.1)
其中, α = ( α 1 , α 2 , . . . , α m ) T ∈ R + m \alpha=(\alpha_1,\alpha_2,...,\alpha_m)^T∈R_+^m α=(α1,α2,...,αm)TR+m,称为 L a g r a n g e Lagrange Lagrange乘子。

其相应的对偶问题为:
max ⁡ α min ⁡ w , b 1 2 ∣ ∣ w ∣ ∣ 2 + ∑ i = 1 m α i ( 1 − y i ( w T x i + b ) ) s . t .        α i ≥ 0 ,       i = 1 , 2 , . . . , m ( 2.2 ) \max \limits_{\alpha} \min \limits_{w,b} \frac{1}{2}||w||^2+\sum_{i=1}^m \alpha_i(1-y_i(w^Tx_i+b)) \tag{$2.2$} \\ s.t.\space\space\space\space\space\space \alpha_i≥0,\space\space\space\space\space i=1,2,...,m αmaxw,bmin21w2+i=1mαi(1yi(wTxi+b))s.t.      αi0,     i=1,2,...,m(2.2)
上式内层 ( w , b ) (w,b) (w,b) 的优化属于无约束优化问题,由极值条件可知,偏导等于零:
∂ L ∂ w = 0     ⟹     w = ∑ i = 1 m α i y i x i ∂ L ∂ b = 0     ⟹     ∑ i = 1 m α i y i = 0 \frac{∂L}{∂w}=0 \space\space\space⟹\space\space\space w=\sum_{i=1}^m\alpha_iy_ix_i \\ \frac{∂L}{∂b}=0 \space\space\space⟹\space\space\space \sum_{i=1}^m\alpha_iy_i=0 \\ wL=0      w=i=1mαiyixibL=0      i=1mαiyi=0
代入 ( 2 , 2 ) (2,2) (2,2) 式得:
max ⁡ α ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j x i T x j s . t .        α i ≥ 0 ,       i = 1 , 2 , . . . , m ∑ i = 1 m α i y i = 0 ( 2.3 ) \max \limits_{\alpha} \sum_{i=1}^m \alpha_i - \frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m \alpha_i\alpha_jy_iy_jx_i^Tx_j \\ \\ s.t.\space\space\space\space\space\space \alpha_i≥0,\space\space\space\space\space i=1,2,...,m \\ \tag{$2.3$} \sum_{i=1}^m\alpha_iy_i=0 αmaxi=1mαi21i=1mj=1mαiαjyiyjxiTxjs.t.      αi0,     i=1,2,...,mi=1mαiyi=0(2.3)


推导过程:
L ( w , b , α ) = 1 2 ∣ ∣ w ∣ ∣ 2 + ∑ i = 1 m α i ( 1 − y i ( w T x i + b ) ) = 1 2 w T w + ∑ i = 1 m ( α i − α i y i w T x i − b α i y i ) = 1 2 w T ∑ i = 1 m α i y i x i + ∑ i = 1 m α i − w T ∑ i = 1 m α i y i x i − b ∑ i = 1 m α i y i = ∑ i = 1 m α i − 1 2 w T ∑ i = 1 m α i y i x i = ∑ i = 1 m α i − 1 2 ( ∑ i = 1 m α i y i x i ) T ∑ i = 1 m α i y i x i = ∑ i = 1 m α i − 1 2 ∑ i = 1 m α i y i x i T ∑ i = 1 m α i y i x i = ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j x i T x j = ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j < x i , x j > L(w,b,\alpha) \\\\ =\frac{1}{2}||w||^2+\sum_{i=1}^m \alpha_i(1-y_i(w^Tx_i+b))\\\\ = \frac{1}{2}w^Tw+\sum_{i=1}^m (\alpha_i-\alpha_iy_iw^Tx_i-b\alpha_iy_i) \\\\ =\frac{1}{2}w^T\sum_{i=1}^m\alpha_iy_ix_i + \sum_{i=1}^m \alpha_i-w^T\sum_{i=1}^m\alpha_iy_ix_i-b\sum_{i=1}^m\alpha_iy_i \\\\ =\sum_{i=1}^m \alpha_i-\frac{1}{2}w^T\sum_{i=1}^m\alpha_iy_ix_i \\\\ =\sum_{i=1}^m \alpha_i-\frac{1}{2}(\sum_{i=1}^m\alpha_iy_ix_i)^T\sum_{i=1}^m\alpha_iy_ix_i \\\\ =\sum_{i=1}^m \alpha_i-\frac{1}{2}\sum_{i=1}^m\alpha_iy_ix_i^T\sum_{i=1}^m\alpha_iy_ix_i \\\\ =\sum_{i=1}^m \alpha_i-\frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m \alpha_i\alpha_jy_iy_jx_i^Tx_j \\\\ =\sum_{i=1}^m \alpha_i-\frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m \alpha_i\alpha_jy_iy_j \\\\ L(w,b,α)=21w2+i=1mαi(1yi(wTxi+b))=21wTw+i=1m(αiαiyiwTxibαiyi)=21wTi=1mαiyixi+i=1mαiwTi=1mαiyixibi=1mαiyi=i=1mαi21wTi=1mαiyixi=i=1mαi21(i=1mαiyixi)Ti=1mαiyixi=i=1mαi21i=1mαiyixiTi=1mαiyixi=i=1mαi21i=1mj=1mαiαjyiyjxiTxj=i=1mαi21i=1mj=1mαiαjyiyj<xi,xj>

说明:

  1. 第一个等号后的式子为原式
  2. 第二个等号后的式子:将向量的二范数化为向量乘法的形式(内积),即 ∣ ∣ w ∣ ∣ 2 = w T w ||w||^2=w^Tw w2=wTw;将求和符号中的式子展开
  3. 第三个等号后的式子:代入 w = ∑ i = 1 m α i y i x i w=\sum_{i=1}^m\alpha_iy_ix_i w=i=1mαiyixi;由于 w w w x x x为向量,其余变量均为数,所以化为如此样式
  4. 第四个等号后的式子:代入 ∑ i = 1 m α i y i = 0 \sum_{i=1}^m\alpha_iy_i=0 i=1mαiyi=0,并合并同类项
  5. 第五个等号后的式子:代入 w = ∑ i = 1 m α i y i x i w=\sum_{i=1}^m\alpha_iy_ix_i w=i=1mαiyixi
  6. 第六个等号后的式子:由于 α i \alpha_i αi y i y_i yi为数值, x i x_i xi为向量,所以相当于对 x i x_i xi 转置
  7. 第七个等号后的式子:将两个求和合并
  8. 第八个等号后的式子: x i T x j = < x i , x j > x_i^Tx_j= xiTxj=<xi,xj> < a , b > <a,b>表示两向量的内积,结果为数值

( 2.2 ) (2.2) (2.2) 式的最优解应满足 KKT 条件(不证明),由 KKT 条件中的互补松弛条件(不说明)可知 α i ( 1 − y i ( w T x i + b ) ) = 0 \alpha_i(1-y_i(w^Tx_i+b))=0 αi(1yi(wTxi+b))=0。当 α i > 0 \alpha_i>0 αi>0时, y i ( w T x i + b ) = 1 y_i(w^Tx_i+b)=1 yi(wTxi+b)=1,说明这些样本点 ( x i , y i ) (x_i,y_i) (xi,yi) 一定在间隔边界上,它们被称为“支持向量”,这些点共同决定了分离超平面。这是 svm 的一个重要特性: 训练完成后,大部分训练样本不需要保留,最终模型仅与支持向量有关

于是可根据支持向量求 w w w
w = ∑ i = 1 m α i y i x i = ∑ i : α i = 0 m 0 ⋅ y i x i + ∑ i : α i > 0 m α i y i x i = ∑ i ∈ S V α i y i x i ( 2.4 ) w\\\tag{$2.4$} =\sum_{i=1}^m\alpha_iy_ix_i \\ =\sum_{i:\alpha_i=0}^m 0·y_ix_i+\sum_{i:\alpha_i>0}^m \alpha_iy_ix_i \\ =\sum_{i∈SV} \alpha_iy_ix_i w=i=1mαiyixi=i:αi=0m0yixi+i:αi>0mαiyixi=iSVαiyixi(2.4)
其中 S V SV SV 代表所有支持向量的集合。对于任意支持向量 ( x s , y s ) (x_s,y_s) (xs,ys),都有 y s ( w T x s + b ) = 1 y_s(w^Tx_s+b)=1 ys(wTxs+b)=1。将 ( 2.4 ) (2.4) (2.4)式代入,并利用 y s 2 = 1 y_s^2=1 ys2=1
y s ( ∑ i ∈ S V α i y i x i T x s + b ) = y s 2     ⟹     b = y s − ∑ i ∈ S V α i y i x i T x s y_s(\sum_{i∈SV} \alpha_iy_ix_i^Tx_s+b)=y_s^2 \space\space\space⟹\space\space\space b=y_s-\sum_{i∈SV}\alpha_iy_ix_i^Tx_s ys(iSVαiyixiTxs+b)=ys2      b=ysiSVαiyixiTxs
实践中,为了得到对 b b b 更稳健的估计,通常对所有支持向量求解得到 b b b 的平均值:
b = 1 ∣ S V ∣ ∑ s ∈ S V ( y s − ∑ i ∈ S V α i y i x i T x s ) b= \frac{1}{|SV|} \sum_{s∈SV}(y_s-\sum_{i∈SV}\alpha_iy_ix_i^Tx_s) b=SV1sSV(ysiSVαiyixiTxs)

于是线性 svm 的分类决策函数可表示为:
f ( x ) = s i g n ( ∑ i ∈ S V α i y i x i T x + b ) f(x)=sign(\sum_{i∈SV} \alpha_iy_ix_i^Tx+b) f(x)=sign(iSVαiyixiTx+b)


缺点:1. 不适用于线性不可分数据集。 2. 对离群点(outlier)敏感。

比如下图就无法找到一个超平面将蓝点和紫点完全分开:

下图显示加入了一个离群点后,超平面发生了很大的变动,最后形成的间隔变得很小,这样最终的泛化效果可能不会太好。

【人工智能】SVM 分类器的设计与应用(QDU)_第2张图片

软间隔 SVM(近似线性可分 SVM)

为了缓解这些问题,引入了 “软间隔(soft margin)”,即允许一些样本点跨越间隔边界甚至是超平面。如下图中一些离群点就跨过了间隔边界。

【人工智能】SVM 分类器的设计与应用(QDU)_第3张图片

于是为每个样本点引入松弛变量 ξ i ξ_i ξi,优化问题变为:

min ⁡ w , b , ξ 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 m ξ i s . t .        y i ( w T x i + b ) ≥ 1 − ξ i ξ i ≥ 0 ,        i = 1 , 2 , . . . , m ( 3.1 ) \min \limits_{w,b,ξ}\frac{1}{2}||w||^2+C\sum_{i=1}^mξ_i \\\\ \tag{$3.1$} s.t.\space\space\space\space\space\space y_i(w^Tx_i+b)≥1-ξ_i \\ ξ_i≥0,\space\space\space\space\space\space i=1,2,...,m w,b,ξmin21w2+Ci=1mξis.t.      yi(wTxi+b)1ξiξi0,      i=1,2,...,m(3.1)
由上式可以看出:

  1. 离群点的松弛变量值越大,点就离间隔边界越远。
  2. 所有没离群的点松弛变量都等于0,即这些点都满足 y i ( w ⊤ x i + b ) ⩾ 1 y_i(w^⊤x_i+b)⩾1 yi(wxi+b)1
  3. C > 0 C>0 C>0 被称为惩罚参数,即为 scikit-learn 中的 svm 超参数C。当C设的越大,意味着对离群点的惩罚就越大,最终就会有较少的点跨过间隔边界,模型也会变得复杂。而C设的越小,则较多的点会跨过间隔边界,最终形成的模型较为平滑。

该优化问题的求解方法与硬间隔类似,为每条约束引入拉格朗日乘子: α i ⩾ 0 \alpha_i⩾0 αi0 β i ⩾ 0 \beta_i⩾0 βi0 α i ⩾ 0 \alpha_i⩾0 αi0 β i ⩾ 0 \beta_i⩾0 βi0 ( 3.1 ) (3.1) (3.1) 式的拉格朗日函数为:
L ( w , b , ξ , α , β ) = 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 m ξ i + ∑ i = 1 m α i [ 1 − ξ i − y i ( w T x i + b ) ] + ∑ i = 1 m β i ( − ξ i ) ( 3.2 ) L(w,b,ξ,\alpha, \beta)=\frac{1}{2}||w||^2+C\sum_{i=1}^mξ_i+\sum_{i=1}^m\alpha_i[1-ξ_i-y_i(w^Tx_i+b)]+\sum_{i=1}^m\beta_i(-ξ_i)\tag{$3.2$} L(w,b,ξ,α,β)=21w2+Ci=1mξi+i=1mαi[1ξiyi(wTxi+b)]+i=1mβi(ξi)(3.2)
其对偶问题为:
max ⁡ α , β min ⁡ w , b , ξ L ( w , b , ξ , α , β ) s . t .        α i ≥ 0 ,        i = 1 , 2 , . . . , m               β i ≥ 0 ,        i = 1 , 2 , . . . , m ( 3.3 ) \max \limits_{\alpha, \beta}\min\limits_{w, b, ξ}L(w,b,ξ,\alpha,\beta)\\\\ \tag{$3.3$} s.t.\space\space\space\space\space\space \alpha_i≥0,\space\space\space\space\space\space i=1,2,..., m\\ \space\space\space\space\space\space\space\space\space\space\space\space\space \beta_i≥0,\space\space\space\space\space\space i=1,2,..., m\\ α,βmaxw,b,ξminL(w,b,ξ,α,β)s.t.      αi0,      i=1,2,...,m             βi0,      i=1,2,...,m(3.3)
上式内层对 ( w , b , ξ ) (w,b,ξ) (w,b,ξ) 的优化属于无约束优化问题,则令偏导为零:
∂ L ∂ w = 0     ⟹     w = ∑ i = 1 m α i y i x i ( 3.4 ) \frac{∂L}{∂w}=0\space\space\space⟹\space\space\space w=\sum_{i=1}^m\alpha_iy_ix_i \tag{$3.4$} wL=0      w=i=1mαiyixi(3.4)

∂ L ∂ b = 0     ⟹     ∑ i = 1 m α i y i = 0 ( 3.5 ) \frac{∂L}{∂b}=0\space\space\space⟹\space\space\space \sum_{i=1}^m\alpha_iy_i=0 \tag{$3.5$} bL=0      i=1mαiyi=0(3.5)

∂ L ∂ ξ = 0     ⟹     β i = C − α i ( 3.6 ) \frac{∂L}{∂ξ}=0\space\space\space⟹\space\space\space \beta_i=C-\alpha_i \tag{$3.6$} ξL=0      βi=Cαi(3.6)

( 3.4 ) ∼ ( 3.6 ) (3.4)∼(3.6) (3.4)(3.6) 式代入 ( 3.2 ) (3.2) (3.2) 式得:
L ( w , b , ξ , α , β ) = 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j x i T x j + C ∑ i = 1 m ξ i + ∑ i = 1 m α i ( 1 − ξ i ) − ∑ i = 1 m ( C − α i ) ξ i = ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j x i T x j L(w,b,ξ,\alpha,\beta)=\frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m\alpha_i\alpha_jy_iy_jx_i^Tx_j+C\sum_{i=1}^mξ_i+\sum_{i=1}^m\alpha_i(1-ξ_i)-\sum_{i=1}^m(C-\alpha_i)ξ_i \\ =\sum_{i=1}^m\alpha_i-\frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m\alpha_i\alpha_jy_iy_jx_i^Tx_j L(w,b,ξ,α,β)=21i=1mj=1mαiαjyiyjxiTxj+Ci=1mξi+i=1mαi(1ξi)i=1m(Cαi)ξi=i=1mαi21i=1mj=1mαiαjyiyjxiTxj
又由 ( 1.6 ) (1.6) (1.6) 式: β i = C − α i ⩾ 0 β_i=C−α_i⩾0 βi=Cαi0 ,因而 0 ⩽ α i ⩽ C 0⩽α_i⩽C 0αiC ,于是最后的优化问题化简为:
max ⁡ α ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j x i T x j s . t .        ∑ i = 1 m α i y i = 0                                                0 ≤ α i ≤ C ,        i = 1 , 2 , . . . , m ( 3.7 ) \max\limits_{\alpha} \sum_{i=1}^m\alpha_i-\frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m\alpha_i\alpha_jy_iy_jx_i^Tx_j \\\\ \tag{$3.7$} s.t.\space\space\space\space\space\space \sum_{i=1}^m\alpha_iy_i=0\\ \space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space0≤\alpha_i≤C,\space\space\space\space\space\space i=1,2,...,m αmaxi=1mαi21i=1mj=1mαiαjyiyjxiTxjs.t.      i=1mαiyi=0                                              0αiC,      i=1,2,...,m(3.7)
求得 α ∗ = ( α 1 ∗ , α 2 ∗ , . . . , α m ∗ ) T \alpha^*=(\alpha^*_1, \alpha^*_2,...,\alpha^*_m)^T α=(α1,α2,...,αm)T中对应于 α i ∗ > 0 \alpha_i^*>0 αi>0的样本点 ( x i , y i ) (x_i,y_i) (xi,yi)的实例 x i x_i xi
ξ i ≥ 0        ⟺        { ξ i = 0 ,        x i 在 间 隔 边 界 上 0 < ξ i < 1 ,        x i 在 间 隔 边 界 于 分 离 超 平 面 之 间 ξ i = 1 ,        x i 在 分 离 超 平 面 上 ξ i > 1 ,        x i 在 分 离 超 平 面 误 分 类 一 侧 ξ_i≥0\space\space\space\space\space\space ⟺\space\space\space\space\space\space \begin{cases} ξ_i=0, \space\space\space\space\space\space x_i在间隔边界上\\ 0<ξ_i<1,\space\space\space\space\space\space x_i在间隔边界于分离超平面之间 \\ ξ_i=1,\space\space\space\space\space\space x_i在分离超平面上 \\ ξ_i>1,\space\space\space\space\space\space x_i在分离超平面误分类一侧 \\ \end{cases} ξi0            ξi=0,      xi0<ξi<1,      xiξi=1,      xiξi>1,      xi

软间隔SVM允许样本有一定程度的误分类。但其实本质依然是线性分类器。

核方法(线性不可分 SVM)

问题引入:
有一个故事,劫匪绑架了富豪的妻子,绑匪威胁富豪,如果能将桌子上的豆子和沙子分开,就放掉他的妻子,否则不仅要杀掉他的妻子还要抢走他的钱。首先,劫匪将沙子和豆子完美地放在了不同的两侧,富豪画了一条线就将这些豆子和沙子分开了;接着,劫匪提高了难度,他将沙子和豆子混乱地撒在了桌子上,让富豪将它们分开。富豪思考了一会,只见他一巴掌拍在了桌子上,沙子由于质地比较轻,所以弹地更高,而豆子比较沉,所以弹地比较低,富豪拿网一接便成功将两类分开。富豪保住了妻子和钱财。
其实对于第一种情况,就相当于硬间隔SVM,不同的两类完美地位于不同的两侧;第二种情况就对应线性不可分的SVM,两类样本比较混乱的分布在一起,通过一个超平面分开比较困难,因此我们通过核函数将样本映射到更高维度的空间使样本可以通过一个超平面分开。这也就对应着富豪将平面上的沙子和豆子拍起到带高度的三维空间中便将两类分开了。

前面展示的硬间隔和软间隔 svm 主要是用于处理线性分类问题,然而现实中很多分类问题是非线性的,如下图所示,无论怎样一个线性超平面都无法很好地将样本点分类:

【人工智能】SVM 分类器的设计与应用(QDU)_第4张图片

所以在此引入核函数(kernel function),构造非线性svm,如下图所示,左图使用的是多项式核函数,右图使用的是高斯核函数,二者均能将样本点很好地分类:

【人工智能】SVM 分类器的设计与应用(QDU)_第5张图片

核函数的主要作用是将样本从原始空间映射到一个更高维的特征空间,使得样本在这个特征空间内线性可分。下图显示原来在二维空间不可分的两类样本点,在映射到三维空间后变为线性可分:

【人工智能】SVM 分类器的设计与应用(QDU)_第6张图片

但回到原来的二维空间中,决策边界就变成非线性的了:

【人工智能】SVM 分类器的设计与应用(QDU)_第7张图片

核函数是如何将原始空间映射到高维的特征空间的? 下面先举个例子:

假设做一个2维到3维的映射, Φ : R 2 ⟶ R 3 Φ:R^2⟶R^3 Φ:R2R3
ϕ ( x ) = ϕ ( x 1 x 2 ) = ( x 1 2 2 x 1 x 2 x 2 2 ) \phi(x)= \phi \left( \begin{matrix}{} x_1\\x_2 \end{matrix} \right)= \left( \begin{matrix}{} x_1^2\\\sqrt{2}x_1x_2\\x_2^2 \end{matrix} \right) ϕ(x)=ϕ(x1x2)=x122 x1x2x22

ϕ ( a ) ϕ(a) ϕ(a) ϕ ( b ) ϕ(b) ϕ(b) 的内积:
ϕ ( a ) T ϕ ( b ) = ( a 1 2 2 a 1 a 2 a 2 2 ) T ⋅ ( b 1 2 2 b 1 b 2 b 2 2 ) = a 1 2 b 1 2 + 2 a 1 b 1 a 2 b 2 + a 2 2 b 2 2 = ( a 1 b 1 + a 2 b 2 ) 2 = ( ( a 1 a 2 ) T ( b 1 b 2 ) ) 2 = ( a T b ) 2 \phi(a)^T\phi(b)= \left( \begin{matrix}{} a_1^2\\\sqrt{2}a_1a_2\\a_2^2 \end{matrix} \right)^T · \left( \begin{matrix}{} b_1^2\\\sqrt{2}b_1b_2\\b_2^2 \end{matrix} \right) \\= a_1^2b_1^2 + 2a_1b_1a_2b_2+a_2^2b_2^2 =(a_1b_1+a_2b_2)^2= \left( \begin{matrix}{} \left( \begin{matrix}{} a_1\\a_2 \end{matrix} \right)^T \left( \begin{matrix}{} b_1\\b_2 \end{matrix} \right) \end{matrix} \right)^2= (a^Tb)^2 ϕ(a)Tϕ(b)=a122 a1a2a22Tb122 b1b2b22=a12b12+2a1b1a2b2+a22b22=(a1b1+a2b2)2=((a1a2)T(b1b2))2=(aTb)2
可以看出转换后向量的内积等于原向量内积的平方,即 ϕ ( a ) T ϕ ( b ) = ( a T b ) 2 ϕ(a)^Tϕ(b)=(a^Tb)^2 ϕ(a)Tϕ(b)=(aTb)2

函数 κ ( a , b ) = ( a T b ) 2 κ(a,b)=(a^Tb)^2 κ(a,b)=(aTb)2 被称为二次多项核函数,于是如果想计算高维特征空间的内积 ϕ ( a ) T ϕ ( b ) ϕ(a)^Tϕ(b) ϕ(a)Tϕ(b),我们只需计算核函数,即原向量内积的平方 ( a T b ) 2 (a^Tb)^2 (aTb)2 就可以了。这样做的好处有:

  • 将样本点由原始空间映射到高维空间后,有大概率使原来线性不可分的问题变为线性可分。
  • 核函数的计算是在低维特征空间计算的,它避免了在高维特征空间下计算内积的超高计算量。

接下来对问题作正式的定义: 数据在原始特征空间 R d R^d Rd 不是线性可分的,则希望通过一个映射 Φ : R d ⟶ R d ~ Φ:R^d⟶R^{\tilde{d}} Φ:RdRd~

,使得数据在新的特征空间 R d ~ R^{\tilde{d}} Rd~ 中线性可分,则软间隔 svm 基本型变为:
min ⁡ w , b , ξ 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 m ξ i s . t .       y i ( w T ϕ ( x i ) + b ) ≥ 1 − ξ i ,       i = 1 , 2 , . . . , m ξ i ≥ 0 ,       i = 1 , 2 , . . . , m \min \limits_{w,b,ξ}\frac{1}{2}||w||^2+C\sum_{i=1}^mξ_i \\\\ s.t. \space\space\space\space\space y_i(w^T\phi(x_i)+b)≥1-ξ_i, \space\space\space\space\space i=1,2,...,m\\ ξ_i≥0,\space\space\space\space\space i=1,2,...,m w,b,ξmin21w2+Ci=1mξis.t.     yi(wTϕ(xi)+b)1ξi,     i=1,2,...,mξi0,     i=1,2,...,m
找到一个核函数 κ ( x i , x j ) = ϕ ( x i ) ⊤ ϕ ( x j ) κ(x_i,x_j)=ϕ(x_i)^⊤ϕ(x_j) κ(xi,xj)=ϕ(xi)ϕ(xj) ,则相应的对偶型转化为核函数型:
max ⁡ α ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j ϕ ( x i ) ⊤ ϕ ( x j ) s . t .       ∑ i = 1 m α i y i = 0                                              0 ≤ α i ≤ C ,       i = 1 , 2 , . . . , m ⟹                                                                                            max ⁡ α ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j κ ( x i , x j ) s . t .       ∑ i = 1 m α i y i = 0                                              0 ≤ α i ≤ C ,       i = 1 , 2 , . . . , m \max \limits_{\alpha} \sum_{i=1}^m \alpha_i-\frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m\alpha_i\alpha_jy_iy_jϕ(x_i)^⊤ϕ(x_j) \\\\ s.t.\space\space\space\space\space \sum_{i=1}^m\alpha_iy_i=0 \\ \space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space 0≤ \alpha_i ≤ C,\space\space\space\space\space i=1,2,...,m \\\\⟹\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\\\\ \max \limits_{\alpha} \sum_{i=1}^m \alpha_i-\frac{1}{2}\sum_{i=1}^m\sum_{j=1}^m\alpha_i\alpha_jy_iy_jκ(x_i,x_j) \\\\ s.t.\space\space\space\space\space \sum_{i=1}^m\alpha_iy_i=0 \\ \space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space\space 0≤ \alpha_i ≤ C,\space\space\space\space\space i=1,2,...,m αmaxi=1mαi21i=1mj=1mαiαjyiyjϕ(xi)ϕ(xj)s.t.     i=1mαiyi=0                                            0αiC,     i=1,2,...,m                                                                                          αmaxi=1mαi21i=1mj=1mαiαjyiyjκ(xi,xj)s.t.     i=1mαiyi=0                                            0αiC,     i=1,2,...,m
这样使得计算复杂度由 O ( d ~ ) O(\tilde{d}) O(d~) 降为 O ( d ) O(d) O(d) 。求解后的分离超平面为:
f ( x ) = w T ϕ ( x ) + b = ∑ i ∈ S V α i y i ϕ ( x i ) T ϕ ( x ) + b = ∑ i ∈ S V α i y i κ ( x i , x ) + b f(x)=w^T\phi(x)+b \\\\ =\sum_{i∈SV}\alpha_iy_i\phi(x_i)^T\phi(x)+b \\\\ =\sum_{i∈SV}\alpha_iy_iκ(x_i,x)+b f(x)=wTϕ(x)+b=iSVαiyiϕ(xi)Tϕ(x)+b=iSVαiyiκ(xi,x)+b
其中 S V SV SV 代表所有支持向量的集合。这样我们就能以较小的计算量解决非线性分类问题,甚至都不需要知道低维空间的数据是怎样映射到高维空间的,只需要在原来的低维空间计算核函数就行了。

名称 形式 优点 缺点
线性核 κ ( x i , x j ) = x i T x j κ(x_i,x_j)=x_i^Tx_j κ(xi,xj)=xiTxj 速度快,可解释性强。 无法解决非线性可分问题。
多项式核 κ ( x i , x j ) = ( λ x i T x j + η ) d κ(x_i,x_j)=(\lambda x_i^Tx_j+\eta)^d κ(xi,xj)=(λxiTxj+η)d 比线性核更一般, d d d 直接描述了被映射空间的复杂度。 参数多 (有 λ λ λ η η η d d d 要选),且当 d d d 很大时会导致计算不稳定。
径向基函数(RBF 核函数) κ ( x i , x j ) = e x p ( − ∣ x i − x j ∣ 2 2 σ 2 ) κ(x_i,x_j)=exp(-\frac{|x_i-x_j|^2}{2\sigma^2}) κ(xi,xj)=exp(2σ2xixj2) 只有一个参数,无计算不稳定问题,拟合能力强。 可解释性差,计算慢,易过拟合。
                 |

PCA

这部分不进行公式的推导和证明。仅说明降维过程。

PCA(Principal Component Analysis),即主成分分析方法,是一种使用最广泛的数据降维算法。PCA的主要思想是将n维特征映射到k维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征。PCA的工作就是从原始的空间中顺序地找一组相互正交的坐标轴,新的坐标轴的选择与数据本身是密切相关的。其中,第一个新坐标轴选择是原始数据中方差最大的方向,第二个新坐标轴选取是与第一个坐标轴正交的平面中使得方差最大的,第三个轴是与第1,2个轴正交的平面中方差最大的。依次类推,可以得到n个这样的坐标轴。通过这种方式获得的新的坐标轴,我们发现,大部分方差都包含在前面k个坐标轴中,后面的坐标轴所含的方差几乎为0。于是,我们可以忽略余下的坐标轴,只保留前面k个含有绝大部分方差的坐标轴。事实上,这相当于只保留包含绝大部分方差的维度特征,而忽略包含方差几乎为0的特征维度,实现对数据特征的降维处理。

PCA降维的一般步骤:

  1. 计算每个特征的均值
  2. 对每个特征数据进行中心化,即原数据-特征均值
  3. 计算特征的协方差矩阵,得到的矩阵大小为特征数×特征数
  4. 获取矩阵的特征值与特征向量
  5. 按特征值从大到小排序
  6. 选取前 n n n个特征向量, n n n为降维到的维度
  7. 选出的 n n n个特征向量即为降维矩阵,用原数据与降维矩阵相乘得到降维后的矩阵

SVM 实现多分类

SVM 是一个二分器,只能用于 2 类样本的分类,现在将它推广到多类问题。可采用一对一的投票策略。

例如:将 A A A B B B C C C D D D 4 类样本分成多个两类分类训练集,即 ( A , B ) (A,B) (A,B) ( A , C ) (A,C) (A,C) ( A , D ) (A,D) (A,D) ( B , C ) (B,C) (B,C) ( B , D ) (B,D) (B,D) ( C , D ) (C,D) (C,D),得到 6 个(对于 n n n类问题,需要 n ( n − 1 ) / 2 n(n-1)/2 n(n1)/2)个SVM 二分器。在测试的时候,把测试样本 x x x 依次送入这 6 个二分器,采取投票形式,最后得到一组结果。

投票是以如下方式进行:

初始化:

  • v o t e ( A ) = v o t e ( B ) = v o t e ( C ) = v o t e ( D ) = 0 vote(A)=vote(B)=vote(C)=vote(D)=0 vote(A)=vote(B)=vote(C)=vote(D)=0

投票过程:

  • 如果使用训练集 ( A , B ) (A,B) (A,B) 得到的分类器将 x x x 判定为 A A A 类,则 v o t e ( A ) = v o t e ( A ) + 1 vote(A)=vote(A)+1 vote(A)=vote(A)+1,否则 v o t e ( B ) = v o t e ( B ) + 1 vote(B)=vote(B)+1 vote(B)=vote(B)+1
  • 如果使用 ( A , C ) (A,C) (A,C) 训练的分类器将 x x x 判定为 A A A 类,则 v o t e ( A ) = v o t e ( A ) + 1 vote(A)=vote(A)+1 vote(A)=vote(A)+1,否则 v o t e ( C ) = v o t e ( C ) + 1 vote(C)=vote(C)+1 vote(C)=vote(C)+1
  • . . . ... ...
  • 如果使用 ( C , D ) (C,D) (C,D) 训练的分类器将 x x x 判定为 C C C 类,则 v o t e ( C ) = v o t e ( C ) + 1 vote(C)=vote(C)+1 vote(C)=vote(C)+1,否则 v o t e ( D ) = v o t e ( D ) + 1 vote(D)=vote(D)+1 vote(D)=vote(D)+1

最终判决:

  • M a x ( v o t e ( A ) , v o t e ( B ) , v o t e ( C ) , v o t e ( D ) ) Max(vote(A),vote(B),vote(C),vote(D)) Max(vote(A),vote(B),vote(C),vote(D))
  • 如有两个以上的最大值,则一般可以简单地取第一个最大值所对应的类别。

实验内容

数据库的选择

可选取 ORL 人脸数据库作为实验样本,总共 40 个人,每人 10 幅图像,图像大小为112 * 92 像素。图像本身已经经过处理,不需要进行归一化和校准等工作。实验样本分为训练样本和测试样本。首先设置训练样本集,选择 40 个人前 5 张图片作为训练样本,进行训练。然后设置测试样本集,将 40 个人后 5 张图片作为测试样本,进行选取识别。

实验基本步骤

这里写的是我的实验步骤,与《实验指导书》的步骤不同。

人脸识别算法步骤概述:

  1. 读取训练数据集

    导入数据集,一半数据作为训练集,另一半作为测试集,采用train_test_split以百分之五十的训练集与测试集数据量之比对数据集进行随机划分。

  2. 主成分分析法降维并去除数据之间的相关性

    使用的是sklearn中自带的PCA函数实现主成分分析降维。(手写了PCA,但是应该没有sklearn的效果好)

  3. SVM 训练

    对比不同的核函数对分类效果的影响,采用10折交叉验证的方式计算得分,比较在不同的降维维度下不同核函数的分类效果。

  4. 多分类

    直接使用SVC函数的参数来实现ovr多分类。

  5. 对比径向基核函数和多项式核函数,计算正确率

    打印完整数据集的正确率、训练集的正确率核测试集的正确率,并采用观察混淆矩阵等方式对模型的性能进行评估。

  6. 对比多种核函数,比较得分

实验过程

导入数据集并创建标签

首先使用Matlab获取每幅图的像素矩阵,保存于excel中;

数据规模:400 × 10304,每一行表示一个样本,从第一行开始每连续的十个样本为同一个人,即具有相同的标签。由于每幅图像的大小为112 × 92,所以每幅图总共10304个特征,即列数;

在python中导入数据,并为400个样本创建标签列表。

PCA降维确定最佳降维维度

由于样本的特征个数过多,难免某些特征会具有相关性,PCA降维的目的就是将具有相关性的特征仅保留一个。

确定最佳降维维度:

【人工智能】SVM 分类器的设计与应用(QDU)_第8张图片

绘制“降维维度-份额”曲线,观察可以发现当降维维度达到10、11左右后开始变得平缓,说明降维效果并不明显了,因此,选定11维为最佳降维维度。

这里选定11维作为降维维度的意义在于,如果将该模型投入使用,用于人脸识别,则应将样本先降至11维再进行分类等操作。

对比径向基核函数和多项式核函数

使用train_test_split以50%的比例划分数据集后,使用不同维度的训练集训练标准化模型、PCA模型和SVM模型;

维度的采样点为20, 50, 100, 200,将全部数据集、训练集和测试集分别投入模型,绘制两种核函数下SVM的“维度-得分”曲线,同时观察不同的样本对模型得分的影响,即评估模型的稳定性。

(这里的“得分”是使用“分类正确率”表示的)

【人工智能】SVM 分类器的设计与应用(QDU)_第9张图片

完整数据集中:
径向基核函数rbf的精确度变化:
 [0.955, 0.965, 0.9675, 0.9675]
多项式核函数poly的精确度变化:
 [0.8025, 0.8075, 0.8025, 0.7975]
 
 
训练集中:
径向基核函数rbf的精确度变化:
 [0.985, 0.995, 0.995, 1.0]
多项式核函数poly的精确度变化:
 [0.9, 0.92, 0.935, 0.955]
 
 
测试集中:
径向基核函数rbf的精确度变化:
 [0.925, 0.935, 0.94, 0.935]
多项式核函数poly的精确度变化:
 [0.705, 0.695, 0.67, 0.64]

观察曲线,发现无论是对于整个数据集而言,还是训练集和测试集而言,径向基核函数SVM的得分都要高于多项式核函数,且正确率维持在90%之上,而多项式核函数SVM在测试集上的得分甚至存在低于70%的情况。由此可见,径向基函数的分类效果明显优于多项式核函数。

对比多种核函数

测试集的混淆矩阵:

【人工智能】SVM 分类器的设计与应用(QDU)_第10张图片

采用10折交叉验证对比径向基核函数、线性核函数、多项式核函数和逻辑回归核函数的“维度-得分”曲线:

【人工智能】SVM 分类器的设计与应用(QDU)_第11张图片

观察可以发现线性核函数和径向基核函数的效果相似且效果都比较好,多项式核函数随着降维维度的升高反而出现得分降低的情况。

还可以发现当维度大于25左右时,得分变化趋于平缓,说明降维维度再高分类效果也不会有显著提升。对于直观上选取的11维作为最佳降维维度不够准确,可以根据得分曲线将最佳降维维度确定于25左右。

附录(代码)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


def load_dataset(path, people_num=40):
    """
    加载数据集
    :param path: 数据路径
    :param people_num: 数据集分类数量
    :param sample_num: 数据集每类样本数量
    :return: 数据集
    """
    sample_num = 10
    dataset = pd.read_excel(path, header=None) # (people_num*sample_num) × (112*92) 特征
    dataset = np.array(dataset)
    X = dataset[:people_num*sample_num, :]
    Y = [] # 标签
    for i in range(0, people_num):
        tmp = (i * np.ones(sample_num, dtype=int)).tolist()
        Y.extend(tmp)
    Y = np.array(Y)

    return X, Y

def plot_nPC(pca, n=50):
    var = pca.explained_variance_ratio_
    # 通过拐点确定选择前几个PC
    plt.plot(var)
    plt.title('Scree Plot', fontsize=15)
    plt.xlabel('Number of Principal Component', fontsize=13)
    plt.ylabel('Proportion', fontsize=13)
    plt.xticks(np.arange(1, n+1, 1), rotation=-30)
    leg = plt.legend(['Proportion of variance from PCA'],
                     loc='best',
                     borderpad=0.3,
                     shadow=False,
                     markerscale=0.4)

    leg.get_frame().set_alpha(0.4)
    leg.draggable(state=True)
    plt.grid()

def analyse_data(X, Y):
    pca, X_pca = PCA(X, dimension=50) # 前50个主成分

    plot_nPC(pca) # 绘制前50个主成分的方差占比
    plt.show()

def PCA(X, dimension):
    """
    进行PCA降维
    :param X: 原始数据集(可能是训练集、测试集或者完整数据集)
    :param dimension: 降到多少维
    :return: 训练的模型 和 降维后的原始数据集
    """
    from sklearn.preprocessing import StandardScaler  # 标准差标准化
    from sklearn.decomposition import PCA  # 特征分解模块的PCA用于降维

    X_std = StandardScaler().fit_transform(X)  # 标准化
    pca = PCA(n_components=dimension)
    pca.fit(X_std)

    return pca, pca.transform(X_std)


def contrast_different_kernel(X, Y, decision_function_shape, test_size=0.5):
    from sklearn.model_selection import train_test_split # 划分数据集
    from sklearn.svm import SVC  # svm包中SVC用于分类
    from sklearn.model_selection import cross_val_score # 交叉验证

    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=test_size, stratify=Y) # 划分数据集

    kernels = ['rbf', 'linear', 'poly', 'sigmoid'] # SVM选取内核
    dimension = [3, 5, 11, 20, 50, 100, 200]
    colors = ['red', 'cyan', 'blue', 'lightgreen', 'gray']

    for i in np.arange(0, len(kernels)):
        accuracy = []
        for d in dimension:
            pca, X_pca = PCA(X, d)
            svm = SVC(kernel=kernels[i], decision_function_shape=decision_function_shape).fit(X, Y)
            scores = cross_val_score(svm, X_pca, Y, cv=10)
            Y_test_predict = svm.predict(X_test)
            # plot_confusion_matrix(Y_test, Y_test_predict, title=kernels[i]+' confusion matrix')
            accuracy.append(scores.mean())
        plt.plot(dimension, accuracy, colors[i])
    plt.xlabel('Dimension', fontsize=13)
    plt.ylabel('Scores', fontsize=13)
    plt.legend(kernels, loc='upper right')
    plt.title('SVM with different kernels (10-fold cross-validation)', fontsize=15)
    plt.show()

def plot_confusion_matrix(test_label_original, test_label_predict, title):
    # 混淆矩阵
    from sklearn.metrics import confusion_matrix
    cm = confusion_matrix(test_label_original, test_label_predict)
    fig, ax = plt.subplots(figsize=(10, 10))
    ax.matshow(cm, cmap=plt.cm.Greens, alpha=0.3)
    for i in range(cm.shape[0]):
        for j in range(cm.shape[1]):
            ax.text(x=j, y=i,
                    s=cm[i, j],
                    va='center', ha='center')
    plt.xlabel('Predicted Values', fontsize=13)
    plt.ylabel('Actual Values', fontsize=13)
    plt.title(title, fontsize=15)
    plt.show()

def different_dataset_plot_rbf_poly_curve(model_rbf, model_poly, X, true_label):
    """
    计算降维至20,50,100,200时对数据集X的预测结果的正确率
    :param model_rbf: 保存20,50,100,200的rbfSVM模型
    :param model_poly:保存20,50,100,200的polySVM模型
    :param X: 保存20,50,100,200的数据集(也就是标准化且PCA后的数据)
    :param true_label: 对应的真实标签
    :return: 两种核函数的正确率变化
    """
    accuracy_rbf = []  # 正确率
    accuracy_poly = []
    for svm_rbf, svm_poly, i in zip(model_rbf, model_poly, [0,1,2,3]):
        pred_rbf = svm_rbf.predict(X[i])
        pred_poly = svm_poly.predict(X[i])

        true_rbf = 0  # 核为rbf的模型分类正确的个数
        true_poly = 0  # 核为poly的模型分类正确的个数
        for i in range(0, true_label.shape[0]):
            if pred_rbf[i] == true_label[i]:
                true_rbf += 1
            if pred_poly[i] == true_label[i]:
                true_poly += 1
        accuracy_rbf.append(true_rbf / true_label.shape[0])
        accuracy_poly.append(true_poly / true_label.shape[0])

    return accuracy_rbf, accuracy_poly

def compare_rbf_poly(X, Y, test_size=0.5):
    """

    :param X:
    :param Y:
    :param test_size:
    :return:
    """
    from sklearn import decomposition
    from sklearn.model_selection import train_test_split  # 划分数据集
    from sklearn.svm import SVC  # svm包中SVC用于分类
    from sklearn.preprocessing import StandardScaler  # 标准差标准化

     # 标准化
    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=test_size, stratify=Y)  # 划分数据集

    stdScaler = StandardScaler().fit(X_train) # 原数据集、训练集和测试集要使用同一个STD(标准化)模型!!!
    X_train = stdScaler.transform(X_train)
    X_test = stdScaler.transform(X_test)
    X = stdScaler.transform(X)

    dimension = [20, 50, 100, 200]
    X_dataset_pca_s = []
    X_train_pca_s = []
    X_test_pca_s = []

    # X_dataset_pca_s = 原数据集 [降到20, 降到50, 降到100, 降到200]
    # X_train_pca_s = 训练集 [降到20, 降到50, 降到100, 降到200]
    # X_test_pca_s = 测试集 [降到20, 降到50, 降到100, 降到200]
    for d in dimension:
        pca = decomposition.PCA(n_components=d).fit(X_train) # 原数据集、训练集和测试集要使用同一个PCA模型!!!
        X_dataset_pca = pca.transform(X)
        X_dataset_pca_s.append(X_dataset_pca)
        X_train_pca = pca.transform(X_train)
        X_train_pca_s.append(X_train_pca)
        X_test_pca = pca.transform(X_test)
        X_test_pca_s.append(X_test_pca)

    model_rbf = []
    model_poly = []
    # rbf:核函数为rbf,[20维数据训练出的SVM, 50维数据训练出的SVM, 100维数据训练出的SVM, 200维数据训练出的SVM]
    # poly:核函数为poly,[20维数据训练出的SVM, 50维数据训练出的SVM, 100维数据训练出的SVM, 200维数据训练出的SVM]
    for i in range(0, len(dimension)):
        model_rbf.append(SVC(kernel='rbf').fit(X_train_pca_s[i], Y_train.ravel()))
        model_poly.append(SVC(kernel='poly').fit(X_train_pca_s[i], Y_train.ravel()))

    accuracy_dataset_rbf, accuracy_dataset_poly = \
        different_dataset_plot_rbf_poly_curve(model_rbf, model_poly, X_dataset_pca_s, Y)
    accuracy_train_dataset_rbf, accuracy_train_dataset_poly = \
        different_dataset_plot_rbf_poly_curve(model_rbf, model_poly, X_train_pca_s, Y_train)
    accuracy_test_dataset_rbf, accuracy_test_dataset_poly = \
        different_dataset_plot_rbf_poly_curve(model_rbf, model_poly, X_test_pca_s, Y_test)

    print("完整数据集中:")
    print("径向基核函数rbf的精确度变化:\n", accuracy_dataset_rbf)
    print("多项式核函数poly的精确度变化:\n",accuracy_dataset_poly)

    print("训练集中:")
    print("径向基核函数rbf的精确度变化:\n", accuracy_train_dataset_rbf)
    print("多项式核函数poly的精确度变化:\n", accuracy_train_dataset_poly)

    print("测试集中:")
    print("径向基核函数rbf的精确度变化:\n", accuracy_test_dataset_rbf)
    print("多项式核函数poly的精确度变化:\n", accuracy_test_dataset_poly)

    # colors = ('red', 'dodgerblue', 'lightgreen', 'gray', 'cyan', 'darkorchid')
    # 整个数据集
    plt.plot(dimension, accuracy_dataset_rbf, color='red', linestyle='-')
    plt.plot(dimension, accuracy_dataset_poly, color='dodgerblue', linestyle='-')
    # 训练集
    plt.plot(dimension, accuracy_train_dataset_rbf, color='lightgreen', linestyle='--')
    plt.plot(dimension, accuracy_train_dataset_poly, color='gray', linestyle='--')
    # 测试集
    plt.plot(dimension, accuracy_test_dataset_rbf, color='cyan', linestyle=':')
    plt.plot(dimension, accuracy_test_dataset_poly, color='darkorchid', linestyle=':')

    plt.rcParams['font.family'] = ['SimHei']

    plt.legend(['AllDataSet---kernel=\'rbf\'', 'AllDataSet---kernel=\'poly\''
                   , 'TrainDataSet---kernel=\'rbf\'', 'TrainDataSet---kernel=\'poly\''
                   , 'TestDataSet---kernel=\'rbf\'', 'TestDataSet---kernel=\'poly\'']
               , loc='upper right'
               , bbox_to_anchor=(1, 1.15)
               , borderaxespad=0.)
    plt.title('Compare RBF and POLY', fontsize=15)
    plt.xlabel('Dimension', fontsize=13)
    plt.ylabel('Scores', fontsize=13)
    plt.show()

if __name__ == '__main__':

    print('数据导入中......')
    ORL_path = 'dataset.xlsx'
    X, Y = load_dataset(path=ORL_path, people_num=40)
    print('数据导入成功')

    # analyse_data(X, Y)
    # best_dimension = 11 # 观察可知最佳降维到11维
    #
    # pca, X_pca = PCA(X, best_dimension)

    # 对比径向基核函数和多项式核函数
    compare_rbf_poly(X, Y)

    # 对比多种核函数
    contrast_different_kernel(X, Y, decision_function_shape='ovr') # 使用的原始数据集

你可能感兴趣的:(【人工智能】,支持向量机,人工智能,机器学习)