機(jī)器學(xué)習(xí)算法原理筆記(一)—— SVM支持向量機(jī)


一、SVM簡(jiǎn)述

SVM支持向量機(jī)(英文全稱:support vector machine)是一個(gè)分類算法, 通過找到一個(gè)分類平面, 將數(shù)據(jù)分隔在平面兩側(cè), 從而達(dá)到分類的目的。

其實(shí)SVM同其他機(jī)器學(xué)習(xí)算法一樣,直觀解釋并不難理解。簡(jiǎn)單來說,SVM就是間隔最大化分類。如下圖所示,其實(shí)能正確對(duì)正負(fù)樣本進(jìn)行分類的分隔線其實(shí)是很多的,通常的分類算法只是找到了其中一條線對(duì)樣本進(jìn)行分類:

考慮到這種情況,我們很自然可以想到那么我們可不可以找到一條最優(yōu)的線來分隔樣本呢?這就是SVM考慮的問題。


二、超平面

我們現(xiàn)在要考慮最優(yōu)的線來對(duì)我們的樣本進(jìn)行分類,但線這個(gè)概念其實(shí)是二維的,當(dāng)我們的數(shù)據(jù)是三維時(shí),這就變成了面。但如果我們的樣本不止二維(這種情況很常見,很少有數(shù)據(jù)集只有這么少的特征),那么此時(shí)就需要提出超平面的概念。

我們對(duì)“平面”概念的理解,一般是定義在三維空間中的:

A、B和C與x、y和z的關(guān)系其實(shí)可以用向量的形式來表示:

這個(gè)平面由兩個(gè)性質(zhì)定義:

  • 方程是線性的,是由空間點(diǎn)的各分量的線性組合
  • 方程數(shù)量是1。這個(gè)平面是建立在“三維”上的。

如果我們撇開“維度”這個(gè)限制,那么就有了超平面的定義。實(shí)際上,超平面是純粹的數(shù)學(xué)概念,不是物理概念,它是平面中的直線、空間中的平面的推廣,只有當(dāng)維度大于3,才稱為“超”平面。

百度百科上對(duì)超平面的數(shù)學(xué)定義是這樣的:超平面H是從n維空間到n-1維空間的一個(gè)映射子空間,它有一個(gè)n維向量和一個(gè)實(shí)數(shù)定義。簡(jiǎn)單來說就是二維空間里的超平面為一條直線. 一維空間里超平面為數(shù)軸上的一個(gè)點(diǎn)。

定義完超平面,我們接下來就要考慮距離的問題,我們高中就學(xué)過三維空間中點(diǎn)到面的距離公式為:

換成向量的表示形式就是:

那么可以想象,超平面上點(diǎn)到超平面的距離用公式表示也不外乎就是A、B、C之類的參數(shù)個(gè)數(shù)變多而已,所以完全可以用上式來表示超平面上點(diǎn)到超平面的距離。


三、間隔最大化

解決了距離的表示方法,我們就可以回到我們?cè)瓉淼膯栴}上來,我們想要找到一個(gè)超平面最大程度地分隔數(shù)據(jù)。考慮到我們對(duì)每個(gè)點(diǎn)都求到超平面的距離然后再對(duì)這個(gè)問題進(jìn)行優(yōu)化顯然是不可行的,那么我們可以將問題轉(zhuǎn)化為距離超平面最近的樣本到超平面的距離最大,也就是說我們先對(duì)下面的式子求一個(gè)使得該式子最小的i,然后再對(duì)其求使得該式子最大的wb

但是這樣的問題顯然還是難以處理,為了能在現(xiàn)實(shí)中應(yīng)用,我們希望能對(duì)其做一些簡(jiǎn)化, 使其變得便于求解的優(yōu)化問題。

觀察距離公式我們可以發(fā)現(xiàn)wb同乘一個(gè)數(shù)r變成 rwrb ,對(duì)上面這個(gè)距離也是沒什么影響的,那么我們干脆找一個(gè)wb使得上面需要變化為1,也就是我們強(qiáng)制使得下面這個(gè)式子成立:

另外,考慮到最大化\frac{1}{∥w∥}其實(shí)也就是最小化∥w∥^2,然后為了求導(dǎo)相消的方便,前面補(bǔ)一個(gè)1/2,這樣我們的問題就變成了下面這個(gè)形式:

這種帶最小值的約束條件我們是不喜歡的,能不能換個(gè)形式呢?比如:

我們用反證法可以證明:

