支援向量機(SVM)從原理到python程式碼實現

楓胤雪發表於2020-12-10

在如下圖所示的二分類問題裡,我們在訓練分類器時就是希望找到一個最優的超平面。直觀來講,我們希望找到如圖所示的一個通道(Margin)能夠區分正負樣本,最大化其寬度,取其中間線為超平面。直觀來說,這樣得到的超平面更具有泛化能力。

圖1我們準備討論的SVM就是採用的這個思想:尋找一個分類器,使其有最大化的Margin。

SVM的優化問題

令訓練集中的資料為 { x i , t i } 1 N , x i ∈ R d , t i ∈ { 1 , − 1 } \{x_i,t_i\}_1^N,x_i\in \mathbb{R}^d,t_i\in\{1,-1\} {xi,ti}1N,xiRdti{1,1},即有N個資料,每個資料的輸入x的維度為d,且所要分類的目標值用1和-1表示。

那麼超平面可以表示為 w T x + b = 0 w^Tx+b = 0 wTx+b=0,w為權重,b為bias或叫位移項。
圖二

那麼,如上圖所示,不難得到這個Margin的寬度為 2 ∣ ∣ w ∣ ∣ \frac{2}{||w||} w2。為了使其儘量寬,就需要是的權重的norm足夠小。這樣我們就得到了SVM裡的優化問題:

a r g m i n w , b 1 2 ∣ ∣ w ∣ ∣ 2 \underset{w,b}{\mathbf{argmin}}\frac12||w||^2 w,bargmin21w2,且其約束條件為

t n ( w T x n + b ) ≥ 1 ∀ n = 1 , 2 , . . . N t_n(w^Tx_n+b)\ge1 \quad \forall n = 1,2,...N tn(wTxn+b)1n=1,2,...N

那麼如何通過這一系列的約束來得到最優的結果呢?SVM裡引入拉格朗日乘子法來找到最優解。

拉格朗日乘子法與對偶問題

如下圖所示,假設有函式 f ( x , y ) f(x,y) f(x,y),要求其極值(最大值/最小值),且滿足約束條件 g ( x , y ) = 0 g(x,y) = 0 g(x,y)=0,這裡令c為0。對不同 d n d_n dn的值,不難想像出 f ( x , y ) = d n f(x,y) = d_n f(x,y)=dn的等高線。

圖三

不難看出當 f ( x , y ) = d n f(x,y) = d_n f(x,y)=dn的等高線與 g ( x , y ) = 0 g(x,y) = 0 g(x,y)=0曲線相切的時候, f ( x , y ) f(x,y) f(x,y)取到極值點,且在這個極值點處, f ( x , y ) f(x,y) f(x,y) g ( x , y ) = 0 g(x,y) = 0 g(x,y)=0的梯度是相切的。

拉格朗日乘子法

對於一般情況,對於要求極值的函式 f ( x ) , x ∈ R d f(x),x\in \mathbb{R}^d f(x),xRd(函式有d維變數x),滿足 g ( x ) = 0 g(x)=0 g(x)=0的約束。由前面二維的例子看出,該問題的目標是在由 g ( x ) = 0 g(x)=0 g(x)=0確定的 d − 1 d-1 d1維約束曲面上尋找 f ( x ) f(x) f(x)的極值點。那麼不難得到:

  • 對於約束曲面上的任一點x,該點的梯度 ▽ g ( x ) \triangledown g(x) g(x)正交於約束平面
  • 對於極值點 x ∗ x^* x,目標函式 f ( x ∗ ) f(x^*) f(x)在該點的梯度 ▽ f ( x ∗ ) \triangledown f(x^*) f(x)正交於約束平面

