《Machine Learning in Action》—— 剖析支持向量機(jī)近哟,單手狂撕線性SVM

《Machine Learning in Action》—— 剖析支持向量機(jī),單手狂撕線性SVM

前面在寫(xiě)NumPy文章的結(jié)尾處也有提到钱豁,本來(lái)是打算按照《機(jī)器學(xué)習(xí)實(shí)戰(zhàn) / Machine Learning in Action》這本書(shū)來(lái)手撕其中代碼的,但由于實(shí)際原因疯汁,可能需要先手撕SVM了牲尺,這個(gè)算法感覺(jué)還是挺讓人頭疼,其中內(nèi)部太復(fù)雜了幌蚊,涉及到的數(shù)學(xué)公式太多了谤碳,也涉及到了許多陌聲的名詞,如:非線性約束條件下的最優(yōu)化溢豆、KKT條件蜒简、拉格朗日對(duì)偶、最大間隔漩仙、最優(yōu)下界搓茬、核函數(shù)等等犹赖,天書(shū)或許、可能卷仑、大概就是這樣的吧峻村。

記得與SVM初次邂逅是在17年,那個(gè)時(shí)候的自己年少輕狂锡凝,視圖想著站在巨人的肩膀上粘昨,把所有自己感興趣的內(nèi)容都搞懂,深入骨髓的那種窜锯。但后來(lái)殘酷的現(xiàn)實(shí)讓我明白一個(gè)道理:你知道的越多张肾,你不知道的也越多。而且那個(gè)時(shí)候自己也沒(méi)有能力锚扎、資源和機(jī)會(huì)去深入SVM內(nèi)部吞瞪,完全無(wú)法理解SVM的內(nèi)部原理。所以工秩,當(dāng)時(shí)自己對(duì)SVM的收獲只有一個(gè):SVM主要是用來(lái)做分類任務(wù)的尸饺,僅此而已。

第二次接觸SVM是在準(zhǔn)備考研復(fù)試吧助币,當(dāng)時(shí)復(fù)試并沒(méi)有給出具體內(nèi)容和范圍浪听,而且自己也還是個(gè)初出茅廬的小子,對(duì)這種所謂的復(fù)試有種莫名的恐懼感眉菱。也只有從上屆學(xué)長(zhǎng)學(xué)姐的口中迹栓,得知復(fù)試的時(shí)候老師會(huì)考究學(xué)生是否有科研的潛力,所以最好把機(jī)器學(xué)習(xí)熟知一下俭缓。那個(gè)時(shí)候也是處于新冠疫情的緊張時(shí)期嘛克伊,就瘋狂補(bǔ)習(xí)機(jī)器學(xué)習(xí)的內(nèi)容,其中就包括支持向量機(jī)——SVM华坦,主要的學(xué)習(xí)渠道是吳恩達(dá)老師的機(jī)器學(xué)習(xí)課程愿吹,感覺(jué)講的的確不錯(cuò),非常適合我這種菜鳥(niǎo)級(jí)選手學(xué)習(xí)惜姐。當(dāng)時(shí)也算是對(duì)SVM有了一定的認(rèn)識(shí)吧犁跪,也大致了解了SVM的工作原理,當(dāng)然了歹袁,也只是對(duì)SVM有了個(gè)的淺顯的認(rèn)識(shí)坷衍,沒(méi)有手撕SVM的過(guò)程,也沒(méi)有完全把它整明白条舔。盡管如此枫耳,復(fù)試的過(guò)程依然被面試導(dǎo)師錘的體無(wú)完膚,除了問(wèn)了機(jī)器學(xué)習(xí)相關(guān)內(nèi)容之外孟抗,編譯原理等一些專業(yè)知識(shí)對(duì)于我這個(gè)貿(mào)易專業(yè)的學(xué)生來(lái)講可太痛苦了迁杨,之前也沒(méi)有接觸過(guò)钻心,全程阿巴阿巴。想到這仑最,眼角又又扔役。。警医。

第三次面對(duì)SVM也就是現(xiàn)在了亿胸,想著無(wú)論如何也要打通我的任督二脈,一定要搞清楚SVM的來(lái)龍去脈预皇,也要像面試?yán)蠋煷肺夷菢映扌裇VM往死里錘。于是有了下文學(xué)習(xí)SVM之后的總結(jié)吟温,一方面算是重新梳理一遍SVM序仙,另一方面也希望來(lái)訪的讀者能夠有所收獲。

對(duì)于剛剛接觸SVM的讀者鲁豪,Taoye主要有以下幾條建議潘悼,也是我學(xué)習(xí)SVM過(guò)程中的一個(gè)小總結(jié)吧:

  • SVM內(nèi)部的數(shù)學(xué)公式很多,但請(qǐng)不要未戰(zhàn)先怯爬橡,犯下兵家大忌治唤。無(wú)論是閱讀該篇文章也好,學(xué)習(xí)其他相關(guān)SVM資源也罷糙申,還請(qǐng)諸君耐心宾添、認(rèn)真且完整的看完。
  • SVM的原理過(guò)程會(huì)涉及到很多的符號(hào)或記號(hào)柜裸,一定要梳理清楚他們所代表的含義缕陕。另外,推導(dǎo)過(guò)程中會(huì)存在很多的向量或矩陣疙挺,一定要明白其中shape扛邑,這一點(diǎn)可能在不同的資料中會(huì)有不一樣的處理方式。
  • 在閱讀的同時(shí)铐然,一定要拿出稿紙手動(dòng)推演SVM的過(guò)程蔬崩,盡可能明白整個(gè)過(guò)程的來(lái)龍去脈,有不明白的地方可以留言或查找其他相關(guān)資料來(lái)輔助自己的理解锦爵。
  • 閱讀一遍或許有不少知識(shí)不理解,但多閱讀幾遍相信一定會(huì)有不少收獲

本文參考了不少書(shū)籍資料以及許多大佬的技術(shù)文章奥裸,行文風(fēng)格盡可能做到通俗易懂险掀,但其中涉及到的數(shù)學(xué)公式在所難免,還請(qǐng)諸讀者靜下心來(lái)慢慢品嘗湾宙。由于個(gè)人水平有限樟氢,才疏學(xué)淺冈绊,對(duì)于SVM也只是略知皮毛,可能文中有不少表述稍有欠妥埠啃、有不少錯(cuò)誤或不當(dāng)之處死宣,還請(qǐng)諸君批評(píng)指正。

我是Taoye碴开,愛(ài)專研毅该,愛(ài)分享,熱衷于各種技術(shù)潦牛,學(xué)習(xí)之余喜歡下象棋眶掌、聽(tīng)音樂(lè)、聊動(dòng)漫巴碗,希望借此一畝三分地記錄自己的成長(zhǎng)過(guò)程以及生活點(diǎn)滴朴爬,也希望能結(jié)實(shí)更多志同道合的圈內(nèi)朋友,更多內(nèi)容歡迎來(lái)訪微信公主號(hào):玩世不恭的Coder

符號(hào)說(shuō)明

符號(hào) 說(shuō)明
x_i 表示單個(gè)樣本橡淆,其中包含多個(gè)屬性召噩,顯示為一個(gè)行向量
x^{(i)} 表示單個(gè)樣本中的某個(gè)屬性特征
y_i 表示單個(gè)樣本所對(duì)應(yīng)的標(biāo)簽(具體分類),為整數(shù)逸爵,非1即-1
w^T 表示的是權(quán)值行向量具滴,其中w=(w_1,w_2,...,w_m)^T,也是所需要訓(xùn)練的參數(shù)
b 表示的是決策面中的b痊银,也是所需要訓(xùn)練的參數(shù)
\hat{\gamma} 表示函數(shù)間隔抵蚊,具體解釋見(jiàn)下文
\gamma 表示幾何間隔,具體解釋見(jiàn)下文
\alpha \alpha=(\alpha_1,...,\alpha_N)表示拉格朗日乘子
K_{ij} 在這篇文章中表示線性核函數(shù)

關(guān)于上述的符號(hào)說(shuō)明溯革,僅僅只是本篇文章的一部分贞绳,其他符號(hào)可通過(guò)正文了解。上述符號(hào)可能部分暫時(shí)不懂致稀,但沒(méi)關(guān)系冈闭,讀者可在閱讀的過(guò)程中,隨時(shí)返回來(lái)查看抖单,即可理解每個(gè)符號(hào)所代表的意義萎攒。

一、SVM是什么

關(guān)于SVM是什么矛绘,之前在Byte Size Biology上看到有篇文章很好的解釋了SVM耍休,在知乎上也有一位名叫“簡(jiǎn)之”的用戶通過(guò)故事的形式來(lái)將其進(jìn)行轉(zhuǎn)述,通俗易懂货矮,很好的向首次接觸SVM的讀者介紹了SVM能干嘛羊精。

image

油管上也有更為直觀認(rèn)識(shí)SVM的短視頻(翻墻):https://www.youtube.com/watch?v=3liCbRZPrZA

總結(jié)一哈:

對(duì)于一個(gè)二分類問(wèn)題宰翅,樣本數(shù)據(jù)是線性可分的,我們則需要通過(guò)一根直線(也就是上述例子當(dāng)中枝條)將兩個(gè)不同種類的樣本進(jìn)行分離。按道理來(lái)講新翎,我們已經(jīng)實(shí)現(xiàn)了需求惠赫,但是终蒂,這根枝條的具體擺放位置可能有無(wú)數(shù)多個(gè)席里,而我們的最終目的是將枝條擺放到一個(gè)最好的位置,從而當(dāng)我們引入了一些新樣本的時(shí)候阵具,依然能最好很好將兩類的數(shù)據(jù)分離開(kāi)來(lái)碍遍,也就是說(shuō)我們需要將模型的“泛化性能”最大化。之前也看到過(guò)一個(gè)例子(來(lái)源忘了)怔昨,這里分享下雀久,大概就是講:我們?cè)谕ㄟ^(guò)懸崖吊橋的時(shí)候,會(huì)不自覺(jué)的盡可能往中間走趁舀,因?yàn)檫@樣的話赖捌,當(dāng)左右起風(fēng)的時(shí)候,雖然我們的位置會(huì)左右稍微移動(dòng)矮烹,但還不至于跌落懸崖越庇。而越靠近邊緣,風(fēng)險(xiǎn)就越大奉狈,就是這么個(gè)道理卤唉。而尋找最大“泛化性能”的過(guò)程,就是將枝條擺放在距離小球最遠(yuǎn)的位置仁期,而小球相對(duì)于枝條的位置就是“間隔”桑驱,而我們要做的就是將這間隔最大化

上述僅僅是對(duì)于線性可分?jǐn)?shù)據(jù)分類的一種處理方式跛蛋,但有的時(shí)候熬的,理想是美好的,現(xiàn)實(shí)卻是殘酷的赊级。在實(shí)際樣本數(shù)據(jù)中押框,大多都是線性不可分的,也就是說(shuō)我們無(wú)法找到合適位置的枝條將不同分類的數(shù)據(jù)分離開(kāi)來(lái)理逊,更別提“間隔最大化”了橡伞。這個(gè)時(shí)候,我們就需要將桌上的小球排起晋被,然后用一個(gè)平面(紙)將不同分類小球分離開(kāi)來(lái)兑徘。也就是說(shuō),我們將低維度映射到了高緯度羡洛,這樣對(duì)于小球的分類就更加容易了挂脑。

再之后,無(wú)聊的大人們,把這些球叫做 「data」最域,把棍子 叫做 「classifier」, 最大間隙trick 叫做「optimization」, 拍桌子叫做「kernelling」, 那張紙叫做「hyperplane」锈麸。

二镀脂、線性可分SVM與間隔最大化

我們先來(lái)看具體看看線性可分的二分類問(wèn)題。

假如說(shuō)忘伞,我們這里有一堆樣本薄翅,也就是我們常說(shuō)的訓(xùn)練集S=\{(x_1, y_1), (x_1, y_1), (x_3, y_3), ..., (x_n, y_n)\},且x_i表示的是樣本i屬性特征向量氓奈,其內(nèi)部有多個(gè)不同屬性翘魄,這里我們不妨指定每個(gè)樣本含有兩個(gè)屬性特征,也就是說(shuō)x_i=(x_{i1}, x_{i2})^T(之所以用列向量表示舀奶,主要是方便后面超平面的構(gòu)建)暑竟。而y_i表示的是每個(gè)樣本中所有屬性特征所對(duì)應(yīng)的標(biāo)簽,由于這里的問(wèn)題屬性二分類育勺,所以y_i的值只存在兩種但荤。為此,我們可以通過(guò)Matplotlib在平面直角坐標(biāo)系中繪制其圖像涧至,初步觀察其分布規(guī)律腹躁,具體代碼如下:

import numpy as np
import pylab as pl
from sklearn import svm

%matplotlib inline
print(np.__version__)