假設(shè)我們現(xiàn)在已經(jīng)求解得滿足y_i(w^?x_i + b) \geq 1且使得\frac{1}{2} w^Tw最小的最優(yōu)值 (w^*, b^{*}),這個(gè)最優(yōu)值 (w^*, b^{*})在等號(hào)不成立,即 y_i(w^?x_i + b) > 1,那么此時(shí)應(yīng)該存在一個(gè)(rw^*, rb^*)使得y_i(w^?x_i + b) = 1成立。因?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=y_i(w%5E%E2%8A%A4x_i%20%2B%20b)%20%3E%201" alt="y_i(w^?x_i + b) > 1" mathimg="1">,所以可以想象r應(yīng)該滿足0 < r < 1的條件。但這樣的話,∥rw^*∥^2 < ∥w^*∥^2,這顯然與假設(shè)是不符合的,所以,我們的問題可以等價(jià)為:

對(duì)于這個(gè)帶約束條件的問題,我們最直接的想到的方法應(yīng)該就是高中學(xué)過的構(gòu)造拉格朗日函數(shù)的方法,所以,先用一個(gè)小節(jié)敘述下構(gòu)造拉格朗日函數(shù)。


四、拉格朗日函數(shù)和對(duì)偶問題

轉(zhuǎn)化成拉格朗日函數(shù)之后,我們自然知道我們要對(duì)f({{u}^{*}})取最小值,那么\alpha , \beta應(yīng)該怎么辦呢?我們進(jìn)行如下操作:

我們對(duì)原問題可以這么理解,我們一定要使得約束條件成立,也就是我們求得的u絕對(duì)會(huì)滿足約束條件。那么怎么保證這一點(diǎn)呢?那就是一旦u不滿足約束條件,那么其就應(yīng)該導(dǎo)致這個(gè)u不可能會(huì)被 \underset{u}{\mathop{\min }}\,f(u )選中,轉(zhuǎn)化成如拉格朗日函數(shù)一樣的形式的話就變成如下表示:

如果我們將 \sum\limits_{i}{{{\alpha }_{i}}{{g}_{i}}({{x}^{*}})}+\sum\limits_{i}{{{\beta }_{i}}{{h}_{i}}({{x}^{*}})} 看成是懲罰的話,那么原問題的懲罰就是一旦不符合約束條件,懲罰就是∞。但這樣的表達(dá)在數(shù)學(xué)上不美觀,那應(yīng)該怎么表示呢?
我們觀察g,當(dāng)不符合g的條件時(shí),{{g}_{i}}({{x}}) > 0,當(dāng)符合的時(shí)候,{{g}_{i}}({{x}}) =< 0。那么我們不就可以用\underset{\alpha }{\mathop{\max }}\,L(u,\alpha ,\beta )來表示嗎?當(dāng)不符合g的條件,{{g}_{i}}({{x}}) > 0時(shí),只要取\alpha為∞,就能使得L(u,\alpha ,\beta )取到最大值,也就是∞,同理也可以得到當(dāng)符合的時(shí)候時(shí),只要取\alpha為0,就能使得L(u,\alpha ,\beta )取到最大值0。所以我們得到了原問題的等價(jià)形式:

那么問題又來了,這個(gè)等價(jià)問題并不好解。所以,我們提出了一個(gè)對(duì)偶問題:

其實(shí)對(duì)偶問題從原問題出發(fā)非常好理解,我們先拋棄掉我們得到的原問題的等價(jià)形式,回到原問題。

我們將原問題轉(zhuǎn)化為拉格朗日函數(shù)后,必然第一反應(yīng)是對(duì)其求最小值:

\begin{align*}\underset{u}{\mathop{\min }}\,L(u,\alpha ,\beta )\\\end{align*}

那么\alpha , \beta怎么辦呢?

假設(shè)我們現(xiàn)在有一個(gè)最優(yōu)的u^*滿足約束條件并且使得f(u)最小,我們將其帶入上式就會(huì)發(fā)現(xiàn)我們并不能保證u是最優(yōu)時(shí),\sum\limits_{i}{{{\alpha }_{i}}{{g}_{i}}({{u}^{*}})}為0,由于\alpha >= 0,又因?yàn)楫?dāng)u^*滿足約束條件{{g}_{i}}({{u}^{*}}) <= 0,所以我們最多只能保證下面這個(gè)不等式:

\begin{align*}f({{u}^{*}})+\sum\limits_{i}{{{\alpha }_{i}}{{g}_{i}}({{u}^{*}})}+\sum\limits_{i}{{{\beta }_{i}}{{h}_{i}}({{u}^{*}})} \le f({{u}^{*}}) ={{p}^{*}} \\\end{align*}

那么怎么使得它和原問題盡可能地接近,最明顯的方式就是對(duì)其\underset{\alpha}{\mathop{\max }}\,L(u,\alpha ,\beta ),當(dāng)然同上面懲罰的道理,也需要對(duì)\beta也進(jìn)行相同的操作,這樣就得到了所謂的原問題的對(duì)偶問題:

既然是求最大值,那么最大的問題就是這個(gè)等號(hào)是不是能成立。

  1. Slater條件