由此,在極值點 x ∗ x^* x處,梯度 ▽ g ( x ∗ ) , ▽ f ( x ∗ ) \triangledown g(x^*),\triangledown f(x^*) g(x),f(x)的方向必相同或相反,即存在 λ ≠ 0 \lambda\ne 0 λ=0使得:
▽ f ( x ∗ ) + λ ▽ g ( x ∗ ) = 0 \triangledown f(x^*)+\lambda\triangledown g(x^*) = 0 f(x)+λg(x)=0
λ \lambda λ稱為拉格朗日乘子,其定義拉格朗日函式:
L ( x , λ ) = f ( x ) + λ g ( x ) L(x,\lambda)=f(x)+\lambda g(x) L(x,λ)=f(x)+λg(x)
這樣 L ( x , λ ) L(x,\lambda) L(x,λ)的極值也就是 f ( x ) f(x) f(x) g ( x ) g(x) g(x)約束下的極值,然後我們就把原約束問題轉換為拉格朗日函式 L ( x , λ ) L(x,\lambda) L(x,λ)無約束問題

KKT條件

但是在SVM裡,我們的優化問題的約束條件是不等式 y n ( w T x n + b ) − 1 ≥ 0 y_n(w^Tx_n+b)-1\ge 0 yn(wTxn+b)10,那麼我們需要分兩種情況討論

  1. 如果極值點落在了邊界上,即 g ( x ∗ ) = 0 g(x^*) = 0 g(x)=0,那麼就是上面的情況,這時就存在 λ > 0 \lambda>0 λ>0使得:

    ▽ f ( x ∗ ) + λ ▽ g ( x ∗ ) = 0 \triangledown f(x^*)+\lambda\triangledown g(x^*) = 0 f(x)+λg(x)=0

  2. 如果極值點落在邊界內,即 g ( x ∗ ) > 0 g(x^*) > 0 g(x)>0,那麼最值點就是極值點,直接令 λ = 0 \lambda = 0 λ=0,對 f ( x ) f(x) f(x)求梯度即可得到極值