"""
    Author: Taoye
    微信公眾號(hào):玩世不恭的Coder
"""
if __name__ == "__main__":
    # np.random.seed(100)        # 可自行設(shè)置隨機(jī)種子每次隨機(jī)產(chǎn)生相同的數(shù)據(jù)
    X_data = np.concatenate((np.add(np.random.randn(20, 2), [3, 3]),       
                             np.subtract(np.random.randn(20, 2), [3, 3])),
                             axis = 0)      # random隨機(jī)生成數(shù)據(jù),+ -3達(dá)到不同類別數(shù)據(jù)分隔的目的 

    Y_label = np.concatenate((np.zeros([20]), np.ones([20])), axis = 0)

    svc = svm.SVC(kernel = "linear")
    svc.fit(X_data, Y_label)
    
    w = svc.coef_[0]      
    ww = -w[0] / w[1]                # 獲取權(quán)重w
    xx = np.linspace(-6, 6)
    yy = ww * xx - (svc.intercept_[0]) / w[1]   # intercept_獲取結(jié)截距
    
    b_down = svc.support_vectors_[0]         # 得到對(duì)應(yīng)的支持向量
    yy_down = ww * xx + (b_down[1] - ww * b_down[0])
    b_up = svc.support_vectors_[-1]
    yy_up = ww * xx + (b_up[1] - ww * b_up[0])

    pl.plot(xx, yy, "k-"); pl.plot(xx, yy_down, "k--"); pl.plot(xx, yy_up, "k--")
    pl.scatter(X_data[:, 0], X_data[:, 1], c = Y_label, cmap = pl.cm.Paired)

    pl.show()

執(zhí)行代碼南蓬,可以繪制如下所示圖片纺非,注意:以上代碼每次運(yùn)行都會(huì)隨機(jī)產(chǎn)生不同的二分類數(shù)據(jù)集,如想每次隨機(jī)產(chǎn)生相同的數(shù)據(jù)集赘方,可自行配置np.random.seed隨機(jī)種子烧颖;另外,還有一點(diǎn)需要需要說(shuō)明的是蒜焊,上述代碼使用到了NumPy倒信,關(guān)于NumPy的使用,可自行參考之前寫(xiě)的一篇文章:print( "Hello泳梆,NumPy鳖悠!" )

image

如上圖所示,我們可以發(fā)現(xiàn)优妙,棕色代表一類數(shù)據(jù)集乘综,此時(shí)標(biāo)簽y_i=1,藍(lán)色代表另一類數(shù)據(jù)集套硼,標(biāo)簽y_i=0卡辰,而要想將上圖兩類數(shù)據(jù)集分離開(kāi)來(lái),顯然不止一條直線,與上圖兩條虛線平行且居其之間的任意一條直線都能達(dá)到此目的九妈。在這無(wú)數(shù)條直線中反砌,要數(shù)上圖中的三條最為特殊,中間實(shí)線居于兩條虛線中間萌朱,我們一般稱其為“決策面”“超平面”宴树,而其所表示的方程,我們一般稱作“決策方程”“超平面方程”晶疼,在這里可以表示為w^Tx+b=0酒贬。(下面會(huì)推導(dǎo))

從上圖我們還可以觀察得到,在所有樣本數(shù)據(jù)集中翠霍,虛線上的樣本距離決策面最近锭吨,我們把這種比較特殊的樣本數(shù)據(jù)一般稱之為“支持向量”,而支持向量到?jīng)Q策面之間的距離稱為“間隔”寒匙。我們不難發(fā)現(xiàn)零如,決策面的位置主要取決于支持向量,而與支持向量除外的數(shù)據(jù)樣本沒(méi)有關(guān)系锄弱。(因?yàn)橹С窒蛄康拇_定就已經(jīng)確定了最大間隔)

關(guān)于上述提到的一些關(guān)于SVM的名詞概念埠况,在正式推演之前,還是有必要理解清楚的棵癣。

前面我們也有提到辕翰,關(guān)于能將兩類不同數(shù)據(jù)集相互分隔開(kāi)來(lái)的直線有無(wú)數(shù)種,而我們要想在這無(wú)數(shù)種直線找到一條最合適的狈谊,也就是達(dá)到一個(gè)間隔最大化的目的喜命,這就是一個(gè)“最優(yōu)化”問(wèn)題。而最優(yōu)化問(wèn)題河劝,我們需要了解兩個(gè)因素壁榕,分別是目標(biāo)函數(shù)和優(yōu)化對(duì)象。既然我們是想要達(dá)到間隔最大化的目標(biāo)赎瞎,那么目標(biāo)函數(shù)自然就是間隔牌里,而優(yōu)化對(duì)象就是我們的決策面方程。所以务甥,我們首先需要用數(shù)學(xué)來(lái)明確間隔和決策面方程:

我們知道牡辽,在平面直角坐標(biāo)系中,一條直線可以用其一般式方程來(lái)來(lái)表示:

Ax+By+C=0

而根據(jù)上述圖像敞临,我們可以知道态辛,橫縱坐標(biāo)代表的意義是一個(gè)樣本的不同屬性特征,而標(biāo)簽則是通過(guò)顏色(棕色和藍(lán)色)來(lái)進(jìn)行表示挺尿。所以上述的直線的一般式方程中的x奏黑、y表示的就是一個(gè)樣本的兩種屬性特征炊邦,為了方便理解,我們不妨將其修改為x^{(1)}熟史、x^{(2)}馁害,并將A、B蹂匹、C替換為w_1蜗细、w_2、b怒详,對(duì)此,我們可以將上述方程向量化踪区,得到:

\left( \begin{matrix} w_1, w_2 \\ \end{matrix} \right) \times \left( \begin{matrix} x^{(1)} \\ x^{(2)} \end{matrix} \right) \ +b=0 \tag{2-1}

w=(w_1, w_2)^T, x=(x^{(1)}, x^{(2)})昆烁,則上述指向方程最終可以表示為:

w^Tx+b=0 \tag{2-2}

式(1-2)表示的就是我們優(yōu)化問(wèn)題的優(yōu)化對(duì)象,也就是決策面方程缎岗。我們知道在平面直角坐標(biāo)系中静尼,一條直線可以通過(guò)其斜率和截距來(lái)確定,而在決策面方程里传泊,我們不難得到:w確定了決策面的方向(斜率) 鼠渺,而b確定了決策面的截距。既然我們已經(jīng)得到了優(yōu)化問(wèn)題的優(yōu)化對(duì)象——決策面方程眷细,那么接下來(lái)就需要得到目標(biāo)函數(shù)——間隔的表達(dá)式了拦盹。

在此,我們需要引入函數(shù)間隔幾何間隔的概念了溪椎。

一般來(lái)講普舆,我們可以通過(guò)樣本點(diǎn)到?jīng)Q策面的距離來(lái)表示分類預(yù)測(cè)的正確程度,距離決策面越遠(yuǎn)校读,一般分類就越正確(可根據(jù)圖像自行理解)沼侣,而在超平面w^Tx+b=0確定的情況下,我們可以通過(guò)|w^Tx_i+b|的值來(lái)描述樣本x_i距超平面的遠(yuǎn)近(注意:這里是描述遠(yuǎn)近歉秫。而不是確切的距離)蛾洛。我們知道,樣本有不同的分類雁芙,所以有的時(shí)候|w^Tx_i+b|的符號(hào)具有不確定性轧膘,所以我們可以通過(guò)w^Tx_i+by_i的符號(hào)來(lái)判斷分類結(jié)果的正確性。也就是說(shuō)可以通過(guò)y_i(w^Tx_i+b)值的大小和符號(hào)來(lái)判斷一個(gè)樣本分類的正確性和正確程度兔甘,這個(gè)就是我們的函數(shù)間隔(這個(gè)概念務(wù)必要理解清楚)扶供,我們不妨用\hat{\gamma_i}來(lái)表示:

\hat{\gamma_i}=y_i(w^Tx_i + b) \tag{2-3}

而我們知道,上述的i=1,2,...,N裂明,表示的是有N個(gè)樣本椿浓,而在N個(gè)樣本中太援,固然存在一個(gè)樣本使得該值達(dá)到最小,該樣本也就是我們前面所說(shuō)的支持向量扳碍,我們把支持向量到超平面的函數(shù)間隔定義為\hat{\gamma}提岔,則:

\hat{\gamma} = \mathop{min}\limits_{i=1,...,N}\hat{\gamma_i} \tag{2-4}

我們只有函數(shù)間隔還不夠,函數(shù)間隔描述的僅僅是樣本分類的正確性和正確程度笋敞,而不是確切的間隔碱蒙。當(dāng)我們成比例的更改wb的時(shí)候,決策面并沒(méi)有發(fā)生任何改變夯巷,而函數(shù)間隔卻發(fā)生了改變赛惩,所以我們需要對(duì)w進(jìn)行約束,從而當(dāng)無(wú)論wb怎么成比例變動(dòng)的時(shí)候趁餐,我們的“間隔”都不會(huì)發(fā)生改變喷兼,也就是進(jìn)行將w規(guī)范化,由函數(shù)間隔規(guī)范后的間隔我們稱之為幾何間隔后雷,我們不妨用\gamma來(lái)表示季惯,則某個(gè)樣本到超平面的幾何間隔為\gamma_i

\gamma_i=\frac{|w^Tx_i + b|}{||w||} \tag{2-5}

我們可以將式子(1-5)理解成點(diǎn)到直線的距離公式(這個(gè)在中學(xué)時(shí)期就學(xué)過(guò)的)。對(duì)于這個(gè)二分類問(wèn)題臀突,我們不妨將二分類的標(biāo)簽定為 y_i=\{1, -1\}勉抓,則\gamma_i可以表示為(之所以乘以y_i,主要是把絕對(duì)值符號(hào)去掉候学,這樣就能描述所有樣本了藕筋,而省去了分類討論的麻煩):

\gamma_i=y_i\frac{w^Tx_i + b}{||w||} \tag{2-6}

而我們知道,上述的i=1,2,...,N梳码,表示的是有N個(gè)樣本念逞,而在N個(gè)樣本中,固然存在一個(gè)樣本使得該值達(dá)到最小边翁,該樣本也就是我們前面所說(shuō)的支持向量翎承,我們把支持向量到超平面的幾何間隔定義為\hat{\gamma},則:

\gamma=\mathop{min}\limits_{i=1,...,N}\gamma_i \tag{2-7}

通過(guò)上述對(duì)函數(shù)間隔和幾何間隔的分析符匾,我們可以得到他們之間的關(guān)系:

\gamma_i=\frac{\hat{\gamma_i}}{||w||}叨咖,即\gamma=\frac{\hat{\gamma}}{||w||} \tag{2-8}

自此,我們已經(jīng)分析得到了該優(yōu)化問(wèn)題的優(yōu)化對(duì)象——決策面方程和目標(biāo)函數(shù)——間隔(幾何間隔)啊胶。在之前甸各,我們提到了支持向量的概念,那么支持向量具有什么特性呢焰坪?細(xì)想一下不難發(fā)現(xiàn)趣倾,支持向量到?jīng)Q策平面的間隔是最近的,即滿足如下式子:

\gamma_i=y_i\frac{w^Tx_i + b}{||w||}\geq\gamma 某饰,即y_i(w^Tx_i + b)\geq\gamma||w||=\hat{\gamma} \tag{2-9}

對(duì)此儒恋,我們就可以通過(guò)數(shù)學(xué)來(lái)表達(dá)該優(yōu)化問(wèn)題:

\begin{aligned} & \mathop{max}\limits_{w,b} \quad \frac{\hat{\gamma}}{||w||} \tag{2-10} \\ & s.t. \quad\ y_i(w^Tx_i + b)\geq\hat{\gamma}善绎,i=1,2,3,...,N \end{aligned}

前面,我們提到了诫尽,函數(shù)間隔描述的僅僅是樣本分類的正確性和正確程度禀酱,而不是確切的間隔。當(dāng)我們成比例的更改wb的時(shí)候牧嫉,函數(shù)間隔雖然發(fā)生了改變剂跟,但并不會(huì)影響我們的幾何間隔——目標(biāo)函數(shù)船逮,也就是說(shuō)漠畜,此時(shí)產(chǎn)生了一個(gè)等價(jià)的最優(yōu)化問(wèn)題。為了方便描述問(wèn)題蹭沛,我們不妨取\hat{\gamma}=1辽剧。另外送淆,我們注意到目標(biāo)函數(shù)\mathop{max}\limits_{w,b} \frac{\hat{\gamma}}{||w||}可以等價(jià)于\mathop{min}\limits_{w,b}\frac{1}{2}||w||^2,(注意抖仅,僅僅是等價(jià)。而之所以等價(jià)為二分之一砖第、平方的形式撤卢,主要是方便后期的求導(dǎo)操作),對(duì)此梧兼,我們可以將數(shù)學(xué)表達(dá)的優(yōu)化問(wèn)題轉(zhuǎn)化為如下形式:
\begin{aligned} & \mathop{min}\limits_{w,b} \quad \frac{1}{2}||w||^2 \\ & s.t. \quad\ y_i(w^Tx_i + b)-1\geq0放吩,i=1,2,3,...,N \tag{2-11} \end{aligned}

關(guān)于如上提到的決策平面和間隔等概念,我們可以通過(guò)下圖來(lái)直觀感受下(理解清楚):

圖片來(lái)源:西瓜書(shū)

至此羽杰,我們已經(jīng)得到了該優(yōu)化問(wèn)題的數(shù)學(xué)表達(dá)渡紫,我們不妨通過(guò)一個(gè)小例子來(lái)檢測(cè)下:


例子來(lái)源:李航-《統(tǒng)計(jì)學(xué)習(xí)方法》第七章內(nèi)容