存在一個(gè)最優(yōu)解u^* ,使得不等式約束{{g}_{i}}({{u}^{*}})≤0嚴(yán)格成立,即{{g}_{i}}({{u}^{*}}) != 0。
當(dāng)原問題為一凸優(yōu)化問題,且滿足Slater條件時(shí),有d* = p*,這樣就原問題和對(duì)偶問題的解一致,求解對(duì)偶問題即可。顯然,Slater是凸優(yōu)化問題與其對(duì)偶問題等價(jià)的一個(gè)充分條件。

  1. KTT條件

考慮一般優(yōu)化問題(不一定是凸優(yōu)化),如果有d* = p*,則:

\begin{align*}\underset{u}{\mathop{\min }}\,L(u,{{\alpha }^{*}},{{\beta }^{*}}) \le L({{u}^{*}},{{\alpha }^{*}},{{\beta }^{*}}) =f({{u}^{*}})+\sum\limits_{i}{{{\alpha }_{i}}^{*}{{g}_{i}}({{u}^{*}})}+\sum\limits_{i}{{{\beta }_{i}}^{*}{{h}_{i}}({{u}^{*}})} \ \le f({{u}^{*}}) ={{p}^{*}} \\\end{align*}

由于d* = p*,所以上面推導(dǎo)過程中所以的不等號(hào)“≤ ”應(yīng)該取到等號(hào)。第一個(gè)等號(hào)得到\underset{u}{\mathop{\min }}\,L(u,{{\alpha }^{*}},{{\beta }^{*}}) \le L({{u}^{*}},{{\alpha }^{*}},{{\beta }^{*}}),這說明u^*\underset{u}{\mathop{\min }}\,L(u,{{\alpha }^{*}},{{\beta }^{*}}) 的一個(gè)極值點(diǎn),所以\underset{u}{\mathop{\min }}\,L(u,{{\alpha }^{*}},{{\beta }^{*}})u* 處的偏導(dǎo)為零,\frac{\partial L(x,{{\alpha }^{*}},{{\beta }^{*}})}{\partial x}{{|}_{{{x}^{*}}}}=0

另外在f({{u}^{*}})+\sum\limits_{i}{{{\alpha }_{i}}^{*}{{g}_{i}}({{u}^{*}})}+\sum\limits_{i}{{{\beta }_{i}}^{*}{{h}_{i}}({{u}^{*}})} \le f({{u}^{*}})取得等號(hào) ,除去本來就應(yīng)該為0的項(xiàng)之外,現(xiàn)在還需要\sum\limits_{i}{{{\alpha }_{i}}^{*}{{g}_{i}}({{u}^{*}})}等于0

綜合以上兩點(diǎn),在加上原來的約束,可以得到KKT條件:

\left\{ \begin{matrix}\frac{\partial L(u,{{\alpha }^{*}},{{\beta }^{*}})}{\partial u}{{|}_{{{u}^{*}}}}=0 \\\sum\limits_{i}{{{\alpha }_{i}}^{*}{{g}_{i}}({{u}^{*}})}=0 \\{{\alpha }_{i}}^{*}\ge 0 \\\begin{matrix}{{g}_{i}}({{u}^{*}})\le 0 \\{{h}_{i}}({{u}^{*}})=0 \\\end{matrix} \\\end{matrix} \right.

盡管KKT條件是d* = p*的必要條件,但當(dāng)原問題是凸優(yōu)化問題時(shí),它就升級(jí)為充要條件,也就是只要找到u^*,α^*,β^*滿足以上五個(gè)條件,那么原問題就和對(duì)偶問題就有相同的解,分別在u^?(α^?,β^?)處取得。

注:另外,根據(jù)KKT條件中的\sum\limits_{i}{{{\alpha }_{i}}^{*}{{g}_{i}}({{u}^{*}})}=0可以得到,{{g}_{i}}({{u}^{*}})<0 ? {{\alpha }_{i}}^{*}=0,反過來說,只有{{g}_{i}}({{u}^{*}})=0{{\alpha }_{i}}^{*}才有可能不為0,這是之后SVM中會(huì)用到的一個(gè)重要性質(zhì)。


五、間隔最大化后續(xù)

我們將線性支持向量機(jī)的拉格朗日函數(shù)寫出:

其對(duì)偶問題為:

我們對(duì)于這個(gè)對(duì)偶問題的求解可以分成兩部分:

  1. 固定α,令拉格朗日函數(shù)分別對(duì)(w, b)求偏導(dǎo)數(shù)并令其等于零:

將結(jié)果帶入原式子:

回帶后的結(jié)果:

  1. 求對(duì)α的極大

改變一下符號(hào),使得其變?yōu)榍笞钚〉膯栴}

那么α怎么求解呢?最笨的方法當(dāng)然是一一帶入去試求,未引入軟間隔時(shí),α使用這種方法還是好求的,但加入軟間隔后,α的限制范圍變多了,就只能尋求更高效的方法,例如SMO算法

假設(shè)我們已經(jīng)得到最優(yōu)的α^*,那么根據(jù)KKT條件可得:

KKT條件

所以我們可以推出:

由第三行KKT 條件還可以得到:

所以支持向量機(jī)的參數(shù) (w, b) 僅由支持向量決定, 與其他樣本無關(guān)(最理想的情況當(dāng)然是我們完美地得到了所有的支持向量,然后得到下面的式子):

其中 SV 代表所有支持向量的集合

b同樣可以由上述條件得出:

線性支持向量機(jī)的假設(shè)函數(shù)可表示為:


六、序列最小最優(yōu)化算法SMO

SMO算法是一種啟發(fā)式算法,其基本思路是:如果所有的變量的解都滿足此最優(yōu)問題的KKT條件,那么這個(gè)優(yōu)化問題的解就能得到。也就是說由于KKT條件是該優(yōu)化問題的充分必要條件,所以只有當(dāng)所有的a都滿足KKT條件時(shí),這些a就是該優(yōu)化問題的解。

但是a的數(shù)量眾多,并且還需要滿足如下等式:

所以,對(duì)所有的a直接進(jìn)行調(diào)整使其符合KKT條件顯然是一件相當(dāng)困難的事情。

就該問題,SMO 選擇每步同時(shí)選擇兩個(gè)變量 α_iα_j 進(jìn)行優(yōu)化,,并固定其他參數(shù),以保證不違背約束。

也就是說我們通過如下方法同時(shí)更新a_ia_j

此時(shí)我們每步的優(yōu)化目標(biāo)為(就是把原來的式子中和a_ia_j無關(guān)的去掉了):

注:這里\Phi(x)是加了映射函數(shù)的意思,去掉不影響,注意這里的c和下面的C不同,下面的C指的是這里的\xi之和前面的超參數(shù),表示對(duì)誤分類的懲罰程度。\xi是松弛因子的意思,具體的推導(dǎo)可以參考:松弛因子

在不考慮其他的約束條件的情況下,我們可以通過用a_j來表示a_i的方式使得本來有兩個(gè)變量的函數(shù)變成只有一個(gè),這個(gè)時(shí)候其實(shí)就可以求偏導(dǎo)并令其為 0得到更新值。

注意:下面推導(dǎo)中中1,2和我們這里的i,j是對(duì)應(yīng)的,僅僅是假設(shè)i,j為1,2而已,K是核函數(shù)的意思,去掉不影響。

詳細(xì)的推導(dǎo)可以參考:

  1. 知乎SMO
  2. CSDN

結(jié)果為:

接著我們就要考慮其他的約束條件:
把SMO中對(duì)于同時(shí)更新α_iα_j過程看成線性規(guī)劃來理解來理解的話,那么下圖所表達(dá)的便是約束條件:`

根據(jù)y_iy_j同號(hào)或異號(hào),可得出α的上下界分別為:

根據(jù)這里得到的上下界對(duì)上面最近求偏導(dǎo)所得到的α進(jìn)行剪裁。

最后可以通過其求另一個(gè)α的值:

到這里為止,其實(shí)SMO算法已經(jīng)可以基本可以結(jié)束了。但是還有一個(gè)關(guān)鍵性的問題要解決,那就是α_iα_j的選取。

理論上講, 每步優(yōu)化時(shí) α_iα_j 可以任意選擇, 但實(shí)踐中通常取 α_i 為違背 KKT 條件最大的α, 而 α_i 取對(duì)應(yīng)樣本與 α_j 對(duì)應(yīng)樣本之間間隔最大的變量,也就是選擇使| E1 - E2 | 最大的α_j 。 具體操作可以參考:SMO變量選取

SMO的主要步驟如下:
  1. 第一步選取一對(duì)α_iα_j ,選取方法使用啟發(fā)式方法
    先“掃描”所有乘子,把第一個(gè)違反KKT條件的作為更新對(duì)象,令為α_i (還有其他一些啟發(fā)式的方法)。在所有不違反KKT條件的α中,選擇使| E_1 - E_2 |最大的α_j進(jìn)行更新,使得能最大限度增大目標(biāo)函數(shù)的值

  2. 固定除α_iα_j的其他參數(shù),用α_j表示α_i,進(jìn)行更新迭代

最后,每次更新完兩個(gè)乘子的優(yōu)化后,都需要再重新計(jì)算b,及對(duì)應(yīng)的E_i值。


七、機(jī)器學(xué)習(xí)實(shí)戰(zhàn)中的python實(shí)現(xiàn)

#coding=utf-8

import numpy as np

#數(shù)據(jù)讀取
def loadDataSet(fileName):
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr = line.strip().split('\t')
        dataMat.append([float(lineArr[0]), float(lineArr[1])])
        labelMat.append(float(lineArr[2]))
    return dataMat,labelMat



#該過程即為已經(jīng)確定了一個(gè)alphas,在剩下的中選取另一個(gè)alphas構(gòu)成SMO算法中選擇兩個(gè)來優(yōu)化的過程
#:已經(jīng)選擇的alphas的下標(biāo);全部alphas的數(shù)碼(要-1,畢竟下標(biāo)從0算起)
#r:選擇的下標(biāo)
def selectJrand(i,m):
    j=i
    while (j==i):
        j = int(np.random.uniform(0,m))
    return j



#剪輯aj,即使得得到的aj在[L,H]的范圍內(nèi);具體方法參考統(tǒng)計(jì)學(xué)習(xí)方法127頁7.108
#:需要剪輯的a;上限H;下限L
#r:剪輯后的aj
def clipAlpha(aj,H,L):
    if aj > H:
        aj = H
    if L > aj:
        aj = L
    return aj



#使用SMO算法進(jìn)行SVM
#:數(shù)據(jù)列表;標(biāo)簽列表;權(quán)衡因子(增加松弛因子而在目標(biāo)優(yōu)化函數(shù)中引入了懲罰項(xiàng));容錯(cuò)率;最大迭代次數(shù)
#r:返回最后的b值和alpha向量
def smoSimple(dataMatIn, classLabels, C, toler, maxIter):
    dataMatrix = np.mat(dataMatIn)
    labelMat = np.mat(classLabels).transpose()

    b = 0
    m,n = np.shape(dataMatrix)
    alphas = np.mat(np.zeros((m,1)))
    iter = 0

    while (iter < maxIter):
        alphaPairsChanged = 0

        for i in range(m):
            #計(jì)算預(yù)測(cè)值,利用的公式是alphas*y*(x*x)+b,可參考李航統(tǒng)計(jì)學(xué)方法中的7.56
            fXi = float(np.multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[i,:].T)) + b
            #計(jì)算出預(yù)測(cè)值與實(shí)際值之間的誤差
            Ei = fXi - float(labelMat[i])

            #如果不滿足KKT條件,即labelMat[i]*fXi<1(labelMat[i]*fXi-1<-toler)
            #and alpha<C 或者labelMat[i]*fXi>1(labelMat[i]*fXi-1>toler)and alpha>0
            #那么就對(duì)其進(jìn)行優(yōu)化
            if ((labelMat[i]*Ei < -toler) and (alphas[i] < C)) \
                 or ((labelMat[i]*Ei > toler) and (alphas[i] > 0)):
                #以下過程即挑選另一個(gè)alphasj并計(jì)算相應(yīng)需要的參數(shù)
                j = selectJrand(i,m)
                fXj = float(np.multiply(alphas,labelMat).T*(dataMatrix*dataMatrix[j,:].T)) + b
                Ej = fXj - float(labelMat[j])

                alphaIold = alphas[i].copy()
                alphaJold = alphas[j].copy()
                #這里的理解可參考統(tǒng)計(jì)學(xué)習(xí)方法第126頁,也就是求出alphas的上下界
                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])

                if L==H: print "L==H"; continue  #如果上下界沒有變化,就表示不需要更新
                # 根據(jù)公式計(jì)算未經(jīng)剪輯的alphaj
                eta = 2.0 * dataMatrix[i,:]*dataMatrix[j,:].T \
                          - dataMatrix[i,:]*dataMatrix[i,:].T \
                          - dataMatrix[j,:]*dataMatrix[j,:].T

                if eta >= 0: print "eta>=0"; continue  #如果eta>=0,跳出本次循環(huán)

                #該公式可參考統(tǒng)計(jì)學(xué)習(xí)方法127頁7.106
                alphas[j] -= labelMat[j]*(Ei - Ej)/eta
                #剪輯alphas
                alphas[j] = clipAlpha(alphas[j],H,L)
                # 如果改變后的alphaj值變化不大,跳出本次循環(huán)
                if (abs(alphas[j] - alphaJold) < 0.00001): print "j not moving enough"; continue
                # 否則,計(jì)算相應(yīng)的alphai值
                alphas[i] += labelMat[j]*labelMat[i]*(alphaJold - alphas[j])#update i by the same amount as j
                # 再分別計(jì)算兩個(gè)alpha情況下對(duì)于的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
                # 如果0<alphai<C,那么b=b1
                if (0 < alphas[i]) and (C > alphas[i]): b = b1
                # 否則如果0<alphai<C,那么b=b1
                elif (0 < alphas[j]) and (C > alphas[j]): b = b2
                # 否則,alphai,alphaj=0或C
                else: b = (b1 + b2)/2.0
                # 如果走到此步,表面改變了一對(duì)alpha值
                alphaPairsChanged += 1
                print "iter: %d i:%d, pairs changed %d" % (iter,i,alphaPairsChanged)
        # 最后判斷是否有改變的alpha對(duì),沒有就進(jìn)行下一次迭代
        if (alphaPairsChanged == 0): iter += 1
        else: iter = 0
        print "iteration number: %d" % iter

    # 返回最后的b值和alpha向量
    return b,alphas

數(shù)據(jù)可從此處下載:鏈接:https://pan.baidu.com/s/1BIuZxz16UPiMWfHYX_lknQ 密碼:90al


八、sklearn實(shí)現(xiàn)

sklearn中一共有SVC, NuSVCLinearSVC 三種實(shí)現(xiàn),它們都能在數(shù)據(jù)集中實(shí)現(xiàn)多元分類。

SVCNuSVC 是相似的方法, 但是接受稍許不同的參數(shù)設(shè)置并且有不同的數(shù)學(xué)方程(在這部分看 數(shù)學(xué)公式). 另一方面, LinearSVC 是另一個(gè)實(shí)現(xiàn)線性核函數(shù)的支持向量分類. 記住 LinearSVC 不接受關(guān)鍵詞 kernel, 因?yàn)樗患僭O(shè)為線性的. 它也缺少一些 SVCNuSVC 的成員(members) 比如 support_

在實(shí)踐過程中,NuSVC 沒怎么用過就暫且不提,但是LinearSVC 確實(shí)比直接在SVC 中把kernel設(shè)為線性核要快,當(dāng)然效果也相對(duì)差一點(diǎn)。

一般主要還是使用SVC

class sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape='ovr', random_state=None)
Parameters:
  • C : float類型,默認(rèn)值為1.0
    錯(cuò)誤項(xiàng)的懲罰系數(shù)。C越大,即對(duì)分錯(cuò)樣本的懲罰程度越大,因此在訓(xùn)練樣本中準(zhǔn)確率越高,但是泛化能力降低,也就是對(duì)測(cè)試數(shù)據(jù)的分類準(zhǔn)確率降低。相反,減小C的話,容許訓(xùn)練樣本中有一些誤分類錯(cuò)誤樣本,泛化能力強(qiáng)。對(duì)于訓(xùn)練樣本帶有噪聲的情況,一般采用后者,把訓(xùn)練樣本集中錯(cuò)誤分類的樣本作為噪聲

  • str類型,默認(rèn)為‘rbf’
    算法中采用的核函數(shù)類型,可選參數(shù)有:‘linear’:線性核函數(shù);‘poly’:多項(xiàng)式核函數(shù);‘rbf’:徑像核函數(shù)/高斯核;‘sigmod’:sigmod核函數(shù);‘precomputed’:核矩陣,precomputed表示自己提前計(jì)算好核函數(shù)矩陣,這時(shí)候算法內(nèi)部就不再用核函數(shù)去計(jì)算核矩陣,而是直接用你給的核矩陣

  • degree: int類型,默認(rèn)為3
    這個(gè)參數(shù)只對(duì)多項(xiàng)式核函數(shù)有用,是指多項(xiàng)式核函數(shù)的階數(shù)n,如果給的核函數(shù)參數(shù)是其他核函數(shù),則會(huì)自動(dòng)忽略該參數(shù)

  • gamma: float類型,默認(rèn)為auto
    核函數(shù)系數(shù),只對(duì)‘rbf’,‘poly’,‘sigmod’有效。如果gamma為auto,代表其值為樣本特征數(shù)的倒數(shù),即1/n_features

  • coef0: float類型,默認(rèn)為0.0
    核函數(shù)中的獨(dú)立項(xiàng),只有對(duì)‘poly’和‘sigmod’核函數(shù)有用,是指其中的參數(shù)c

  • probability: bool類型,默認(rèn)為False
    是否啟用概率估計(jì),這必須在調(diào)用fit()之前啟用,并且會(huì)fit()方法速度變慢

  • shrinking: bool類型,默認(rèn)為True
    是否采用啟發(fā)式收縮方式

  • tol: float類型,默認(rèn)為1e^-3
    svm停止訓(xùn)練的誤差精度

  • cache_size: float類型,默認(rèn)為200
    指定訓(xùn)練所需要的內(nèi)存,以MB為單位,默認(rèn)為200MB

  • class_weight: 字典類型或者‘balance’字符串,默認(rèn)為None
    給每個(gè)類別分別設(shè)置不同的懲罰參數(shù)C。如果沒有給,則會(huì)給所有類別都給C=1,即前面參數(shù)指出的參數(shù)C。如果給定參數(shù)‘balance’,則使用y的值自動(dòng)調(diào)整與輸入數(shù)據(jù)中的類頻率成反比的權(quán)重

  • verbose : bool類型,默認(rèn)為False
    是否啟用詳細(xì)輸出。 此設(shè)置利用libsvm中的每個(gè)進(jìn)程運(yùn)行時(shí)設(shè)置,如果啟用,可能無法在多線程上下文中正常工作。一般情況都設(shè)為False,不用管它
    max_iter : int類型,

  • 默認(rèn)為-1
    最大迭代次數(shù),如果為-1,表示不限制

  • random_state: int類型,默認(rèn)為None
    偽隨機(jī)數(shù)發(fā)生器的種子,在混洗數(shù)據(jù)時(shí)用于概率估計(jì)

  • decision_function_shape:str類型,默認(rèn)是’ovr’
    用來選擇如何構(gòu)造多類的SVM分類器。SVM算法最初是為二值分類問題設(shè)計(jì)的,當(dāng)處理多類問題時(shí),就需要構(gòu)造合適的多類分類器。 具體可以參考:decision_function_shape解釋

Attributes:
  • support_:各類的支持向量在訓(xùn)練樣本中的索引

  • n_support_:各類各有多少個(gè)支持向量

  • support_vectors_:各類所有的支持向量

  • dual_coef_: 對(duì)偶系數(shù),即支持向量在決策函數(shù)中的系數(shù),在多分類問題中,這個(gè)會(huì)有所不同

  • coef_: 每個(gè)特征系數(shù)(重要性),只有核函數(shù)是Linear的時(shí)候可用

  • intercept_: 決策函數(shù)中的常數(shù)項(xiàng),和coef_共同構(gòu)成決策函數(shù)的參數(shù)值

Method:
  • fit(X, y): 在數(shù)據(jù)集(X,y)上擬合SVM模型

  • predict(X): 預(yù)測(cè)數(shù)據(jù)值X的標(biāo)簽

  • score(X,y): 返回給定測(cè)試集和對(duì)應(yīng)標(biāo)簽的平均準(zhǔn)確率

  • decision_function(X): 獲取數(shù)據(jù)集中樣本X到分離超平面的距離

  • get_params([deep]): 獲取模型的參數(shù)

使用例子:

import numpy as np
from sklearn.svm import SVC

# 自己構(gòu)造的小數(shù)據(jù)
X = np.array([[-1, -1], [-2, -1], [1, 1], [2, 1]])
y = np.array([1, 1, 2, 2])

# 加載SVC模型(一般來說可能前面還有一個(gè)標(biāo)準(zhǔn)化的步驟,這邊暫時(shí)省掉)
clf = SVC()
# 訓(xùn)練該模型
 clf.fit(X, y) 

>> SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
    decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
    max_iter=-1, probability=False, random_state=None, shrinking=True,
    tol=0.001, verbose=False)

print(clf.predict([[-0.8, -1]]))
>> [1]


九、SVM相關(guān)面試題

這部分還是不斷更新:

面試好像對(duì)手推SVM和各個(gè)參數(shù)看得比較重,這部分還是要好好地推和背。

1. SVM的原理是什么?

SVM是一種二類分類模型。它的基本模型是在特征空間中尋找間隔最大化的分離超平面的線性分類器。(間隔最大是它有別于感知機(jī))

  1. 當(dāng)訓(xùn)練樣本線性可分時(shí),通過硬間隔最大化,學(xué)習(xí)一個(gè)線性分類器,即線性可分支持向量機(jī)
  2. 當(dāng)訓(xùn)練數(shù)據(jù)近似線性可分時(shí),引入松弛變量,通過軟間隔最大化,學(xué)習(xí)一個(gè)線性分類器,即線性支持向量機(jī)
  3. 當(dāng)訓(xùn)練數(shù)據(jù)線性不可分時(shí),通過使用核技巧及軟間隔最大化,學(xué)習(xí)非線性支持向量機(jī)

注:以上各SVM的數(shù)學(xué)推導(dǎo)應(yīng)該熟悉:硬間隔最大化(幾何間隔)---學(xué)習(xí)的對(duì)偶問題---軟間隔最大化(引入松弛變量)---非線性支持向量機(jī)(核技巧)

2. SVM為什么采用間隔最大化?

當(dāng)訓(xùn)練數(shù)據(jù)線性可分時(shí),存在無窮個(gè)分離超平面可以將兩類數(shù)據(jù)正確分開。感知機(jī)利用誤分類最小策略,求得分離超平面,不過此時(shí)的解有無窮多個(gè)。線性可分支持向量機(jī)利用間隔最大化求得最優(yōu)分離超平面,這時(shí),解是唯一的。另一方面,此時(shí)的分隔超平面所產(chǎn)生的分類結(jié)果是最魯棒的,對(duì)未知實(shí)例的泛化能力最強(qiáng)。

3. 為什么要將求解SVM的原始問題轉(zhuǎn)換為其對(duì)偶問題?
  1. 是對(duì)偶問題往往更易求解(當(dāng)我們尋找約束存在時(shí)的最優(yōu)點(diǎn)的時(shí)候,約束的存在雖然減小了需要搜尋的范圍,但是卻使問題變得更加復(fù)雜。為了使問題變得易于處理,我們的方法是把目標(biāo)函數(shù)和約束全部融入一個(gè)新的函數(shù),即拉格朗日函數(shù),再通過這個(gè)函數(shù)來尋找最優(yōu)點(diǎn)。)

  2. 自然引入核函數(shù),進(jìn)而推廣到非線性分類問題

4. 為什么SVM要引入核函數(shù)?

當(dāng)樣本在原始空間線性不可分時(shí),可將樣本從原始空間映射到一個(gè)更高維的特征空間,使得樣本在這個(gè)特征空間內(nèi)線性可分。在學(xué)習(xí)預(yù)測(cè)中,只定義核函數(shù)K(x,y),而不是顯式的定義映射函數(shù)?。因?yàn)樘卣骺臻g維數(shù)可能很高,甚至可能是無窮維,因此直接計(jì)算?(x)·?(y)是比較困難的。相反,直接計(jì)算K(x,y)比較容易(即直接在原來的低維空間中進(jìn)行計(jì)算,而不需要顯式地寫出映射后的結(jié)果)。

核函數(shù)的定義:K(x,y)=<?(x),?(y)>,即在特征空間的內(nèi)積等于它們?cè)谠紭颖究臻g中通過核函數(shù)K計(jì)算的結(jié)果。

5. svm RBF核函數(shù)的具體公式?

Gauss徑向基函數(shù)則是局部性強(qiáng)的核函數(shù),其外推能力隨著參數(shù)σ的增大而減弱。

這個(gè)核會(huì)將原始空間映射為無窮維空間。不過,如果 σ 選得很大的話,高次特征上的權(quán)重實(shí)際上衰減得非常快,所以實(shí)際上(數(shù)值上近似一下)相當(dāng)于一個(gè)低維的子空間;反過來,如果 σ 選得很小,則可以將任意的數(shù)據(jù)映射為線性可分——當(dāng)然,這并不一定是好事,因?yàn)殡S之而來的可能是非常嚴(yán)重的過擬合問題。不過,總的來說,通過調(diào)控參數(shù)σ ,高斯核實(shí)際上具有相當(dāng)高的靈活性,也是使用最廣泛的核函數(shù)之一。

6. 為什么SVM對(duì)缺失數(shù)據(jù)敏感?

這里說的缺失數(shù)據(jù)是指缺失某些特征數(shù)據(jù),向量數(shù)據(jù)不完整。SVM沒有處理缺失值的策略(決策樹有)。而SVM希望樣本在特征空間中線性可分,所以特征空間的好壞對(duì)SVM的性能很重要。缺失特征數(shù)據(jù)將影響訓(xùn)練結(jié)果的好壞。

7. SVM如何處理多分類問題?

一般有兩種做法:一種是直接法,直接在目標(biāo)函數(shù)上修改,將多個(gè)分類面的參數(shù)求解合并到一個(gè)最優(yōu)化問題里面。看似簡(jiǎn)單但是計(jì)算量卻非常的大。

另外一種做法是間接法:對(duì)訓(xùn)練器進(jìn)行組合。其中比較典型的有一對(duì)一,和一對(duì)多。

一對(duì)多,就是對(duì)每個(gè)類都訓(xùn)練出一個(gè)分類器,由svm是二分類,所以將此而分類器的兩類設(shè)定為目標(biāo)類為一類,其余類為另外一類。這樣針對(duì)k個(gè)類可以訓(xùn)練出k個(gè)分類器,當(dāng)有一個(gè)新的樣本來的時(shí)候,用這k個(gè)分類器來測(cè)試,那個(gè)分類器的概率高,那么這個(gè)樣本就屬于哪一類。這種方法效果不太好,bias比較高。

svm一對(duì)一法(one-vs-one),針對(duì)任意兩個(gè)類訓(xùn)練出一個(gè)分類器,如果有k類,一共訓(xùn)練出C(2,k) 個(gè)分類器,這樣當(dāng)有一個(gè)新的樣本要來的時(shí)候,用這C(2,k) 個(gè)分類器來測(cè)試,每當(dāng)被判定屬于某一類的時(shí)候,該類就加一,最后票數(shù)最多的類別被認(rèn)定為該樣本的類。


參考:

  1. https://www.cnblogs.com/dreamvibe/p/4349886.html
  2. 支持向量機(jī)通俗導(dǎo)論(理解SVM的三層境界)
  3. 統(tǒng)計(jì)機(jī)器學(xué)習(xí)
  4. https://www.cnblogs.com/steven-yang/p/5658362.html
  5. https://blog.csdn.net/on2way/article/details/47730367
  6. https://www.cnblogs.com/zy230530/p/6901277.html
  7. 機(jī)器學(xué)習(xí)實(shí)戰(zhàn)
  8. sklearn官方手冊(cè)
  9. https://www.cnblogs.com/solong1989/p/9620170.html
  10. https://blog.csdn.net/github_39261590/article/details/75009069
  11. https://blog.csdn.net/szlcw1/article/details/52336824
  12. https://blog.csdn.net/szlcw1/article/details/52259668
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。