綜合上面2種情況我們可以得到Karush-Kuhn-Tucker (KKT)條件:
{ λ ≥ 0 g ( x ) ≥ 0 λ g ( x ) = 0 \begin{aligned} \begin{cases} \lambda \ge 0\\ g(x)\ge0\\ \lambda g(x)=0 \end{cases} \end{aligned} λ0g(x)0λg(x)=0
通俗意義理解KKT條件的話就是目標函式在約束條件下取得極值的充要條件,也就是目標函式在約束條件下取得極值時對應的x,λ必須滿足KKT條件,反之亦然。

多問題約束推廣

將上述做法推廣到m個等式約束和n個不等式約束,且可行域非空的優化問題。
m i n x f ( x ) , x ∈ R d h i ( x ) = 0 ( i = 1 , . . . , m ) g j ( x ) ≥ 0 ( j = 1 , . . . , n ) \begin{aligned} &min_xf(x), x\in \mathbb{R}^d\\ h_i&(x)= 0(i=1,...,m)\\ g_j&(x)\ge 0(j = 1,...,n) \end{aligned} higjminxf(x),xRd(x)=0(i=1,...,m)(x)0(j=1,...,n)
引入拉格朗日乘子 λ = ( λ 1 , λ 2 , . . . , λ m ) . T , μ = ( μ 1 , μ 2 , . . . , μ n ) . T \lambda=(\lambda_1,\lambda_2,...,\lambda_m).T , \mu=(\mu_1,\mu_2,...,\mu_n).T λ=(λ1λ2,...,λm).T,μ=(μ1,μ2,...,μn).T, 相應的拉格朗日函式為:
L ( x , λ , μ ) = f ( x ) + ∑ i = 1 m λ i h i ( x ) + ∑ j = 1 n μ j g j ( x ) L(x,\lambda,\mu) = f(x)+\sum_{i=1}^m\lambda_i h_i(x)+\sum_{j=1}^n\mu_j g_j(x) L(x,λ,μ)=f(x)+i=1mλihi(x)+j=1nμjgj(x)
由不等式約束引入KKT條件(j=1,2,3,…,n):
{ μ j ≥ 0 g j ( x ) ≥ 0 μ j g j ( x ) = 0 \begin{cases} \mu_j \ge 0\\ g_j(x)\ge0\\ \mu_j g_j(x)=0 \end{cases} μj0gj(x)0μjgj(x)=0

支援向量機的拉格朗日函式

根據其優化問題:
m i n w , b 1 2 ∣ ∣ w ∣ ∣ 2 s . t t n ( w T x n + b ) ≥ 1 ∀ n = 1 , 2 , . . . N \begin{aligned} \underset{w,b}{\mathbf{min}}\frac12||w||^2\\ s.t \quad t_n(w^Tx_n+b)\ge1 &\quad \forall n = 1,2,...N \end{aligned} w,bmin21w2s.ttn(wTxn+b)1n=1,2,...N
對每條約束新增拉格朗日乘子 α 1 ≥ 0 \alpha_1 \ge 0 α10,則該問題的拉格朗日函式可寫為:
L ( w , b , α ) = 1 2 ∣ ∣ w ∣ ∣ 2 − ∑ n = 1 N α i ( t n ( w T x n + b ) − 1 ) L(w,b,\alpha) = \frac12||w||^2 - \sum_{n=1}^N\alpha_i(t_n(w^Tx_n+b)-1) L(w,b,α)=21w2n=1Nαi(tn(wTxn+b)1)

KKT條件為:
{ α n ≥ 0 t n ( w T x n + b ) − 1 ≥ 0 α n ( t n ( w T x n + b ) − 1 ) = 0 \begin{aligned} \begin{cases} \alpha_n \ge 0\\ t_n(w^Tx_n+b)-1\ge0\\ \alpha_n(t_n(w^Tx_n+b)-1)=0 \end{cases} \end{aligned} αn0tn(wTxn+b)10αn(tn(wTxn+b)1)=0

對偶形式求最優解

上面的拉格朗日函式分別對w和b求偏導可以得到
w = ∑ n = 1 N α n t n x n 0 = ∑ n = 1 N α n t n \begin{aligned} w &= \sum_{n = 1}^N\alpha_nt_nx_n\\ 0 &= \sum_{n=1}^N\alpha_nt_n \end{aligned} w0=n=1Nαntnxn=n=1Nαntn
將上式帶入到拉格朗日函式中消去w,b:
L p = 1 2 ∣ ∣ w ∣ ∣ 2 − ∑ n = 1 N α i t n w T x n − b ∑ n = 1 N α n t n + ∑ n = 1 N α n = 1 2 ∣ ∣ w ∣ ∣ 2 − ∑ n = 1 N α i t n w T x n + ∑ n = 1 N α n ( s i n c e : ∑ n = 1 N α n t n = 0 ) = 1 2 w T w − w T w + ∑ n = 1 N α n ( s i n c e : w = ∑ n = 1 N α n t n x n ) = ∑ n = 1 N α n − 1 2 w T w = ∑ n = 1 N α n − 1 2 ( ∑ n = 1 N α n t n x n ) T ( ∑ m = 1 N α m t m x m ) = ∑ n = 1 N α n − 1 2 ∑ n = 1 N ∑ m = 1 N α n α m t n t m ( x n T x m ) \begin{aligned} L_p &= \frac12||w||^2 - \sum_{n=1}^N\alpha_it_nw^Tx_n-\boxed {b\sum_{n=1}^N\alpha_nt_n}+\sum_{n=1}^N\alpha_n\\ &=\frac12||w||^2 - \boxed{\sum_{n=1}^N\alpha_it_nw^Tx_n}+\sum_{n=1}^N\alpha_n\quad &(since: \quad\sum_{n=1}^N\alpha_nt_n = 0)\\ &=\frac12w^Tw - w^Tw+\sum_{n=1}^N\alpha_n \quad &(since: w = \sum_{n = 1}^N\alpha_nt_nx_n)\\ & = \sum_{n=1}^N\alpha_n -\boxed{\frac12w^Tw}\\ & = \sum_{n=1}^N\alpha_n -\boxed{\frac12(\sum_{n=1}^N\alpha_nt_nx_n)^T(\sum_{m=1}^N\alpha_mt_mx_m)}\\ & = \sum_{n=1}^N\alpha_n -\frac12\sum_{n=1}^N\sum_{m=1}^N\alpha_n\alpha_mt_nt_m(\mathbf{x_n^Tx_m}) \end{aligned} Lp=21w2n=1NαitnwTxnbn=1Nαntn+n=1Nαn=21w2n=1NαitnwTxn+n=1Nαn=21wTwwTw+n=1Nαn=n=1Nαn21wTw=n=1Nαn21(n=1Nαntnxn)T(m=1Nαmtmxm)=n=1Nαn21n=1Nm=1Nαnαmtntm(xnTxm)(since:n=1Nαntn=0)(since:w=n=1Nαntnxn)
從而得到對偶問題:
m a x ∑ n = 1 N α n − 1 2 ∑ n = 1 N ∑ m = 1 N α n α m t n t m ( x n T x m ) s . t . ∑ n = 1 N α n t n = 0 α n ≥ 0 , ∀ n = 1 , 2 , . . . , N \begin{aligned} &\mathbb{max} \sum_{n=1}^N\alpha_n -\frac12\sum_{n=1}^N\sum_{m=1}^N\alpha_n\alpha_mt_nt_m(\mathbf{x_n^Tx_m})\\ s.t. \quad&\sum_{n=1}^N\alpha_nt_n = 0\\ &\alpha_n \ge 0, \forall n = 1,2,...,N \end{aligned} s.t.maxn=1Nαn21n=1Nm=1Nαnαmtntm(xnTxm)n=1Nαntn=0αn0,n=1,2,...,N
通過對這個凸優化問題求解可以得到最優解 α ∗ \alpha^* α, 理論上來說,使用 w = ∑ n = 1 N α n t n x n w = \sum_{n = 1}^N\alpha_nt_nx_n w=n=1Nαntnxn即可求得最優的權重,但是在實際計算過程中,由於精度的問題,在得到的support vectors的 α ∗ \alpha^* α值往往並不是0,而是接近於0的一個很小的值,這就可能會帶來誤差。

但我們知道SVM的超平面是隻由support vectors,因此我們可以根據最優的 α ∗ \alpha^* α中並不是趨近於0且大於0 的值,其index所對應的資料就是support vectors。然後通過相應的support vectors即可求得相應的最優權重w。
w = ∑ n = 1 N s v α n ∗ t n x n w = \sum_{n = 1}^{N_{sv}}\alpha_n^*t_nx_n w=n=1Nsvαntnxn
而且由上面圖二我們知道support vectors是恰好落在Margin邊緣的,那麼滿足 t n ( w T x n + b ) = 1 t_n(w^Tx_n+b) = 1 tn(wTxn+b)=1,根據此我們可以求得相應的b的值。也就是說只需要一個support vector我們就可以求得b的值。但是對於多個support vectors,我們這裡採用取平均的方式來求得b,更具有魯棒性。
b = 1 N s v ∑ n ∈ s v ( t n − w T x n ) b = \frac1{N_{sv}}\sum_{n\in sv}(t_n-w^Tx_n) b=Nsv1nsv(tnwTxn)
到此SVM對於線性可分的資料集的分類就結束了。但是現實生活當中,絕大部分的資料集並不是線性可分的,對此SVM引入鬆弛變數來解決這個問題。

鬆弛變數

如下圖所示,當前資料是線性不可分的,也就是沒辦法找到一個超平面,使得恰好兩個類別資料分開。

圖4

我們為每一個訓練資料 x n x_n xn設定了一個鬆弛變數 ξ n ≥ 0 \xi_n\ge0 ξn0,其取值分為以下兩種情況:

  1. 對於資料點落在了Margin正確的一側,令 ξ n = 0 \xi_n = 0 ξn=0
  2. 對於其他的資料點,我們令 ξ = ∣ t n − ( w T x n + b ) ∣ \xi = |t_n-(w^Tx_n+b)| ξ=tn(wTxn+b)

也就是說對於落在超平面(決策邊界)上的點有 ξ n = 1 \xi_n = 1 ξn=1;對於錯誤分類的點有 ξ n > 1 \xi_n > 1 ξn>1;對於正確分類且落在Margin裡的點有 0 < ξ n < 1 0<\xi_n < 1 0<ξn<1;對於正確分類且落在Margin外的點有 ξ n = 0 \xi_n = 0 ξn=0

這樣SVM的優化問題就發生了些許改變:
對 於 線 性 可 分 的 數 據 : m i n 1 2 ∣ ∣ w ∣ ∣ 2 對 於 線 性 不 可 分 數 據 : m i n 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ n = 1 N ξ n \begin{aligned} &對於線性可分的資料:\mathbb{min}\frac12 ||w||^2\\ &對於線性\textbf不可分資料:\mathbb{min}\frac12 ||w||^2+C\sum_{n=1}^N\xi_n \end{aligned} min21w2min21w2+Cn=1Nξn
其中C為超引數,是人為設定的懲罰因子。然後完整的優化問題為:
m i n 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ n = 1 N ξ n s . t t n ( w T x n + b ) ≥ 1 − ξ n ∀ n = 1 , 2 , . . . N ξ n ≥ 0 ∀ n = 1 , 2 , . . . N \begin{aligned} &\mathbb{min}\frac12 ||w||^2+C\sum_{n=1}^N\xi_n\\ s.t \quad &t_n(w^Tx_n+b)\ge 1 - \xi_n\quad &\forall n = 1,2,...N\\ &\xi_n \ge 0\quad &\forall n = 1,2,...N \end{aligned} s.tmin21w2+Cn=1Nξntn(wTxn+b)1ξnξn0n=1,2,...Nn=1,2,...N
那麼根據前面拉格朗日乘子法多約束推廣可以得到新的拉格朗日優化函式:
L p = 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ n = 1 N ξ n − ∑ n = 1 N α i ( t n ( w T x n + b ) − 1 + ξ n ) − ∑ n = 1 N μ n ξ n L_p = \frac12 ||w||^2+C\sum_{n=1}^N\xi_n -\sum_{n=1}^N\alpha_i(t_n(w^Tx_n+b)-1+\xi_n) - \sum_{n=1}^N\mu_n\xi_n Lp=21w2+Cn=1Nξnn=1Nαi(tn(wTxn+b)1+ξn)n=1Nμnξn
新的KKT條件也就是:
{ α n ≥ 0 t n ( w T x n + b ) − 1 + ξ n ≥ 0 α n ( t n ( w T x n + b ) − 1 + ξ n ) = 0 μ n ≥ 0 ξ n ≥ 0 μ n ξ n = 0 \begin{aligned} \begin{cases} \alpha_n \ge 0\\ t_n(w^Tx_n+b)-1+\xi_n\ge0\\ \alpha_n(t_n(w^Tx_n+b)-1+\xi_n)=0\\ \mu_n\ge0\\ \xi_n\ge 0 \\ \mu_n\xi_n=0 \end{cases} \end{aligned} αn0tn(wTxn+b)1+ξn0αn(tn(wTxn+b)1+ξn)=0μn0ξn0μnξn=0
那麼對w,b和 ξ n \xi_n ξn求偏導可得:
w = ∑ n = 1 N α n t n x n 0 = ∑ n = 1 N α n t n C = α n + μ n , n = 1 , 2... , N \begin{aligned} w &= \sum_{n = 1}^N\alpha_nt_nx_n\\ 0 &= \sum_{n=1}^N\alpha_nt_n\\ C &= \alpha_n+\mu_n,\quad n = 1,2...,N \end{aligned} w0C=n=1Nαntnxn=n=1Nαntn=αn+μn,n=1,2...,N
可以發現對w和b求偏導的結果和前面是一樣的,那麼類似的我們可以將上面拉格朗日函式用 α , μ \alpha,\mu α,μ進行改寫:
L p = 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ n = 1 N ξ n − ∑ n = 1 N α i ( t n ( w T x n + b ) − 1 + ξ n ) − ∑ n = 1 N μ n ξ n = ∑ n = 1 N α n − 1 2 ∑ n = 1 N ∑ m = 1 N α n α m t n t m ( x n T x m ) + C ∑ n = 1 N ξ n − ∑ n = 1 N α n ξ n − ∑ n = 1 N μ n ξ n s i n c e : C = α n + μ n ,   n = 1 , 2... , N ⇒ C ∑ n = 1 N ξ n − ∑ n = 1 N α n ξ n − ∑ n = 1 N μ n ξ n = 0 L p = ∑ n = 1 N α n − 1 2 ∑ n = 1 N ∑ m = 1 N α n α m t n t m ( x n T x m ) \begin{aligned} L_p &= \frac12 ||w||^2+C\sum_{n=1}^N\xi_n -\sum_{n=1}^N\alpha_i(t_n(w^Tx_n+b)-1+\xi_n) - \sum_{n=1}^N\mu_n\xi_n\\ & = \sum_{n=1}^N\alpha_n -\frac12\sum_{n=1}^N\sum_{m=1}^N\alpha_n\alpha_mt_nt_m(\mathbf{x_n^Tx_m})+\boxed{C\sum_{n=1}^N\xi_n-\sum_{n=1}^N\alpha_n\xi_n-\sum_{n=1}^N\mu_n\xi_n}\\ since: C &= \alpha_n+\mu_n,\ n = 1,2...,N \quad \Rightarrow \quad C\sum_{n=1}^N\xi_n-\sum_{n=1}^N\alpha_n\xi_n-\sum_{n=1}^N\mu_n\xi_n = 0\\ L_p &= \sum_{n=1}^N\alpha_n -\frac12\sum_{n=1}^N\sum_{m=1}^N\alpha_n\alpha_mt_nt_m(\mathbf{x_n^Tx_m}) \end{aligned} Lpsince:CLp=21w2+Cn=1Nξnn=1Nαi(tn(wTxn+b)1+ξn)n=1Nμnξn=n=1Nαn21n=1Nm=1Nαnαmtntm(xnTxm)+Cn=1Nξnn=1Nαnξnn=1Nμnξn=αn+μn, n=1,2...,NCn=1Nξnn=1Nαnξnn=1Nμnξn=0=n=1Nαn21n=1Nm=1Nαnαmtntm(xnTxm)
我們發現結果是和上面一樣的,那麼對偶問題中優化的目標也是一樣的,只是約束變了:
m a x ∑ n = 1 N α n − 1 2 ∑ n = 1 N ∑ m = 1 N α n α m t n t m ( x n T x m ) s . t . ∑ n = 1 N α n t n = 0 0 ≤ α n ≤ C , ∀ n = 1 , 2 , . . . , N \begin{aligned} &\mathbb{max} \sum_{n=1}^N\alpha_n -\frac12\sum_{n=1}^N\sum_{m=1}^N\alpha_n\alpha_mt_nt_m(\mathbf{x_n^Tx_m})\\ s.t. \quad&\sum_{n=1}^N\alpha_nt_n = 0\\ &\boxed{0\le\alpha_n \le C, \forall n = 1,2,...,N} \end{aligned} s.t.maxn=1Nαn21n=1Nm=1Nαnαmtntm(xnTxm)n=1Nαntn=00αnC,n=1,2,...,N

超引數懲罰因子C

其實從上面最後的約束我們可以明顯發現,如果C取很大以至於無窮的話那麼就跟前面線性可分的情況一樣了,也就越不允許出現在Margin的資料點,換句話說就是對於不符合規矩的資料點的懲罰很大。相反C取得小,根據最優時滿足 C = α n + μ n , n = 1 , 2... , N C = \alpha_n+\mu_n,\quad n = 1,2...,N C=αn+μn,n=1,2...,N,就允許很多 μ \mu μ的值為0,對應的鬆弛變數值就不為0,那麼就允許部分資料點落在Margin內部甚至於錯誤分類且在Margin外。

我們可以看一下以下幾個例子來更好地理解C值的選取對分類的影響

  • 訓練資料明顯是線性可分的情況:
    在這裡插入圖片描述

  • 訓練資料還是線性可分的,但比較勉強:
    在這裡插入圖片描述

  • 訓練資料線性不可分:
    在這裡插入圖片描述

從上面三個例子我們可以看出,C值的選取取決於訓練集線性可分的程度,如果訓練集線性可分,那麼C值要取得大,如果訓練集線性不可分且複雜,那麼C值就要取小一點。因此在實際生活中,選取合適的C值直接影響了分類器的泛化能力,就需要通過視覺化等多種方法來分析資料從而選擇更合適的C值。當然一般來說比較難分析,還是通過不斷地測試C的值來確定最優。

好了,SVM的基本原理到此就結束了,我們可以嘗試去用程式碼實現一個簡單的SVM分類器了。

Python實現

對於SVM中的對偶問題,我這裡使用了cvxopt包來找到最優的 α ∗ \alpha* α. cvxopt是一個免費的軟體包,用於基於Python程式語言的凸優化。

以下為簡單的線性SVM分類器的python程式碼:

def svmlin(X, t, C):
    """
    INPUT:
    X        : the dataset                   (num_samples x dim)
    t        : labeling                      (num_samples x 1)
    C        : 懲罰因子                       (scalar)

    OUTPUT:
    alpha    : 拉格朗日乘子                    (num_samples x 1)
    sv       : supports vectors的布林向量      (1 x num_samples)
    w        : 分類器的權重                    (1 x dim)
    b        : 線性SVM的偏移值                 (scalar)
    result   : 分類結果                       (1 x num_samples)
    slack    : 位於Margin中的資料點,布林向量。  (1 x num_samples)
    """

    N = X.shape[0]

    # 計算拉格朗日對偶形式的中的t_nt_m(x_n^Tx_m)
    # H(i,j) = t_i * t_j * dot_product(x_i, x_j)
    # 這裡先求tn*x_n的矩陣,之後點乘自己就是我們所需要的
    y = t.reshape(-1, 1)
    X_dash = y * X
    H = np.dot(X_dash, X_dash.T)

    # cvxopt.solvers 尋找的是最優的alpha使得等式值最小化, 因此我們要對f取負
    # 以使得cvxopt.solvers找的是最大化等式的alpha:
    #       max 1'*x - 0.5*x'*H*x    subject to:  A*x <= b
    #        x
    #   <=>
    #       min -1'*x + 0.5*x'*H*x    subject to:  A*x <= b
    #        x
    f = (-1) * np.ones(N)

    # G,h是對alpha值的約束,每一個拉格朗日乘子的上下限: 0 <= alpha_n <= C
    # 這裡分為兩部分:0 <= alpha_n,alpha_n <= C
    # 實際操作時,是 -I x <= 0;I x <=C, I為對角線矩陣
    # 因此G的結構是上面為負Identity,下面為正Identity
    G = np.vstack([-np.eye(N), np.eye(N)])
    LB = np.zeros(N)
    UB = C * np.ones(N)
    h = np.hstack([-LB, UB])

    # 構造約束條件: sum(t_n * alpha_n) = 0 => Ax = b
    A = t.reshape((1, N)).astype(np.double)
    b = np.double(0)

    sol = cvxopt.solvers.qp(P=cvxopt.matrix(H), q=cvxopt.matrix(f), G=cvxopt.matrix(G), h=cvxopt.matrix(h),
                            A=cvxopt.matrix(A), b=cvxopt.matrix(b))
    #獲取最優的alpha值
    alpha = np.array(sol['x']).reshape((-1,))


    # 查詢support vectors, 前面原理提到過,雖然理論上非support vectors的對應的alpha
    # 應該值為0,但是由於浮點數的精度問題,alpha並不會為0,只是趨近於0
    # 所以這裡設了一個閾值1e-6,預設小於這個數的都是應該值為0的
    sv = np.where(alpha > 1e-6, True, False)
    if ~sv.any():
        # 如果沒有發現任何support vectors
        raise ValueError('No support vectors found.')
    else:
        # 由KKT條件,在鬆弛變數不為0時候,u_n = 0. 且最優時候: alpha_n = C - u_n
        # 所以尋找相應的index,對應的alpha值趨近於C即可(理論上alpha == C)
        slack = np.where(alpha > C - 1e-6, True, False)

        # 計算權重
        w = (alpha[sv] * t[sv]).dot(X[sv])

        # 計算bias,也就是b的值
        b = np.mean(t[sv] - w.dot(X[sv].T))

        # 獲取最後結果
        result = X.dot(w) + b
        result[result >= 0] = 1
        result[result < 0] = -1

    return alpha, sv, w, b, result, slack

總結

本文主要是對線性SVM分類器的原理進行分析,著重於對優化問題以及尋找超平面的原理進行解析,在基本的SVM的思想方面沒有多做解釋,如果對那一部分有疑問可以直接參考下面參考資料第二條。希望大家讀完本文後能對SVM有更深的理解。

另外對於非線性SVM分類器以及核方法,本人之後會補上,寫不動了,要躺一會。

請大家多多點贊收藏轉發支援,寫這玩意很費勁的,公式純手打的-_-

參考文獻

相關文章