例子1:已知一個(gè)如圖所示的訓(xùn)練數(shù)據(jù)集,其正例點(diǎn)是x_1=(3, 3)^T,x_2=(4, 3)^T考赛,負(fù)例點(diǎn)為x_3=(1, 1)^T惕澎,試求最大間隔分離的決策面?

image

根據(jù)前面的優(yōu)化問(wèn)題表達(dá)颜骤,我們可以得到如下表示:

\begin{aligned} & \mathop{min}\limits_{w,b} \quad \frac{1}{2}(w_1^2+w_2^2) \\ & s.t. \quad\ \ 3w_1+3w_2+b \geq1 \\ & \qquad \quad\ 4w_1+3w_2+b \geq1 \\ & \qquad \quad -w_1-w_2-b \geq1 \end{aligned}

求解可以得到目標(biāo)函數(shù)的最小時(shí)唧喉,w_1=w_2=\frac{1}{2},b=-2,于是最大間隔分離的決策面為:

\frac{1}{2}x^{(1)}+\frac{1}{2}x^{(2)}-2=0

其中忍抽,x_1=(3,3)^Tx_3=(1,1)^T為支持向量八孝。


三、拉格朗日乘數(shù)法和對(duì)偶問(wèn)題

首先鸠项,我們有必要先了解下什么是拉格朗日乘數(shù)法干跛。

關(guān)于對(duì)偶問(wèn)題,《統(tǒng)計(jì)學(xué)習(xí)方法》一書(shū)中是如此描述的:

為了求解線性可分的支持向量機(jī)的最優(yōu)化問(wèn)題祟绊,將它作為原始最優(yōu)化問(wèn)題楼入,應(yīng)用拉格朗日對(duì)偶性哥捕,通過(guò)求解對(duì)偶問(wèn)題(dual problem)得到原始問(wèn)題(primary problem)的最優(yōu)解,這就是線性可分支持向量機(jī)的對(duì)偶算法(dual algorithm)浅辙。這樣做的優(yōu)點(diǎn)扭弧,一是對(duì)偶問(wèn)題往往更容易求解;二是自然引入核函數(shù)记舆,進(jìn)而推廣到非線性分類問(wèn)題鸽捻。

按照前面對(duì)優(yōu)化問(wèn)題的求解思路,構(gòu)造拉格朗日方程的目的是將約束條件放到目標(biāo)函數(shù)中泽腮,從而將有約束優(yōu)化問(wèn)題轉(zhuǎn)換為無(wú)約束優(yōu)化問(wèn)題御蒲。我們?nèi)匀槐羞@一思路去解決不等式約束條件下的優(yōu)化問(wèn)題,那么如何針對(duì)不等式約束條件下的優(yōu)化問(wèn)題構(gòu)建拉格朗日函數(shù)呢诊赊?

因?yàn)槲覀円蠼獾氖亲钚』瘑?wèn)題厚满,所以一個(gè)直觀的想法是如果我能夠構(gòu)造一個(gè)函數(shù),使得該函數(shù)在可行解區(qū)域內(nèi)與原目標(biāo)函數(shù)完全一致碧磅,而在可行解區(qū)域外的數(shù)值非常大碘箍,甚至是無(wú)窮大,那么這個(gè)沒(méi)有約束條件的新目標(biāo)函數(shù)的優(yōu)化問(wèn)題就與原來(lái)有約束條件的原始目標(biāo)函數(shù)的優(yōu)化是等價(jià)的問(wèn)題鲸郊。

對(duì)此丰榴,我們重新回顧下原優(yōu)化問(wèn)題的數(shù)學(xué)表達(dá):

關(guān)于拉個(gè)朗日乘數(shù)法的解題思路,其實(shí)早在大學(xué)《高等數(shù)學(xué)》這門(mén)課程中就已經(jīng)提到過(guò)秆撮,我們不妨通過(guò)一個(gè)小例子來(lái)了解下其解題的一般形式:


例子來(lái)源:李億民-《微積分方法》第二章內(nèi)容

例子2:求函數(shù)f(x, y)=4x+xy^2+y^2D:x^2+y^2\leq1上的最值四濒。

做拉格朗日函數(shù)L(x,y,\lambda)

L(x, y, \lambda)=4x+xy^2+y^2+\lambda(x^2+y^2-1)

上面的拉格朗日函數(shù),我們分別對(duì)x,y,\lambda求偏導(dǎo)职辨,得到:

\begin{cases} L_x^{'}(x,y,\lambda)=4+y^2+2\lambda x=0 \\ L_y^{'}(x,y,\lambda)=2xy+2y+2\lambda y=0 \\ L_\lambda^{'}(x,y,\lambda)=x^2+y^2-1=0\\ \end{cases}

求解得到x=1,y=0x=-1,y=0盗蟆,所以f_{min}(x,y)=f(-1,0)=-4,f_{max}(x,y)=f(1,0)=4


上例就是利用拉格朗日求解最優(yōu)問(wèn)題的一般思路舒裤,先構(gòu)造拉格朗日函數(shù)喳资,然后分別對(duì)參數(shù)求偏導(dǎo),最終求解得到最優(yōu)解腾供。而我們要想得到最大間隔骨饿,同樣可以根據(jù)該思路進(jìn)行,只不過(guò)式子更加復(fù)雜台腥,而我們還需要利用拉格朗日的對(duì)偶性來(lái)簡(jiǎn)化優(yōu)化問(wèn)題宏赘。

在此之前,我們先來(lái)回顧下該優(yōu)化問(wèn)題下的數(shù)學(xué)表達(dá):

\begin{aligned} & \mathop{min}\limits_{w,b} \quad \frac{1}{2}||w||^2 \\ & s.t. \quad\ y_i(w^Tx_i + b)-1\geq0黎侈,i=1,2,3,...,N \tag{3-1} \end{aligned}

按照我們例2的思路察署,我們首先構(gòu)造出該優(yōu)化問(wèn)題的拉格朗日函數(shù),注意:(2-1)式的限制條件是對(duì)于樣本 i 的峻汉,而這里的i=1,2,3,...,N贴汪,所以想這樣的約束條件有N個(gè)脐往,而每個(gè)約束條件都對(duì)應(yīng)一個(gè)拉格朗日乘子(例2的\lambda),我們不妨將該拉格朗日乘子定義為\alpha_i扳埂,其中i=1,2,3,...N业簿。據(jù)此,我們構(gòu)建出的該優(yōu)化問(wèn)題的拉格朗日函數(shù)如下:

L(w,b,\alpha)=\frac{1}{2}||w||^2-\sum^N_{i=1}\alpha_iy_i(w^Tx_i+b) + \sum^N_{i=1}\alpha_i \tag{3-2}

其中阳懂,\alpha=(\alpha_1,\alpha_2,\alpha_3,...,\alpha_N)^T為拉格朗日乘子向量梅尤。

\theta(w,b)=\mathop{max}\limits_{\alpha>0} \ L(w,b,\alpha),原始目標(biāo)函數(shù)即可轉(zhuǎn)化為:

\mathop{min}\limits_{w,b} \frac{1}{2}||w||^2= \mathop{min}\limits_{w,b}\ \mathop{max}\limits_{\alpha}L(w,b,\alpha) =p^* \tag{3-3}

根據(jù)上述目標(biāo)函數(shù)岩调,我們可以發(fā)現(xiàn)是先求最大值巷燥,再求最小值,而內(nèi)層最小值是關(guān)于\alpha号枕,而外層最大值是關(guān)于w,b缰揪,而我們的\alpha又是不等式約束,這樣對(duì)于求解來(lái)講過(guò)于麻煩葱淳。由拉格朗日的對(duì)偶性钝腺,原始問(wèn)題的對(duì)偶問(wèn)題就是極大極小值,其對(duì)偶問(wèn)題如下:

\mathop{max}\limits_{\alpha}\ \mathop{min}\limits_{w,b}L(w,b,\alpha) =d^* \tag{3-4}

且原問(wèn)題和對(duì)偶問(wèn)題滿足如關(guān)系:d^*\leq p^*赞厕,而我們要找的是d^*= p^*艳狐。讀到這里,我們應(yīng)該會(huì)存在兩個(gè)疑問(wèn):

  • 疑問(wèn)1:為什么前面我們令\theta(w,b)=\mathop{max}\limits_{\alpha>0} \ L(w,b,\alpha)坑傅,而不是其他的表達(dá)形式呢僵驰?

主要是因?yàn)榕缯@樣替換之后唁毒,我們能使得該函數(shù)在可行解區(qū)域內(nèi)與原目標(biāo)函數(shù)完全一致,而在可行解區(qū)域外的數(shù)值非常大星爪,甚至是無(wú)窮大浆西,那么這個(gè)沒(méi)有約束條件的新目標(biāo)函數(shù)的優(yōu)化問(wèn)題就與原來(lái)有約束條件的原始目標(biāo)函數(shù)的優(yōu)化是等價(jià)的問(wèn)題。(這句話要重點(diǎn)理解

令:

\theta(w,b)=\mathop{max}\limits_{\alpha>0} \ L(w,b,\alpha)=\mathop{max}\limits_{\alpha>0} \ [\frac{1}{2}||w||^2-\sum^N_{i=1}\alpha_iy_i(w^Tx_i+b) + \sum^N_{i=1}\alpha_i \tag{3-5}]

之后顽腾,\theta(w,b)在可行解區(qū)域之內(nèi)\quad\ y_i(w^Tx_i + b)-1\geq0和可行解區(qū)域之外\quad\ y_i(w^Tx_i + b)-1<0近零,我們通過(guò)分析得到:在可行解區(qū)域之內(nèi),

\sum^N_{i=1}\alpha_iy_i(w^Tx_i+b) - \sum^N_{i=1}\alpha_i \geq0

此時(shí)抄肖,我們要求的是 \mathop{max}\limits_{\alpha>0} \ L(w,b,\alpha)久信,而\frac{1}{2}||w||^2減去一個(gè)大于等于0的最大值是多少?不就是等于\frac{1}{2}||w||^2么漓摩,而\frac{1}{2}||w||^2同樣也是我們可行解區(qū)域之內(nèi)的目標(biāo)函數(shù)裙士。也就是說(shuō)在可行解區(qū)域之內(nèi),\frac{1}{2}||w||^2就等價(jià)于\mathop{max}\limits_{\alpha>0} \ L(w,b,\alpha)管毙。同理腿椎,我們可以分析得到桌硫,在的可行解區(qū)域之外,此時(shí)\mathop{max}\limits_{\alpha>0} \ L(w,b,\alpha)可區(qū)域無(wú)窮大啃炸。所以沒(méi)有約束的新目標(biāo)函數(shù)的優(yōu)化問(wèn)題就與原來(lái)有約束條件的原始目標(biāo)函數(shù)的優(yōu)化是等價(jià)的問(wèn)題铆隘,即:

\frac{1}{2}||w||^2 \quad => \quad \mathop{max}\limits_{\alpha>0} \ L(w,b,\alpha) \tag{3-6}

  • 疑問(wèn)2:為什么將原問(wèn)題轉(zhuǎn)化為對(duì)偶問(wèn)題之后,在什么樣的條件下南用,才會(huì)滿足d^*= p^*膀钠?

轉(zhuǎn)化為對(duì)偶問(wèn)題之后,要使得d^*= p^*等式成立训枢,則需要滿足如下條件托修,也就是該問(wèn)題成立時(shí)候的KKT條件

\begin{cases} \alpha_i, & i=1,2,3,...,N\\ y_i(w^Tx_i+b)\geq0, & i=1,2,3,...,N\\ \alpha_i(y_i(w^Tx_i+b)-1)=0, & i=1,2,3,...,N\\ \end{cases} \tag{3-7}

前兩個(gè)條件我們不難得到,前面我們也有過(guò)對(duì)其進(jìn)行分析恒界,那么第三個(gè)條件為什么需要滿足呢睦刃?

在介紹支持向量和決策平面的時(shí)候,我們有提到十酣,最終的決策平面只會(huì)與支持向量相關(guān)涩拙,而與其他大多數(shù)樣本數(shù)據(jù)(非支持向量)無(wú)關(guān)。我們不妨來(lái)對(duì)它們分別介紹耸采,當(dāng)樣本點(diǎn)為支持向量的時(shí)候兴泥,此時(shí)y_i(w^Tx_i+b)-1=0,即當(dāng)所取的樣本點(diǎn)為非支持向量的時(shí)候虾宇,要使得\alpha_i(y_i(w^Tx_i+b)-1)=0搓彻,則此時(shí)的\alpha_i=0。所以從整體樣本域來(lái)講嘱朽,只有滿足\alpha_i(y_i(w^Tx_i+b)-1)=0的時(shí)候旭贬,才能到達(dá)目標(biāo)決策平面與支持向量有關(guān),而與其他大多數(shù)非支持向量無(wú)關(guān)搪泳。

綜上稀轨,只有滿足KKT條件的時(shí)候,才能到達(dá)d^*= p^*岸军,即在滿足KKT條件的時(shí)候奋刽,才能將原始目標(biāo)問(wèn)題,轉(zhuǎn)化為對(duì)偶問(wèn)題艰赞,此時(shí)兩者是等價(jià)的佣谐,且此時(shí)的目標(biāo)函數(shù)為內(nèi)層關(guān)于w,b的最小值,而外層是關(guān)于\alpha的最大值方妖,這樣一來(lái)狭魂,大大方便了我們對(duì)目標(biāo)函數(shù)的求解。所以優(yōu)化問(wèn)題,我們轉(zhuǎn)化如下:

\mathop{max}\limits_{\alpha}\ \mathop{min}\limits_{w,b}[\frac{1}{2}||w||^2-\sum^N_{i=1}\alpha_iy_i(w^Tx_i+b) + \sum^N_{i=1}\alpha_i] \tag{3-8}

而要解決這個(gè)優(yōu)化問(wèn)題趁蕊,我們可以分為兩步來(lái)進(jìn)行求解:

  1. 先求內(nèi)層關(guān)于w,b的最小值坞生,此時(shí)我們應(yīng)該將\alpha視為常數(shù)
  2. 再求外層關(guān)于\alpha的最大值,由于經(jīng)過(guò)了第一步關(guān)于w,b的最小值掷伙,這兩個(gè)參數(shù)已經(jīng)被消掉了是己,所以第二步只會(huì)存在關(guān)于\alpha的求解

經(jīng)過(guò)上述對(duì)目標(biāo)函數(shù)的問(wèn)題分析,我們下面根據(jù)上述的兩個(gè)步驟來(lái)手握手式的進(jìn)行求解任柜。

四卒废、模型的求解

關(guān)于拉格朗日的內(nèi)層求解

首先,我們需要對(duì)內(nèi)層的最小值問(wèn)題進(jìn)行求解宙地,即求:

\mathop{min}\limits_{w,b}L(w,b)=\mathop{min}\limits_{w,b}[\frac{1}{2}||w||^2-\sum^N_{i=1}\alpha_iy_i(w^Tx_i+b) + \sum^N_{i=1}\alpha_i] \tag{4-1}

注意摔认,此時(shí)L(w,b)僅僅只是關(guān)于w,b,而\alpha是由外層最大值問(wèn)題進(jìn)行求解的宅粥,在這里當(dāng)做常數(shù)處理即可参袱。根據(jù)例2,我們需要求出L(w,b)關(guān)于w,b的偏導(dǎo)秽梅,我們?cè)谶@假設(shè)每個(gè)樣本含有m個(gè)屬性抹蚀,則x_i=(x_i^{(1)},x_i^{(2)},...,x_i^{(m)})^T企垦,應(yīng)各位“老婆們”的要求环壤,具體求偏導(dǎo)的詳細(xì)過(guò)程如下:

image

為了讓讀者徹底明白上述過(guò)程,所以步驟有點(diǎn)多钞诡,這里就不采用Latex語(yǔ)法來(lái)編輯上述公式的推導(dǎo)過(guò)程了郑现,當(dāng)然了,Taoye會(huì)盡可能地將過(guò)程寫(xiě)的足夠詳細(xì)荧降。上述關(guān)于拉格朗日函數(shù)求偏導(dǎo)的過(guò)程接箫,自認(rèn)為已經(jīng)寫(xiě)的很詳細(xì)了,最主要的是要區(qū)分x誊抛、w的shape問(wèn)題列牺,以及各自代表的意義是什么整陌。對(duì)于上述過(guò)程有不清楚的拗窃,隨時(shí)歡迎聯(lián)系Taoye或在下方留言,也歡迎更多讀者來(lái)訪微信公眾號(hào):玩世不恭的Coder泌辫。

對(duì)此随夸,我們已經(jīng)通過(guò)上面過(guò)程得到L(w,b)關(guān)于w,b偏導(dǎo)所要滿足的式子:

w=\sum_{i=1}^N\alpha_iy_ix_i \\ 0=\sum_{i=1}^N\alpha_iy_i \tag{4-2}

之后,我們將式子(4-2)重新帶回到(4-1)中的最小值問(wèn)題中震放,即可消掉w,b參數(shù)宾毒,也就是說(shuō)得到的式子僅僅只是關(guān)于\alpha,具體代回過(guò)程如下圖所示:

image

上圖就是將對(duì)w,b求導(dǎo)之后所得到的式子待會(huì)L(w,b)的完整過(guò)程殿遂,務(wù)必要好好理解清楚诈铛。

關(guān)于這個(gè)代回的過(guò)程乙各,有兩點(diǎn)還是有必要說(shuō)一下的,這也是前幾天實(shí)驗(yàn)室的同學(xué)存在疑問(wèn)的地方幢竹。(參照上述圖片來(lái)解疑

  • 疑問(wèn)1:這里前一項(xiàng)難道不是和后一項(xiàng)同樣為0么耳峦?因?yàn)椴皇钦f(shuō)了\sum_{i=1}^N\alpha_iy_i=0啊焕毫?蹲坷??

其實(shí)這個(gè)地方的后一項(xiàng)是為0邑飒,而前一項(xiàng)并不一定為0循签。因?yàn)楹笠豁?xiàng)中的b其實(shí)就相當(dāng)于一個(gè)固定的常數(shù),也就是\alpha_iy_i中的每一項(xiàng)所乘的數(shù)都是b疙咸,這樣的話县匠,固定的常數(shù)乘以0,結(jié)果當(dāng)然依然等于0咯撒轮。

而我們?cè)倏纯辞耙豁?xiàng)聚唐,可以發(fā)現(xiàn)前一項(xiàng)中除了\alpha_iy_i之外,還有w^Tx_i的存在腔召,而我們的i是會(huì)隨著樣本的變化而改變的杆查,所以每次乘的數(shù)可能并不一定相同。舉個(gè)例子理解一下吧:2+3-5=0臀蛛,這個(gè)我們都應(yīng)該知道亲桦。當(dāng)我們?cè)?img class="math-inline" src="https://math.jianshu.com/math?formula=2%E3%80%813%E3%80%815" alt="2、3浊仆、5" mathimg="1">的前面同時(shí)乘以一個(gè)相同的數(shù)客峭,這個(gè)等式是依然成立的,然而當(dāng)我在2抡柿、3舔琅、5前面分別乘以一個(gè)并不相同的數(shù),那么這個(gè)等式就不成立了洲劣,比如 2*2+2*3-2*5=0依然成立备蚓,而 2*2+3*3-4*5=0就不成立了。

就是這個(gè)道理囱稽,務(wù)必要好好理解清楚郊尝。

  • 疑問(wèn)2:為什么這一步可以推導(dǎo)至下面那一步呢?战惊?流昏?

其實(shí)這個(gè)問(wèn)題很好理解魏滚,因?yàn)檫@兩個(gè)成績(jī)形式的式子是相互獨(dú)立的奇适,也就是說(shuō)\sum雖然都有i柳爽,但是這兩個(gè)i并不一定是同時(shí)取同一個(gè)值的绽快。這就像一種笛卡爾積的形式,所以將前一個(gè)\sum式子中的i換成j
依然成立刁绒,所以能推導(dǎo)至下面那一步襟锐。。膛锭。

通過(guò)上述過(guò)程粮坞,我們已經(jīng)得到了代回之后的式子,如下:

\mathop{min}\limits_{w,b}L(w,b)=\sum_{i=1}^N\alpha_i-\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N\alpha_i\alpha_jy_iy_jx_i^Tx_i \tag{4-3}

并且我們觀察可以發(fā)現(xiàn)初狰,式子此時(shí)僅僅只存在\alpha莫杈,而w,b已經(jīng)成功被消掉了。注意:上式中的x_i,y_j表示的樣本奢入,也就說(shuō)這些樣本的各個(gè)屬性特征以及標(biāo)簽都是已知的筝闹,所以上式只有\alpha是未知的。

至此腥光,我們已經(jīng)解決了對(duì)偶問(wèn)題的內(nèi)層最小值問(wèn)題关顷,接下來(lái)我們就要求解外層的最大值問(wèn)題了,將最小值的式子代回原對(duì)偶問(wèn)題武福,我們更新下對(duì)偶問(wèn)題议双,得到如下:

\begin{aligned} & \mathop{max}\limits_{\alpha}\ \mathop{min}\limits_{w,b} L(w,b,\alpha) \\ = & \mathop{max}\limits_{\alpha}\ \mathop{min}\limits_{w,b}[\frac{1}{2}||w||^2-\sum^N_{i=1}\alpha_iy_i(w^Tx_i+b) + \sum^N_{i=1}\alpha_i] \tag{4-4} \\ = & \mathop{max}\limits_{\alpha}[\sum_{i=1}^N\alpha_i-\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N\alpha_i\alpha_jy_iy_jx_i^Tx_j] \\ = & \mathop{min}\limits_{\alpha}[\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N\alpha_i\alpha_jy_iy_jx_i^Tx_j-\sum_{i=1}^N\alpha_i] \\ & s.t. \quad \alpha_i\geq0, \quad i=1,2,...,N \\ & \qquad \quad \sum_{i=1}^N\alpha_iy_i=0 \end{aligned}

如上,已經(jīng)將原對(duì)偶轉(zhuǎn)換為了上式的樣子捉片,下面我們據(jù)此再來(lái)看之前的例1


例子來(lái)源:李航-《統(tǒng)計(jì)學(xué)習(xí)方法》第七章內(nèi)容

例子3:已知一個(gè)如圖所示的訓(xùn)練數(shù)據(jù)集平痰,其正例點(diǎn)是x_1=(3, 3)^T,x_2=(4, 3)^T,負(fù)例點(diǎn)為x_3=(1, 1)^T伍纫,試求最大間隔分離的決策面宗雇?

image

根據(jù)所給數(shù)據(jù),其對(duì)偶問(wèn)題是:

\begin{aligned} \mathop{min}\limits_{\alpha} & [\frac{1}{2}\sum_{j=1}^N\alpha_i\alpha_jy_iy_jx_i^Tx_j-\sum_{i=1}^N\alpha_i] \\ & = \frac{1}{2}(18\alpha_1^2+25\alpha_2^2+2\alpha_3^2+42\alpha_1\alpha_2-12\alpha_1\alpha_3-14\alpha_2\alpha_3)-\alpha_1-\alpha_2-\alpha_3 \\ s.t. & \alpha_1+ \alpha_2-\alpha_3=0 \\ & \alpha_1 \geq0, \quad i=1,2,3 \end{aligned}

我們將\alpha_3=\alpha_1+\alpha_2代入到目標(biāo)函數(shù)并記為:

s(\alpha_1,\alpha_2)=4\alpha_1^2+\frac{13}{2}\alpha_2^2+10\alpha_1\alpha_2-2\alpha_1-2\alpha_2
對(duì)\alpha_1,\alpha_2求偏導(dǎo)數(shù)并令其為0莹规,易知s(\alpha_1,\alpha_2)在點(diǎn)(\frac{3}{2},-1)^T取極值赔蒲,但該點(diǎn)不滿足約束條件\alpha_2\geq0,所以最小值應(yīng)在邊界上達(dá)到良漱。

當(dāng)\alpha_1=0時(shí)舞虱,最小值為s(0,\frac{2}{13})=-\frac{2}{13};當(dāng)\alpha_2=0時(shí)债热,最小值s(\frac{1}{4},0)=-\frac{1}{4}砾嫉。所以幼苛,當(dāng)\alpha_1=\frac{1}{4},\alpha_2=0,\alpha_3=\alpha_1+\alpha_2=\frac{1}{4}時(shí)窒篱,此時(shí)s(\alpha_1,\alpha_2)達(dá)到最小。

這樣的話,就說(shuō)明\alpha_1=\alpha_3=\frac{1}{4}所對(duì)應(yīng)的點(diǎn)x_1,x_3就是支持向量了墙杯,根據(jù)w=\sum_{i=1}^N\alpha_iy_ix_i配并,我們可以求得此時(shí)w_1=w_2=\frac{1}{2},再由b=y-\sum_{i=1}^N\alpha_iy_ix_i^Tx高镐,可以得到b=-2

綜上溉旋,我們可以得到?jīng)Q策面最終為:

\frac{1}{2}x^{(1)}+\frac{1}{2}x^{(2)}-2=0

其中,x_1=(3,3)^Tx_3=(1,1)^T為支持向量嫉髓。


歷經(jīng)九九八十一難观腊,終于來(lái)到了這最后一步了,只要我們能求得上式的最小值算行,那么模型的求解也就該到一段落了梧油。

那么,問(wèn)題來(lái)了州邢,關(guān)于上式儡陨,我們應(yīng)當(dāng)如何求解呢?量淌?骗村?

下面就應(yīng)該是我們的重頭戲閃亮登場(chǎng)了——SMO算法,各位看官掌聲歡迎一下呀枢,有請(qǐng)SMO大佬登臺(tái)表演胚股。。裙秋。

基于SMO算法的外層求解

關(guān)于SMO算法信轿,李航老師的《統(tǒng)計(jì)學(xué)習(xí)方法》一書(shū)中是這么描述的,

關(guān)于外層問(wèn)題的求解残吩,我們有許多方法可供使用财忽。當(dāng)我們的數(shù)據(jù)樣本比較少的時(shí)候,可以將支持向量機(jī)的學(xué)習(xí)問(wèn)題轉(zhuǎn)換為凸二次規(guī)劃問(wèn)題泣侮,這樣的凸二次規(guī)劃問(wèn)題具有全局最優(yōu)解即彪,并且有許多最優(yōu)化算法可以用于這一問(wèn)題的求解。但是當(dāng)訓(xùn)練樣本容量很大時(shí)活尊,這些算法往往變得非常低效隶校,以致無(wú)法使用。所以蛹锰,如何高效地實(shí)現(xiàn)支持向量機(jī)學(xué)習(xí)就成為一個(gè)重要的問(wèn)題深胳。目前人們已提出許多快速實(shí)現(xiàn)算法。而在這些算法中铜犬,要數(shù)Platt的序列最小最優(yōu)化(sequential minimal optimization SMO)算法最為人所知舞终。

SMO算法是一種啟發(fā)式算法轻庆,其基本思想是:如果所有變量的解都滿足此最優(yōu)化問(wèn)題的KKT條件,那么這個(gè)最優(yōu)化問(wèn)題的解就得到了敛劝。因?yàn)镵KT條件是該最優(yōu)化問(wèn)題的充分必要條件余爆。否則,選擇兩個(gè)變量夸盟,固定其他變量蛾方,針對(duì)這兩個(gè)變量構(gòu)建一個(gè)二次規(guī)劃問(wèn)題。這個(gè)二次規(guī)劃問(wèn)題關(guān)于這兩個(gè)變量的解就應(yīng)該更接近原始二次規(guī)劃問(wèn)題的解上陕,因?yàn)檫@會(huì)使得原始二次規(guī)劃問(wèn)題的目標(biāo)函數(shù)值變得更小桩砰。更重要的是,這時(shí)子問(wèn)題可以通過(guò)解析方法求解释簿,這樣就可以大大提高整個(gè)算法的計(jì)算速度五芝。子問(wèn)題有兩個(gè)變量,一個(gè)是違反KKT條件最嚴(yán)重的那一個(gè)辕万,另一個(gè)由約束條件自動(dòng)確定枢步。如此,SMO算法將原問(wèn)題不斷分解為子問(wèn)題并對(duì)子問(wèn)題求解渐尿,進(jìn)而達(dá)到求解原問(wèn)題的目的醉途。

上述內(nèi)容來(lái)自李航——《統(tǒng)計(jì)學(xué)習(xí)方法》第二版。

不知道大伙讀完上述關(guān)于內(nèi)容是什么感受砖茸,這里簡(jiǎn)單總結(jié)一下李航老師所表達(dá)的意思吧隘擎。

在Taoye的印象里,小學(xué)時(shí)期上語(yǔ)文課的時(shí)候?qū)W習(xí)過(guò)一篇文章叫做《走一步凉夯,再走一步》货葬。(具體幾年級(jí)就記不清楚了)

嘿!您還別說(shuō)劲够,剛剛?cè)ニ阉髁讼逻@篇課文震桶,還真就叫這個(gè)名兒。第一次讀李航老師《統(tǒng)計(jì)學(xué)習(xí)方法》中關(guān)于SMO的內(nèi)容之后征绎,就讓我想起這篇文章蹲姐。我還專門(mén)重新讀了一下這篇文章,主要講的內(nèi)容是這樣的:

文章中主人公名叫小亨特人柿,他不是天生體弱怯懦嘛柴墩,在一次和小伙伴攀登懸崖的時(shí)候,由于內(nèi)心的恐懼凫岖、害怕江咳,在攀登途中上不去,也下不來(lái)哥放。然后呢歼指,他的小伙伴杰里就把小亨特的父親找來(lái)了爹土,父親對(duì)小亨特說(shuō):“不要想有多遠(yuǎn),有多困難东臀,你需要想的是邁一小步着饥。這個(gè)你能做到犀农《韪常看著手電光指的地方『巧冢看到那塊石頭沒(méi)有赁濒?”,最終通過(guò)父親的鼓勵(lì)孟害,小亨特成功脫險(xiǎn)拒炎。文末作者還總結(jié)道:在我生命中有很多時(shí)刻,每當(dāng)我遇到一個(gè)遙不可及挨务、令人害怕的情境击你,并感到驚慌失措時(shí),我都能夠應(yīng)付——因?yàn)槲一叵肫鹆撕芫靡郧白约荷线^(guò)的那一課谎柄。我提醒自己不要看下面遙遠(yuǎn)的巖石丁侄,而是注意相對(duì)輕松、容易的第一小步朝巫,邁出一小步鸿摇、再一小步,就這樣體會(huì)每一步帶來(lái)的成就感劈猿,直到完成了自己想要完成的拙吉,達(dá)到了自己的目標(biāo),然后再回頭看時(shí)揪荣,不禁對(duì)自己走過(guò)的這段漫漫長(zhǎng)路感到驚訝和自豪筷黔。

把《走一步,再走一步》這篇文章搬出來(lái)仗颈,真的不是在湊字?jǐn)?shù)從而給大家閱讀帶來(lái)壓力必逆,只是覺(jué)得SMO算法描述的就是這么個(gè)理兒。算了揽乱,不多說(shuō)了名眉,說(shuō)多了還真的會(huì)有湊字?jǐn)?shù)的嫌疑。(ノへ ̄凰棉、)

下面我們開(kāi)始進(jìn)入到SMO吧损拢。。撒犀。

在這之前福压,我們把外層的最小值問(wèn)題再搬出來(lái):

\begin{aligned} & \mathop{min}\limits_{\alpha}[\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N\alpha_i\alpha_jy_iy_jx_i^Tx_j-\sum_{i=1}^N\alpha_i] \\ & s.t. \quad \alpha_i\geq0, \quad i=1,2,...,N \\ & \qquad \quad \sum_{i=1}^N\alpha_iy_i=0 \end{aligned} \tag{4-5}

在這里掏秩,我們是假設(shè)對(duì)于所有的樣本數(shù)據(jù)都是100%線性可分的。

對(duì)于該優(yōu)化問(wèn)題的SMO算法荆姆,我們可以這樣理解:因?yàn)樵谖覀兊臄?shù)據(jù)集中蒙幻,x_i屬于每個(gè)樣本的屬性特征,y_i為樣本所對(duì)應(yīng)的標(biāo)簽胆筒,而這些都是已知的邮破,上述優(yōu)化問(wèn)題的目標(biāo)函數(shù)只存在\alpha_i為未知變量,且未知變量有N個(gè)仆救。而根據(jù)SMO算法的思想抒和,我們每次只將其中兩個(gè)\alpha看做變量,而其他\alpha僅僅只是常數(shù)彤蔽。在卻確定其中一個(gè)變量的時(shí)候摧莽,另一個(gè)變量就可以通過(guò)\sum_{i=1}^N\alpha_iy_i=0約束得到。我們不妨將該兩個(gè)變量定為\alpha_1,\alpha_2顿痪,則SMO不斷執(zhí)行如下兩個(gè)步驟直至收斂:

  • 選取一對(duì)需要更新的變量\alpha_1和\alpha_2
  • 固定\alpha_1和\alpha_2以外的參數(shù)镊辕,根據(jù)求解式(4-5)獲得更新后\alpha_1和\alpha_2
  • 更新好\alpha_1和\alpha_2之后,重新選取兩個(gè)\alpha進(jìn)行不斷更新迭代(重復(fù)1蚁袭、2步驟)

講到這里征懈,SMO算法是不是和《走一步,再走一步》中主人公類似呢撕阎?將一個(gè)大的受裹、復(fù)雜的問(wèn)題轉(zhuǎn)換成多個(gè)小問(wèn)題,然后不斷的迭代更新虏束。

為什么我們每次都同時(shí)優(yōu)化兩個(gè)參數(shù)棉饶,而不是一個(gè)呢?因?yàn)槊看胃聝蓚€(gè)參數(shù)镇匀,才能確保\sum_{i=1}^N\alpha_iy_i=0約束條件成立照藻。而當(dāng)我們僅僅只是修改一個(gè)\alpha時(shí),那么就將違背這個(gè)約束條件了汗侵。

據(jù)SMO的思想幸缕,我們不妨把目標(biāo)函數(shù)中的\alpha_1和\alpha_2單獨(dú)拎出來(lái),如下:

image

注意:因?yàn)槲覀兊?img class="math-inline" src="https://math.jianshu.com/math?formula=W(%5Calpha_1%2C%5Calpha_2)" alt="W(\alpha_1,\alpha_2)" mathimg="1">僅僅只是對(duì)\alpha_1晰韵,\alpha_2作為參數(shù)发乔,而\alpha_3,\alpha_4,...,\alpha_N只是作為一個(gè)參數(shù)而存在。還有一點(diǎn)需要注意的是雪猪,因?yàn)槲覀兪嵌诸悊?wèn)題栏尚,且樣本數(shù)據(jù)的標(biāo)簽為非1即-1,所以y_i^2=1只恨,這個(gè)在化簡(jiǎn)過(guò)程中需要用到译仗。此時(shí)我們得到關(guān)于\alpha_1,\alpha_2的目標(biāo)函數(shù)為:

\begin{aligned} W(\alpha_1, \alpha_2)= & \frac{1}{2}K_{11}\alpha_1^2+\frac{1}{2}K_{22}\alpha_2^2+\alpha_1\alpha_2y_1y_2K_{12} -(\alpha_1+\alpha_2) \\ & + y_1\alpha_1\sum_{i=3}^Ny_i\alpha_iK_{1i}+y_2\alpha_2\sum_{i=3}^Ny_i\alpha_iK_{2i} + H \\ & 其中K_{ij}=x_i^Tx_j,H=\sum_{i=3}^N\sum_{j=3}^N\alpha_i\alpha_jy_iy_jx_i^Tx_j^T-\sum_{i=3}^N\alpha_i \end{aligned} \tag{4-6}

我們知道對(duì)于這個(gè)式子是有一個(gè)約束條件的抬虽,我們可以根據(jù)這個(gè)用\alpha_2來(lái)表示\alpha_1(注意:y_i^2=1),如下:

\begin{aligned} & \qquad \sum_{i=1}^N\alpha_iy_i=0 \\ & => \alpha_1y_1+\alpha_2y_2=-\sum_{i=3}^N\alpha_iy_i=G \\ & => \alpha_1=y_1(G-\alpha_2y_2) \end{aligned} \tag{4-7}

通過(guò)上式纵菌,用\alpha_2來(lái)表示\alpha_1阐污,我們不妨將\alpha_1帶到W(\alpha_1,\alpha_2)中,得到一個(gè)只關(guān)于\alpha_2的式子:

\begin{aligned} W(\alpha_2)= & \frac{1}{2}K_{11}(G-\alpha_2y_2)^2+\frac{1}{2}K_{22}\alpha_2^2+\alpha_2(G-\alpha_2y_2)y_2K_{12}\\ & -[y_1(G-\alpha_2y_2) + \alpha_2]+(G-\alpha_2y_2)\sum_{i=3}^Ny_i\alpha_iK_{1i} \\ & + y_2\alpha_2\sum_{i=3}^Ny_i\alpha_iK_{2i}+H \end{aligned} \tag{4-8}

此時(shí)的W(\alpha_2)僅僅只是關(guān)于\alpha_2的函數(shù)咱圆,我們將W(\alpha_2)對(duì)\alpha_2進(jìn)行求導(dǎo)笛辟,并令導(dǎo)數(shù)為0:

image

image

image

上述就是SMO中限制其中兩個(gè)變量的推到過(guò)程的推到過(guò)程(公式太多,過(guò)程有點(diǎn)復(fù)雜闷堡,確實(shí)不方便使用Latex語(yǔ)法隘膘,不過(guò)過(guò)程都已經(jīng)寫(xiě)的很詳細(xì)了疑故,還是需要靜下心來(lái)慢慢手動(dòng)推導(dǎo)的)下面總結(jié)一下上述SMO算法的過(guò)程吧:

前面我們不是得到了僅僅關(guān)于\alpha_2為變量的W(\alpha_2)么杠览,也就是說(shuō)此時(shí)的未知數(shù)只有一個(gè),我們要求W(\alpha_2)的最值應(yīng)該怎么求呢纵势?當(dāng)然是對(duì)其進(jìn)行求導(dǎo)咯踱阿,然后對(duì)導(dǎo)數(shù)為0,即可解出W(\alpha_2)取最值時(shí)候的\alpha_2钦铁,整理之后得到如下式子:

(K_{11}+K_{22}-2K_{12})\alpha_2=y_2(y_2-y_1+GK_{11}-GK_{12}+\sum_{i=3}^N\alpha_iy_iK_{1i}-\sum_{i=3}^N\alpha_iy_iK_{2i}) \tag{4-9}

此時(shí)软舌,我們可以發(fā)現(xiàn)除了數(shù)據(jù)樣本相關(guān)信息和\alpha_2之外,還有G的存在牛曹,而我們前面也又說(shuō)到佛点,SMO算法本身是一個(gè)不斷迭代更新的過(guò)程,我們需要的是可以通過(guò)的更新之前的\alpha_2來(lái)修改\alpha_2黎比,從而得到一個(gè)新的\alpha_2超营,我們不妨令新的\alpha\alpha^{new}、舊的\alpha\alpha^{old}阅虫。而我們知道舊的\alpha之間需要滿足一個(gè)限制條件:

\alpha_1^{old}y_1 + \alpha_2^{old}y_2=G \tag{4-9}

所以演闭,我們重新將G代回到(4-9)式,用\alpha_1^{old}颓帝、\alpha_2^{old}來(lái)代替G米碰,(要時(shí)刻注意:y_i^2=1)得到:

\begin{aligned} (K_{11}+K_{22}-2K_{12})\alpha_2^{new}= & y_2(y_2-y_1+\alpha_1^{old}y_1K_{11}+\alpha_2^{old}y_2K_{11} \\ & -\alpha_1^{old}y_1K_{12}-\alpha_2^{old}y_2K_{12} \\ & + \sum_{i=3}^N\alpha_iy_iK_{1i}-\sum_{i=3}^N\alpha_iy_iK_{2i}) \end{aligned} \tag{4-10}

之后我們通過(guò)前面拉格朗日得到的關(guān)系式,用f(x_1)购城、f(x_2)來(lái)代替(4-10)后面的兩個(gè)級(jí)數(shù)吕座,整理最終得到:
\begin{aligned} & \alpha_2^{new}=\frac{y_2(E_1-E_2)}{\eta}+\alpha_2^{old} \\ & \alpha_2^{new}=y_1(G-\alpha_2^{new}y_2) \end{aligned} \tag{4-11}

PS:關(guān)于\eta、E_1瘪板、E_2是什么吴趴,請(qǐng)見(jiàn)上圖中的內(nèi)容。

通過(guò)如上式子篷帅,我們就能求得更新之后的\alpha_1史侣、\alpha_2拴泌,而SMO算法的核心在于兩兩不斷的更新迭代,所以最終我們會(huì)得到惊橱,每個(gè)樣本x_i蚪腐、y_i都會(huì)對(duì)應(yīng)一個(gè)\alpha_i,而前面我們也有說(shuō)過(guò)税朴,決策面最終只會(huì)與支持向量有關(guān)回季,而與非支持向量的樣本無(wú)關(guān),所以大多數(shù)的\alpha_i都等于0正林,只有少數(shù)\alpha_i為非0泡一。如此一來(lái),我們就能求解得到\alpha向量:\alpha=(\alpha_1,\alpha_2,...,\alpha_N)觅廓,隨后鼻忠,我們就能通過(guò)\alpha_i、x_i杈绸、y_i就能求得參數(shù)w

w=\sum_{i=1}^N\alpha_iy_ix_i

還有一點(diǎn)需要注意的是醉拓,上述過(guò)程都是默認(rèn)所有樣本數(shù)據(jù)都是線性可分的裳朋,也就是說(shuō)沒(méi)有一個(gè)樣本會(huì)被誤分類。但這只是理想狀態(tài)下,而實(shí)際不免會(huì)有個(gè)別數(shù)據(jù)不得不被誤分類屹堰,這時(shí)我們需要定義懲罰參數(shù)和容錯(cuò)率涵叮,而容錯(cuò)率是用來(lái)不斷優(yōu)化\alpha的萌踱,主要通過(guò)實(shí)際值與真實(shí)值得到厌漂。而懲罰參數(shù)我們定為C,而要想成功更新得到\alpha_2^{new}烧栋,則需要確定\alpha_2^{new}的范圍写妥。對(duì)此,我們不妨定義如下:

0\leq\alpha_i\leq C ,\qquad i=1,2,3,...,N\\ L\leq\alpha_2^{new}\leq R \tag{4-12}

而我們知道:

\alpha_1^{new}y_1+\alpha_2^{new}y_2=\alpha_1^{old}y_1+\alpha_2^{old}y_2=G \tag{4-13}

綜合上式劲弦,可以確定L耳标、R的范圍:

L=max(0, \alpha_2^{old}-\alpha_1^{old}),R=min(C,C+\alpha_2^{old}-\alpha_1^{old}) \quad y_1 \neq y_2\\ L=max(0, \alpha_2^{old}+\alpha_1^{old}-C),R=min(C,\alpha_2^{old}+\alpha_1^{old})\quad y_1=y_2 \tag{4-14}

而這個(gè)在不同情況下的L,R的范圍,我們會(huì)在下面實(shí)際編程的時(shí)候需要用到邑跪,主要是用來(lái)更新\alpha值次坡。

接下來(lái),就是更新b值了画畅。前面我們已經(jīng)定義了懲罰參數(shù)C砸琅,且0\leq\alpha_i^{new} \leq C,此時(shí)通過(guò)E_1轴踱、E_2更新得到的b_1症脂、b_2固然是相等的;但假如我們更新之后的\alpha不在這個(gè)區(qū)間之內(nèi),則此時(shí)得到的b_1诱篷、b_2是不相等的壶唤,所以我們需要確定在不同情況下更新之后的b值:

前面,我們已經(jīng)得到:

y_1=\sum_{i=1}^N\alpha_iy_ix_ix_1+b

因?yàn)槲覀兪谴蛩阃ㄟ^(guò)\alpha_1^{new}棕所、\alpha_2^{new}的值來(lái)得到更新之后的b^{new}闸盔,所以把\alpha_1^{new}、\alpha_2^{new}單獨(dú)拎出來(lái)琳省,得到:

b_1^{new}=y_1-\sum_{i=3}^N\alpha_iy_ix_i^Tx_1-\alpha_1^{new}y_1x_1^Tx_1-\alpha_2^{new}y_2x_2^Tx_1 \tag{4-15}

同時(shí)迎吵,因?yàn)樯鲜鲋械募?jí)數(shù)形式可以使用E_1和b^{old}來(lái)表示,所以整理之后得:

b_1^{new}=b^{old}-E_1-y_1(\alpha_1^{new}-\alpha_1^{old})x_1^Tx_1-y_2(\alpha_2^{new}-\alpha_2^{old})x_2^Tx_1 \tag{4-16}

同理针贬,可以得到b_2^{new}

b_2^{new}=b^{old}-E_2-y_1(\alpha_1^{new}-\alpha_1^{old})x_1^Tx_1-y_2(\alpha_2^{new}-\alpha_2^{old})x_2^Tx_2 \tag{4-17}

當(dāng)更新之后的\alpha_1^{new}击费、\alpha_2^{new}都有效的時(shí)候,即在[0-C]區(qū)間之內(nèi)時(shí)桦他,此時(shí)b^{new}=b_1^{new}=b_2^{new}蔫巩,而在不滿足上述條件的時(shí)候,我們更新之后的b^{new}b_1和b_2的均值瞬铸,即:

b^{new} = \begin{cases} b_1^{new}, & 0\leq\alpha_1^{new}\leq C \\ b_2^{new}, & 0\leq\alpha_1^{new}\leq C \\ \frac{b_1^{new}+b_2^{new}}{2}, & 其他 \\ \end{cases} \tag{4-18}

如此一來(lái)批幌,我們就已經(jīng)完成了SMO算法的流程础锐,該有的參數(shù)都已經(jīng)求解出來(lái)了嗓节。

說(shuō)實(shí)話,寫(xiě)到這皆警,Taoye的確有點(diǎn)累了拦宣,腦細(xì)胞也嚴(yán)重不足了,但為了各位“老婆們”的正常閱讀信姓,還是得繼續(xù)寫(xiě)下去才行鸵隧。

下面,我們就通過(guò)編程來(lái)實(shí)現(xiàn)線性SVM算法吧R馔啤(本次手撕SVM的數(shù)據(jù)集依然采用我們前面所隨機(jī)創(chuàng)建的)

五豆瘫、編程手撕線性SVM

在前面,我們其實(shí)已經(jīng)實(shí)現(xiàn)了線性SVM的分類菊值,只不過(guò)那個(gè)時(shí)候使用的是sklearn內(nèi)置的接口外驱。但既然是手撕SVM,當(dāng)然是需要自己來(lái)實(shí)現(xiàn)這一功能的腻窒。

在這里需要提前說(shuō)明的是昵宇,上述代碼大量使用到了NumPy操作,關(guān)于NumPy的使用儿子,可自行參考之前寫(xiě)的一篇文章:print( "Hello瓦哎,NumPy!" )

訓(xùn)練SVM模型,沒(méi)數(shù)據(jù)集可不行蒋譬,本次手撕SVM的數(shù)據(jù)集依然采用我們前面所隨機(jī)創(chuàng)建割岛,對(duì)此,我們定義一個(gè)etablish_data方法來(lái)隨機(jī)創(chuàng)建一個(gè)SVM二分類數(shù)據(jù)集:

"""
    Author: Taoye
    微信公眾號(hào): 玩世不恭的Coder
    Explain: 用于生成訓(xùn)練數(shù)據(jù)集
    Parameters:
        data_number: 樣本數(shù)據(jù)數(shù)目
    Return:
        x_data: 數(shù)據(jù)樣本的屬性矩陣
        y_label: 樣本屬性所對(duì)應(yīng)的標(biāo)簽
"""
def etablish_data(data_number):
    x_data = np.concatenate((np.add(np.random.randn(data_number, 2), [3, 3]),       
                             np.subtract(np.random.randn(data_number, 2), [3, 3])),
                             axis = 0)      # random隨機(jī)生成數(shù)據(jù)犯助,+ -3達(dá)到不同類別數(shù)據(jù)分隔的目的 
    temp_data = np.zeros([data_number])
    temp_data.fill(-1)
    y_label = np.concatenate((temp_data, np.ones([data_number])), axis = 0)
    return x_data, y_label

前面蜂桶,我們?cè)谥v解SMO算法的時(shí)候提到,每次都會(huì)選取隨機(jī)兩個(gè)\alpha來(lái)進(jìn)行更新也切,這里我們不妨將第一個(gè)\alpha_i通過(guò)遍歷的形式逐個(gè)選取扑媚,而另一個(gè)則通過(guò)np.random模塊來(lái)隨機(jī)選取,這里需要主要的是雷恃,第二個(gè)選取的\alpha_j不能與第一個(gè)相同疆股。為此,我們定義一個(gè)方法random_select_alpha_j來(lái)隨機(jī)選取第二個(gè)\alpha_j(第一個(gè)已經(jīng)通過(guò)遍歷得到):

"""
    Author: Taoye
    微信公眾號(hào): 玩世不恭的Coder
    Explain: 隨機(jī)選取alpha_j
    Parameters:
        alpha_i_index: 第一個(gè)alpha的索引
        alpha_number: alpha總數(shù)目
    Return:
        alpha_j_index: 第二個(gè)alpha的索引
"""
def random_select_alpha_j(alpha_i_index, alpha_number):
    alpha_j_index = alpha_i_index
    while alpha_j_index == alpha_i_index:
        alpha_j_index = np.random.randint(0, alpha_number)
    return alpha_j_index

我們知道倒槐,每一個(gè)更新之后的\alpha_j^{new}都需要滿足L\leq\alpha_j^{new}\leq R旬痹。為此,我們定義一個(gè)方法modify_alpha來(lái)確定\alpha在區(qū)間之內(nèi):

"""
    Author: Taoye
    微信公眾號(hào): 玩世不恭的Coder
    Explain: 使得alpha_j在[L, R]區(qū)間之內(nèi)
    Parameters:
        alpha_j: 原始alpha_j
        L: 左邊界值
        R: 右邊界值
    Return:
        L,R,alpha_j: 修改之后的alpha_j
"""
def modify_alpha(alpha_j, L, R):
    if alpha_j < L: return L
    if alpha_j > R: return R
    return alpha_j

我們模型訓(xùn)練是一個(gè)迭代更新的過(guò)程讨越,而更新的前提是誤差比較大两残,所以我們需要定義一個(gè)方法calc_E_i來(lái)計(jì)算誤差,但誤差又怎么計(jì)算呢把跨?這一點(diǎn)其實(shí)我們?cè)谧铋_(kāi)始就已經(jīng)提到過(guò)了人弓,誤差是通過(guò)模型計(jì)算出來(lái)的值與其真實(shí)值最差得到,也就是前面提到的E_j下面的推導(dǎo)務(wù)必要理解清楚着逐,矩陣變換要十分熟悉):

\begin{aligned} f(x_j) & =w^Tx_j+b \\ & = \sum_{i=1}^N\alpha_iy_ix_i^Tx_j+b \\ & = \alpha_1y_1x_1^Tx_j+\alpha_2y_2x_2^Tx_j+...+\alpha_Ny_Nx_N^Tx_j+b \\ & = (\alpha_1y_1,\alpha_2y_2,...,\alpha_Ny_N)\left( \begin{matrix} x_1^Tx_j\\ x_2^Tx_j \\ \vdots\\ x_N^Tx_j \\ \end{matrix} \right)+b \\ & = [\left( \begin{matrix} \alpha_1\\ \alpha_2 \\ \vdots\\ \alpha_N \\ \end{matrix} \right) \cdot \left( \begin{matrix} y_1\\ y_2 \\ \vdots\\ y_N \\ \end{matrix} \right)]^T*xx_j^T+b \end{aligned} \tag{5-1}

E_i=f(x_i)-y_i \tag{5-2}

根據(jù)上述誤差的推導(dǎo)崔赌,我們現(xiàn)在就可以通過(guò)代碼來(lái)計(jì)算誤差了(上面的推導(dǎo)務(wù)必要理解清楚,矩陣變換要十分熟悉耸别,才能理解下面代碼所表達(dá)的含義):

"""
    Author: Taoye
    微信公眾號(hào): 玩世不恭的Coder
    Explain: 計(jì)算誤差并返回
"""
def calc_E(alphas, y_lable, x_data, b, i):
    f_x_i = float(np.multiply(alphas, y_lable).T * (x_data * x_data[i, :].T)) + b
    return f_x_i - float(y_label[i])

同樣的健芭,我們把其他一些用于整體代換的單獨(dú)拎出來(lái),并通過(guò)方法進(jìn)行返回秀姐,除了上述的誤差E_i之外慈迈,還有\eta和b,相關(guān)推導(dǎo)過(guò)程讀者可自行根據(jù)上述E_i來(lái)進(jìn)行(一定要會(huì))省有,相關(guān)公式和代碼如下:

\begin{aligned} & \eta = K_{ii}+K_{jj}-2K_{ij} \\ & b_i^{new}=b^{old}-E_i-y_i(\alpha_i^{new}-\alpha_i^{old})x_i^Tx_i-y_j(\alpha_j^{new}-\alpha_j^{old})x_j^Tx_i\\ & b_j^{new}=b^{old}-E_j-y_i(\alpha_i^{new}-\alpha_i^{old})x_i^Tx_i-y_j(\alpha_j^{new}-\alpha_j^{old})x_j^Tx_j \tag{5-3} \end{aligned}

"""
    Author: Taoye
    微信公眾號(hào): 玩世不恭的Coder
    Explain: 計(jì)算eta并返回
"""
def calc_eta(x_data, i, j):
    eta = 2.0 * x_data[i, :] * x_data[j, :].T \
            - x_data[i, :] * x_data[i, :].T \
            - x_data[j, :] * x_data[j,:].T
    return eta
    
"""
    Author: Taoye
    微信公眾號(hào): 玩世不恭的Coder
    Explain: 計(jì)算b1, b2并返回
"""
def calc_b(b, x_data, y_label, alphas, alpha_i_old, alpha_j_old, E_i, E_j, i, j):
    b1 = b - E_i \
         - y_label[i] * (alphas[i] - alpha_i_old) * x_data[i, :] * x_data[i, :].T \
         - y_label[j] * (alphas[j] - alpha_j_old) * x_data[i, :] * x_data[j, :].T
    b2 = b - E_j \
         - y_label[i] * (alphas[i] - alpha_i_old) * x_data[i, :] * x_data[j, :].T \
         - y_label[j] * (alphas[j] - alpha_j_old) * x_data[j, :] * x_data[j, :].T
    return b1, b2

OK痒留,準(zhǔn)備工作已經(jīng)完成了,接下來(lái)是時(shí)候放出我們的核心SMO算法的代碼了锥咸,大家可根據(jù)前面的SMO思想來(lái)理解狭瞎,下面代碼也會(huì)放出詳細(xì)的注釋來(lái)幫助大家理解:

"""
    Author: Taoye
    微信公眾號(hào): 玩世不恭的Coder
    Explain: SMO核心算法,求得b和laphas向量
    Parameters:
        x_data: 樣本屬性特征矩陣
        y_label: 屬性特征對(duì)應(yīng)的標(biāo)簽
        C:懲罰參數(shù)
        toler:容錯(cuò)率
        max_iter:迭代次數(shù)
    Return:
        b: 決策面的參數(shù)b
        alphas:獲取決策面參數(shù)w所需要的alphas
"""
def linear_smo(x_data, y_label, C, toler, max_iter):
    x_data = np.mat(x_data); y_label = np.mat(y_label).T     # 將數(shù)據(jù)轉(zhuǎn)換為矩陣類型
    m, n = x_data.shape                                      # 得到數(shù)據(jù)樣本的shape信息
    b, alphas, iter_num = 0, np.mat(np.zeros((m, 1))), 0     # 初始化參數(shù)b和alphas和迭代次數(shù)
    while (iter_num < max_iter):                            # 最多迭代max_iter次
        alpha_optimization_num = 0   # 定義優(yōu)化次數(shù)
        for i in range(m):          # 遍歷每個(gè)樣本搏予,一次選取一個(gè)樣本計(jì)算誤差
            E_i = calc_E(alphas, y_label, x_data, b, i)      # 樣本i的誤差計(jì)算
            if ((y_label[i] * E_i < -toler) and (alphas[i] < C)) or ((y_label[i] * E_i > toler) and (alphas[i] > 0)):
                j = random_select_alpha_j(i, m)              # 隨機(jī)選取一個(gè)不與i重復(fù)j
                E_j = calc_E(alphas, y_label, x_data, b, j)  # 計(jì)算樣本j的誤差
                alpha_i_old = alphas[i].copy(); alpha_j_old = alphas[j].copy();
                if (y_label[i] != y_label[j]):               # 重新規(guī)范alphas的左右區(qū)間
                    L, R = max(0, alphas[j] - alphas[i]), min(C, C + alphas[j] - alphas[i])
                else:
                    L, R = max(0, alphas[j] + alphas[i] - C), min(C, alphas[j] + alphas[i])
                if L == R: print("L==R"); continue          # L==R時(shí)選取下一個(gè)樣本
                eta = calc_eta(x_data, i, j)                  # 計(jì)算eta值
                if eta >= 0: print("eta>=0"); continue
                alphas[j] -= y_label[j] * (E_i - E_j) / eta
                alphas[j] = modify_alpha(alphas[j], L, R)     # 修改alpha[j]
                if (abs(alphas[j] - alpha_j_old) < 0.00001): print("alpha_j更改太小"); continue
                alphas[i] += y_label[j] * y_label[i] * (alpha_j_old - alphas[j])    # 修改alphas[i]
                b1, b2= calc_b(b, x_data, y_label, alphas, alpha_i_old, alpha_j_old, E_i, E_j, i, j)    # 計(jì)算b值
                if (0 < alphas[i]) and (C > alphas[i]): b = b1
                elif (0 < alphas[j]) and (C > alphas[j]): b = b2
                else: b = (b1 + b2)/2.0
                alpha_optimization_num += 1
                print("迭代次數(shù):%d熊锭,樣本:%d,alphas向量的優(yōu)化次數(shù):%d" % (iter_num, i+1, alpha_optimization_num))
        if (alpha_optimization_num == 0): iter_num += 1
        else: iter_num = 0
        print("迭代次數(shù):%d" % iter_num)
    return b, alphas

上述SMO核心方法,我們可以通過(guò)定義輸入樣本的屬性特征碗殷、標(biāo)簽以及迭代次數(shù)等來(lái)得到\alphab精绎。隨后,我們可以通過(guò)w\alpha之間的關(guān)系來(lái)的計(jì)算出w锌妻,關(guān)系和相關(guān)代碼如下所示:

w=\sum_{i=1}^N\alpha_iy_ix_i \tag{5-4}

"""
    Author: Taoye
    微信公眾號(hào): 玩世不恭的Coder
    Explain: 根據(jù)公式計(jì)算出w權(quán)值向量
    Parameters:
        x_data: 樣本屬性特征矩陣
        y_label: 屬性特征對(duì)應(yīng)的標(biāo)簽
        alphas:linear_smo方法所返回的alphas向量
    Return:
        w: 決策面的參數(shù)w
"""
def calc_w(x_data, y_label, alphas):
    x_data, y_label, alphas = np.array(x_data), np.array(y_label), np.array(alphas)
    return np.dot((np.tile(y_label.reshape(1, -1).T, (1, 2)) * x_data).T, alphas).tolist()

好的代乃,b有了,w也有了仿粹,該有的都有了搁吓,接下來(lái)就是驗(yàn)證模型效果了,這里我們使用Matplotlib來(lái)繪制吭历,定義一個(gè)plot_result方法來(lái)展示模型分類結(jié)果:

import pylab as pl

"""
    Author: Taoye
    微信公眾號(hào): 玩世不恭的Coder
    Explain: 繪制出分類結(jié)果
    Parameters:
        x_data: 樣本屬性特征矩陣
        y_label: 屬性特征對(duì)應(yīng)的標(biāo)簽
        w:決策面的w參數(shù)
        b:決策面的參數(shù)b
"""
def plot_result(x_data, y_label, w, b):
    data_number, _ = x_data.shape; middle = int(data_number / 2)
    plt.scatter(x_data[:, 0], x_data[:, 1], c = y_label, cmap = pl.cm.Paired)
    x1, x2 = np.max(x_data), np.min(x_data)
    w1, w2 = w[0][0], w[1][0]
    y1, y2 = (-b - w1 * x1) / w2, (-b - w1 * x2) / w2
    plt.plot([float(x1), float(x2)], [float(y1), float(y2)])    # 繪制決策面
    for index, alpha in enumerate(alphas):
        if alpha > 0:
            b_temp = - w1 * x_data[index][0] - w2 * x_data[index][1]
            y1_temp, y2_temp = (-b_temp - w1 * x1) / w2, (-b_temp - w1 * x2) / w2
            plt.plot([float(x1), float(x2)], [float(y1_temp), float(y2_temp)], "k--")    # 繪制支持向量
            plt.scatter(x_data[index][0], x_data[index][1], s=150, c='none', alpha=0.7, linewidth=2, edgecolor='red')   # 圈出支持向量
    plt.show()

if __name__ == "__main__":
    x_data, y_label = etablish_data(50)
    b, alphas = linear_smo(x_data, y_label, 0.8, 0.0001, 40)
    w = calc_w(x_data, y_label, alphas)
    plot_result(x_data, y_label, w, b)
繪制分類結(jié)果

完整代碼:

import numpy as np
import pylab as pl
from matplotlib import pyplot as plt

class TearLinearSVM:
    def __init__(self):
        pass

    """
        Author: Taoye
        微信公眾號(hào): 玩世不恭的Coder
        Explain: 用于生成訓(xùn)練數(shù)據(jù)集
        Parameters:
            data_number: 樣本數(shù)據(jù)數(shù)目
        Return:
            x_data: 數(shù)據(jù)樣本的屬性矩陣
            y_label: 樣本屬性所對(duì)應(yīng)的標(biāo)簽
    """
    def etablish_data(self, data_number):
        x_data = np.concatenate((np.add(np.random.randn(data_number, 2), [3, 3]),       
                                 np.subtract(np.random.randn(data_number, 2), [3, 3])),
                                 axis = 0)      # random隨機(jī)生成數(shù)據(jù)堕仔,+ -3達(dá)到不同類別數(shù)據(jù)分隔的目的 
        temp_data = np.zeros([data_number])
        temp_data.fill(-1)
        y_label = np.concatenate((temp_data, np.ones([data_number])), axis = 0)
        return x_data, y_label

    """
        Author: Taoye
        微信公眾號(hào): 玩世不恭的Coder
        Explain: 隨機(jī)選取alpha_j
        Parameters:
            alpha_i_index: 第一個(gè)alpha的索引
            alpha_number: alpha總數(shù)目
        Return:
            alpha_j_index: 第二個(gè)alpha的索引
    """
    def random_select_alpha_j(self, alpha_i_index, alpha_number):
        alpha_j_index = alpha_i_index
        while alpha_j_index == alpha_i_index:
            alpha_j_index = np.random.randint(0, alpha_number)
        return alpha_j_index

    """
        Author: Taoye
        微信公眾號(hào): 玩世不恭的Coder
        Explain: 使得alpha_j在[L, R]區(qū)間之內(nèi)
        Parameters:
            alpha_j: 原始alpha_j
            L: 左邊界值
            R: 右邊界值
        Return:
            L,R,alpha_j: 修改之后的alpha_j
    """
    def modify_alpha(self, alpha_j, L, R):
        if alpha_j < L: return L
        if alpha_j > R: return R
        return alpha_j

    """
        Author: Taoye
        微信公眾號(hào): 玩世不恭的Coder
        Explain: 計(jì)算誤差并返回
    """
    def calc_E(self, alphas, y_lable, x_data, b, i):
        f_x_i = float(np.dot(np.multiply(alphas, y_lable).T, x_data * x_data[i, :].T)) + b
        return f_x_i - float(y_label[i])

    """
        Author: Taoye
        微信公眾號(hào): 玩世不恭的Coder
        Explain: 計(jì)算eta并返回
    """
    def calc_eta(self, x_data, i, j):
        eta = 2.0 * x_data[i, :] * x_data[j, :].T \
                - x_data[i, :] * x_data[i, :].T \
                - x_data[j, :] * x_data[j,:].T
        return eta

    """
        Author: Taoye
        微信公眾號(hào): 玩世不恭的Coder
        Explain: 計(jì)算b1, b2并返回
    """
    def calc_b(self, b, x_data, y_label, alphas, alpha_i_old, alpha_j_old, E_i, E_j, i, j):
        b1 = b - E_i \
             - y_label[i] * (alphas[i] - alpha_i_old) * x_data[i, :] * x_data[i, :].T \
             - y_label[j] * (alphas[j] - alpha_j_old) * x_data[i, :] * x_data[j, :].T
        b2 = b - E_j \
             - y_label[i] * (alphas[i] - alpha_i_old) * x_data[i, :] * x_data[j, :].T \
             - y_label[j] * (alphas[j] - alpha_j_old) * x_data[j, :] * x_data[j, :].T
        return b1, b2

    """
        Author: Taoye
        微信公眾號(hào): 玩世不恭的Coder
        Explain: SMO核心算法,求得b和laphas向量
        Parameters:
            x_data: 樣本屬性特征矩陣
            y_label: 屬性特征對(duì)應(yīng)的標(biāo)簽
            C:懲罰參數(shù)
            toler:容錯(cuò)率
            max_iter:迭代次數(shù)
        Return:
            b: 決策面的參數(shù)b
            alphas:獲取決策面參數(shù)w所需要的alphas
    """
    def linear_smo(self, x_data, y_label, C, toler, max_iter):
        x_data = np.mat(x_data); y_label = np.mat(y_label).T     # 將數(shù)據(jù)轉(zhuǎn)換為矩陣類型
        m, n = x_data.shape                                      # 得到數(shù)據(jù)樣本的shape信息
        b, alphas, iter_num = 0, np.mat(np.zeros((m, 1))), 0     # 初始化參數(shù)b和alphas和迭代次數(shù)
        while (iter_num < max_iter):                            # 最多迭代max_iter次
            alpha_optimization_num = 0   # 定義優(yōu)化次數(shù)
            for i in range(m):          # 遍歷每個(gè)樣本晌区,一次選取一個(gè)樣本計(jì)算誤差
                E_i = self.calc_E(alphas, y_label, x_data, b, i)      # 樣本i的誤差計(jì)算
                if ((y_label[i] * E_i < -toler) and (alphas[i] < C)) or ((y_label[i] * E_i > toler) and (alphas[i] > 0)):
                    j = self.random_select_alpha_j(i, m)              # 隨機(jī)選取一個(gè)不與i重復(fù)j
                    E_j = self.calc_E(alphas, y_label, x_data, b, j)  # 計(jì)算樣本j的誤差
                    alpha_i_old = alphas[i].copy(); alpha_j_old = alphas[j].copy();
                    if (y_label[i] != y_label[j]):               # 重新規(guī)范alphas的左右區(qū)間
                        L, R = max(0, alphas[j] - alphas[i]), min(C, C + alphas[j] - alphas[i])
                    else:
                        L, R = max(0, alphas[j] + alphas[i] - C), min(C, alphas[j] + alphas[i])
                    if L == R: print("L==R"); continue          # L==R時(shí)選取下一個(gè)樣本
                    eta = self.calc_eta(x_data, i, j)                  # 計(jì)算eta值
                    if eta >= 0: print("eta>=0"); continue
                    alphas[j] -= y_label[j] * (E_i - E_j) / eta
                    alphas[j] = self.modify_alpha(alphas[j], L, R)     # 修改alpha[j]
                    if (abs(alphas[j] - alpha_j_old) < 0.00001): print("alpha_j更改太小"); continue
                    alphas[i] += y_label[j] * y_label[i] * (alpha_j_old - alphas[j])    # 修改alphas[i]
                    b1, b2= self.calc_b(b, x_data, y_label, alphas, alpha_i_old, alpha_j_old, E_i, E_j, i, j)    # 計(jì)算b值
                    if (0 < alphas[i]) and (C > alphas[i]): b = b1
                    elif (0 < alphas[j]) and (C > alphas[j]): b = b2
                    else: b = (b1 + b2)/2.0
                    alpha_optimization_num += 1
                    print("迭代次數(shù):%d摩骨,樣本:%d,alphas向量的優(yōu)化次數(shù):%d" % (iter_num, i+1, alpha_optimization_num))
            if (alpha_optimization_num == 0): iter_num += 1
            else: iter_num = 0
            print("迭代次數(shù):%d" % iter_num)
        return b, alphas

    """
        Author: Taoye
        微信公眾號(hào): 玩世不恭的Coder
        Explain: 根據(jù)公式計(jì)算出w權(quán)值向量
        Parameters:
            x_data: 樣本屬性特征矩陣
            y_label: 屬性特征對(duì)應(yīng)的標(biāo)簽
            alphas:linear_smo方法所返回的alphas向量
        Return:
            w: 決策面的參數(shù)w
    """
    def calc_w(self, x_data, y_label, alphas):
        x_data, y_label, alphas = np.array(x_data), np.array(y_label), np.array(alphas)
        return np.dot((np.tile(y_label.reshape(1, -1).T, (1, 2)) * x_data).T, alphas).tolist()

    """
        Author: Taoye
        微信公眾號(hào): 玩世不恭的Coder
        Explain: 繪制出分類結(jié)果
        Parameters:
            x_data: 樣本屬性特征矩陣
            y_label: 屬性特征對(duì)應(yīng)的標(biāo)簽
            w:決策面的w參數(shù)
            b:決策面的參數(shù)b
    """
    def plot_result(self, x_data, y_label, w, b):
        data_number, _ = x_data.shape; middle = int(data_number / 2)
        plt.scatter(x_data[:, 0], x_data[:, 1], c = y_label, cmap = pl.cm.Paired)
        x1, x2 = np.max(x_data), np.min(x_data)
        w1, w2 = w[0][0], w[1][0]
        y1, y2 = (-b - w1 * x1) / w2, (-b - w1 * x2) / w2
        plt.plot([float(x1), float(x2)], [float(y1), float(y2)])    # 繪制決策面
        
        for index, alpha in enumerate(alphas):
            if alpha > 0:
                b_temp = - w1 * x_data[index][0] - w2 * x_data[index][1]
                y1_temp, y2_temp = (-b_temp - w1 * x1) / w2, (-b_temp - w1 * x2) / w2
                plt.plot([float(x1), float(x2)], [float(y1_temp), float(y2_temp)], "k--")    # 繪制支持向量
                plt.scatter(x_data[index][0], x_data[index][1], s=150, c='none', alpha=0.7, linewidth=2, edgecolor='red')   # 圈出支持向量
        plt.show()

if __name__ == '__main__':
    linear_svm = TearLinearSVM()
    x_data, y_label = linear_svm.etablish_data(50)
    b, alphas = linear_svm.linear_smo(x_data, y_label, 0.8, 0.0001, 40)
    w = linear_svm.calc_w(x_data, y_label, alphas)
    linear_svm.plot_result(x_data, y_label, w, b)

呼呼呼朗若!可算是結(jié)束了恼五,做個(gè)小總結(jié)吧。

SVM是學(xué)習(xí)機(jī)器學(xué)習(xí)必然接觸到的一個(gè)重要算法哭懈,所以一定要對(duì)其內(nèi)在原理了解清楚灾馒,并不是說(shuō)一定要手撕SVM的完整代碼,但最起碼使用框架的時(shí)候要了解內(nèi)部都做了什么“小動(dòng)作”银伟,不要為了用而用你虹。

本文介紹了線性SVM的算法原理,主要分為了五個(gè)部分的內(nèi)容彤避。一、首先通過(guò)參考比較權(quán)威的書(shū)籍以及優(yōu)秀資料對(duì)SVM做了一個(gè)比較“良心”的介紹夯辖,讓讀者對(duì)SVM有一個(gè)比較宏觀的概念琉预,這小子(SVM)究竟是誰(shuí)?竟如此騷氣蒿褂,讓不少研究者拜倒其石榴裙下圆米。二、其次向讀者介紹了線性SVM以及最大間隔啄栓,這部分也是手撕SVM必須要掌握的一些基本概念娄帖,并且最終得到了SVM最初的優(yōu)化問(wèn)題。三昙楚、利用拉格朗日乘數(shù)法構(gòu)建最值問(wèn)題近速,將優(yōu)化問(wèn)題中的約束問(wèn)題集成到了目標(biāo)函數(shù)本身,之后利用拉格朗日的對(duì)偶性,將最初的優(yōu)化問(wèn)題轉(zhuǎn)化成了內(nèi)層關(guān)于w削葱、b的最小值奖亚,外層關(guān)于\alpha的對(duì)偶問(wèn)題。四析砸、對(duì)偶問(wèn)題的求解昔字,這也是SVM算法的最核心內(nèi)容,先是對(duì)內(nèi)層關(guān)于w首繁、b的函數(shù)求導(dǎo)作郭,然后代回原式,從而消掉w,b參數(shù)弦疮,只留下未知的\alpha所坯,隨后利用SMO算法求得迭代更新之后的\alpha。五挂捅、手撕線性SVM的代碼實(shí)現(xiàn)芹助,結(jié)果證明,分類的效果還不錯(cuò)闲先,這是個(gè)好家伙W赐痢!伺糠!

說(shuō)實(shí)話蒙谓,這篇文章有點(diǎn)肝,也是挪用了不少其他任務(wù)的時(shí)間训桶。

這篇文章僅僅只是手撕線性SVM累驮,也就是說(shuō)大多數(shù)據(jù)樣本都可以被正確分類,但在實(shí)際中舵揭,許多的數(shù)據(jù)集都是線性不可分的谤专,這個(gè)時(shí)候可能就要引入核函數(shù)的概念了。關(guān)于非線性SVM午绳,我們留在之后再來(lái)肝置侍。。拦焚。

本文參考了不少書(shū)籍資料以及許多大佬的技術(shù)文章蜡坊,行文風(fēng)格盡可能做到了通俗易懂,但其中涉及到的數(shù)學(xué)公式在所難免赎败,還請(qǐng)諸讀者靜下心來(lái)慢慢品嘗秕衙。由于個(gè)人水平有限,才疏學(xué)淺僵刮,對(duì)于SVM也只是略知皮毛据忘,可能文中有不少表述稍有欠妥鹦牛、有不少錯(cuò)誤或不當(dāng)之處,還請(qǐng)諸君批評(píng)指正若河,有任何問(wèn)題歡迎在下方留言能岩。

我是Taoye,愛(ài)專研萧福,愛(ài)分享拉鹃,熱衷于各種技術(shù),學(xué)習(xí)之余喜歡下象棋鲫忍、聽(tīng)音樂(lè)膏燕、聊動(dòng)漫,希望借此一畝三分地記錄自己的成長(zhǎng)過(guò)程以及生活點(diǎn)滴悟民,也希望能結(jié)實(shí)更多志同道合的圈內(nèi)朋友坝辫,更多內(nèi)容歡迎來(lái)訪微信公主號(hào):玩世不恭的Coder

參考資料:

<font style="font-size:13px;opacity:0.7">[1] 《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》:Peter Harrington 人民郵電出版社</font>
<font style="font-size:13px;opacity:0.7">[2] 《統(tǒng)計(jì)學(xué)習(xí)方法》:李航 第二版 清華大學(xué)出版社</font>
<font style="font-size:13px;opacity:0.7">[3] 《機(jī)器學(xué)習(xí)》:周志華 清華大學(xué)出版社</font>
<font style="font-size:13px;opacity:0.7">[4] 《微積分方法》:李億民 中國(guó)海洋出版社</font>
<font style="font-size:13px;opacity:0.7">[5] Support Vector Machines explained well(翻墻):http://bytesizebio.net/2014/02/05/support-vector-machines-explained-well/</font>
<font style="font-size:13px;opacity:0.7">[6] 關(guān)于更為直觀認(rèn)識(shí)SVM的video(翻墻):https://www.youtube.com/watch?v=3liCbRZPrZA</font>
<font style="font-size:13px;opacity:0.7">[7] 支持向量機(jī)(SVM)是什么意思?:https://www.zhihu.com/question/21094489/answer/86273196</font>
<font style="font-size:13px;opacity:0.7">[8] 看了這篇文章你還不懂SVM你就來(lái)打我:https://zhuanlan.zhihu.com/p/49331510</font>
<font style="font-size:13px;opacity:0.7">[9] 拉格朗日乘數(shù)法:https://www.cnblogs.com/maybe2030/p/4946256.html</font>

推薦閱讀

print( "Hello射亏,NumPy近忙!" )
干啥啥不行,吃飯第一名
Taoye滲透到一家黑平臺(tái)總部智润,背后的真相細(xì)思極恐
《大話數(shù)據(jù)庫(kù)》-SQL語(yǔ)句執(zhí)行時(shí)及舍,底層究竟做了什么小動(dòng)作?
那些年窟绷,我們玩過(guò)的Git锯玛,真香
基于Ubuntu+Python+Tensorflow+Jupyter notebook搭建深度學(xué)習(xí)環(huán)境
網(wǎng)絡(luò)爬蟲(chóng)之頁(yè)面花式解析
手握手帶你了解Docker容器技術(shù)
一文詳解Hexo+Github小白建站
?打開(kāi)ElasticSearch、kibana兼蜈、logstash的正確方式

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末攘残,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子为狸,更是在濱河造成了極大的恐慌歼郭,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钥平,死亡現(xiàn)場(chǎng)離奇詭異实撒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)涉瘾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)捷兰,“玉大人立叛,你說(shuō)我怎么就攤上這事」泵” “怎么了秘蛇?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵其做,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我赁还,道長(zhǎng)妖泄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任艘策,我火速辦了婚禮蹈胡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘朋蔫。我一直安慰自己罚渐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布驯妄。 她就那樣靜靜地躺著荷并,像睡著了一般。 火紅的嫁衣襯著肌膚如雪青扔。 梳的紋絲不亂的頭發(fā)上源织,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音微猖,去河邊找鬼谈息。 笑死,一個(gè)胖子當(dāng)著我的面吹牛励两,可吹牛的內(nèi)容都是我干的黎茎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼当悔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼傅瞻!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起盲憎,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嗅骄,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后饼疙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體溺森,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年窑眯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了屏积。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡磅甩,死狀恐怖炊林,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卷要,我是刑警寧澤渣聚,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布独榴,位于F島的核電站,受9級(jí)特大地震影響奕枝,放射性物質(zhì)發(fā)生泄漏棺榔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一隘道、第九天 我趴在偏房一處隱蔽的房頂上張望症歇。 院中可真熱鬧,春花似錦薄声、人聲如沸当船。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)德频。三九已至,卻和暖如春缩幸,著一層夾襖步出監(jiān)牢的瞬間壹置,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工表谊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钞护,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓爆办,卻偏偏與公主長(zhǎng)得像难咕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子距辆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容