【機(jī)器學(xué)習(xí)(五)】支持向量機(jī)

支持向量機(jī)的一般原理

【機(jī)器學(xué)習(xí)】支持向量機(jī) SVM(非常詳細(xì))

支持向量機(jī)(SVW,support vector machine)跟邏輯回歸比較像⊙可以說脑融,支持向量機(jī)是邏輯回歸的一種優(yōu)化或者擴(kuò)展。因此赁炎,雖然說支持向量機(jī)既可以處理分類問題擎场,也可以處理回歸問題瞒御,但是它一般還是主要用于分類問題父叙。而且其本質(zhì)是處理二元分類問題

簡(jiǎn)單說肴裙,支持向量機(jī)就是找到個(gè)(決策)邊界(或者理解成分界線趾唱,或超平面),既能將兩個(gè)分類進(jìn)行完美的區(qū)分蜻懦,又能使得該邊界距離兩個(gè)分類之間的間距達(dá)到最大甜癞。(因?yàn)橹挥虚g距最大,才更具有魯棒性宛乃,分類器的效果才最好)悠咱。

1.最大邊緣分類

邊緣(margin)
數(shù)據(jù)集中任何一點(diǎn)到該超平面的最小正交距離
最大邊緣超平面
尋找一條直線蒸辆,可以分隔兩個(gè)類別,盡可能遠(yuǎn)離觀測(cè)數(shù)據(jù)

如何找到這個(gè)“超平面”?

邏輯回歸中析既,因?yàn)閿?shù)據(jù)要分成兩類躬贡,用0,1來進(jìn)行的兩類區(qū)分眼坏。而且為了最后使得

的值能落在0拂玻,1之間,引入了邏輯函數(shù)

宰译,并且給g(z)賦予了一個(gè)意義檐蚜,即代表了分類結(jié)果為1時(shí)的概率。函數(shù)值越靠近1沿侈,代表分類結(jié)果為1的可能性越大闯第。函數(shù)值越靠近0,代表分類結(jié)果為0的可能性越大缀拭。
此外咳短,hθ(x)只和θTx有關(guān),θTx>0智厌,那么hθ(x)>0.5诲泌,而g(z)只是用來映射盲赊,真實(shí)的類別決定權(quán)還是在于θTx铣鹏。
當(dāng)θTx>>0時(shí),hθ(x)=1哀蘑,反之hθ(x)=0诚卸。如果只從θTx出發(fā),希望模型達(dá)到的目標(biāo)就是讓訓(xùn)練數(shù)據(jù)中y=1的特征θTx>>0绘迁,而是y=0的特征θTx<<0合溺。Logistic回歸就是要學(xué)習(xí)得到θ,使得正例的特征遠(yuǎn)大于0缀台,負(fù)例的特征遠(yuǎn)小于0棠赛,而且要在全部訓(xùn)練實(shí)例上達(dá)到這個(gè)目標(biāo)。

在svm中膛腐,對(duì)上述邏輯回歸稍微做一點(diǎn)點(diǎn)調(diào)整睛约。首先,還是講數(shù)據(jù)分為兩類哲身,但是用-1辩涝,1來進(jìn)行區(qū)分。因此勘天,引入一個(gè)新的g(z)怔揩,能夠使得映射后的值落在[-1,1] 之間捉邢。

注意,這個(gè)新的映射函數(shù)g(z) 是一個(gè)分段函數(shù)商膊,而不是之前在邏輯回歸中的連續(xù)函數(shù)伏伐。換言之,在進(jìn)行分類的時(shí)候晕拆,遇到一個(gè)新的數(shù)據(jù)點(diǎn)x秘案,將x代入f(x) 中,如果f(x)小于0則將x的類別賦為-1潦匈,如果f(x)大于0則將x的類別賦為1阱高。

假設(shè)已經(jīng)找到了這個(gè)超平面,用

表示茬缩。一定會(huì)滿足如下幾點(diǎn):
1)在分類為1的所有樣本中赤惊,一定存在一個(gè)點(diǎn),其距離超平面的距離最近凰锡。設(shè)為x0未舟;
2)在分類為-1的所有樣本中,一定存在一個(gè)點(diǎn)掂为,其距離超平面的距離最近裕膀。設(shè)為x1;
3)將x0帶入到上面的式子中勇哗,得到的f(x0)昼扛,一定大于0。且其他所有分類為1的樣本點(diǎn)欲诺,都有f(xn)≥f(x0)抄谐;
4) 同理,將x1帶入到上面的式子中扰法,得到的f(x1)蛹含,一定小于0。且其他所有分類為-1的樣本點(diǎn)塞颁,都有f(xm)≤f(x1)浦箱;
5)對(duì)于x0或者x1到超平面f(x) 的函數(shù)距離|f(x0)|,|f(x1)|祠锣,無論是多少酷窥,都不會(huì)影響超平面f(x)=0的存在。即锤岸,如果成比例的改變w和b竖幔,函數(shù)距離|f(x0)|,|f(x1)|也會(huì)成比例改變是偷,但是拳氢,對(duì)于要求解的超平面是不會(huì)有影響的募逞;

6)根據(jù)點(diǎn)到直線的距離公式,可以知道x0到超平面f(x) 的幾何距離為:|f(x0)|/||w||馋评。(x1是一樣的)放接,其中

所以,SVM的目標(biāo)函數(shù)為:

2.軟邊緣(soft margin)

允許某些觀測(cè)數(shù)據(jù)可以違反距離分隔超平面至少要和邊緣一樣遠(yuǎn)的約束條件

其中:

相比于硬間隔的苛刻條件留特,允許個(gè)別樣本點(diǎn)出現(xiàn)在間隔帶里面纠脾。允許部分樣本點(diǎn)不滿足約束條件:

可以引入一個(gè)松弛變量εi,令εi≥0蜕青,即


增加軟邊緣后我們的優(yōu)化目標(biāo)變成了:

這里的C苟蹈,就跟之前過擬合中的λ一樣,是一個(gè)懲罰因子右核。如果C設(shè)的很大慧脱,ε就會(huì)很小,就相當(dāng)于是硬邊緣贺喝,要求完全線形可分菱鸥。反之,如果C設(shè)得比較小躏鱼,ε就會(huì)相對(duì)較大氮采,此時(shí)將會(huì)允許有跟多的樣本點(diǎn)不滿足約束條件。

3.核函數(shù)

還有一些數(shù)據(jù)沒法直接用一條直線分開染苛,這類數(shù)據(jù)叫做非線性可分?jǐn)?shù)據(jù)鹊漠。比如下圖,一維數(shù)據(jù)紅點(diǎn)和藍(lán)點(diǎn)位于同一條線上殖侵,找不到分界點(diǎn)將紅點(diǎn)和藍(lán)點(diǎn)分開贸呢。


對(duì)于這種問題,如果用函數(shù)f(x)=x2來映射這幾個(gè)數(shù)據(jù)拢军,增加一個(gè)維度,將一維數(shù)據(jù)轉(zhuǎn)換為二維數(shù)據(jù)怔鳖,紅點(diǎn)就變成(-1, 1)和(1, 1)茉唉,而藍(lán)點(diǎn)變成(-3, 9)和(3, 9)。這樣紅點(diǎn)和藍(lán)點(diǎn)就變成線性可分的结执,可以很容易地找到?jīng)Q策邊界度陆。

所以,可以將低維空間中的非線性可分離數(shù)據(jù)献幔,映射到高維空間懂傀,就可能得到線性可分離數(shù)據(jù)。
這就如同在邏輯回歸中提到的一樣蜡感,可以使用高級(jí)數(shù)的多項(xiàng)式模型來解決無法用直線進(jìn)行分隔的分類問題:

為了獲得上圖所示的判定邊界蹬蚁,模型可能是

的形式恃泪。

但是這里有個(gè)問題:原來的特征是低維的,人為的構(gòu)造了一些特征犀斋,讓其變成高維的了贝乎。那到底要如何構(gòu)造特征,才能確保到了高維后叽粹,一定線形可分呢览效?

如何構(gòu)造新的特征?介紹一個(gè)新的構(gòu)造特征的思路:即引入某種函數(shù)虫几,這些函數(shù)用來計(jì)算當(dāng)前訓(xùn)練樣本與給定標(biāo)記之間的相似度锤灿。如果給定了5個(gè)標(biāo)記,那么就會(huì)構(gòu)造出5個(gè)新的特征辆脸。這些變換過的特征衡招,代表當(dāng)前所有訓(xùn)練樣本,與這5個(gè)標(biāo)記之間的相似程度每强。這就是核函數(shù)的思想始腾。

那么,如何選定標(biāo)記呢空执? 一個(gè)最簡(jiǎn)單的做法浪箭,即是將訓(xùn)練集的所有樣本作為標(biāo)記。一條樣本代表一個(gè)標(biāo)記辨绊,有m個(gè)樣本奶栖,就有m個(gè)標(biāo)記。那么轉(zhuǎn)換后的特征就有m個(gè)(實(shí)際是m+1個(gè)门坷,這里不考慮截距項(xiàng))宣鄙。要做的事情,就是用交叉驗(yàn)證或者測(cè)試集或者直接再用訓(xùn)練集來計(jì)算出m個(gè)特征的參數(shù)θ默蚌。

核函數(shù)的作用就是接收低維空間的輸入向量冻晤,能夠計(jì)算出在高維空間里的向量點(diǎn)積。

4.預(yù)測(cè)化學(xué)品的生物降解

  • 數(shù)據(jù)集:biodeg.csv
  • 41個(gè)數(shù)值型變量绸吸,1055種化學(xué)品的分子組成
  • V42包含輸出鼻弧,不可生物降解NRB,可生物降解RB
  • 使用e1071包锦茁,svm函數(shù)
    設(shè)置scale=TRUE攘轩,輸入特征歸一化

在R中進(jìn)行支持向量機(jī)的模型預(yù)測(cè)比較簡(jiǎn)單憎兽,可以直接使用e1071包的svm函數(shù)即可實(shí)現(xiàn)延窜。

#導(dǎo)入數(shù)據(jù),預(yù)測(cè)化學(xué)品的生物降解
bdf <- read.table("biodeg.csv", sep=";", quote="\"")
head(bdf, n = 3) #查看數(shù)據(jù)定鸟,有41個(gè)特征稿存。第42列包含輸出笨篷,不可生物降解為NRB瞳秽,可生物降解為RB
#將第42列因子化
bdf$V42 <- factor(bdf$V42)
#將第42列變?yōu)?,1
levels(bdf$V42)<-c(0,1)

#區(qū)分測(cè)試集和訓(xùn)練集
library(caret)
library(tidyverse)
set.seed(23419002)
bdf_sampling_vector <- createDataPartition(bdf$V42, p = 0.80, list = FALSE)
bdf_train <- bdf[bdf_sampling_vector,]
bdf_test <- bdf[-bdf_sampling_vector,]

#區(qū)分測(cè)試集和訓(xùn)練集
library(e1071)
#用支持向量機(jī)來進(jìn)行模型構(gòu)建冕屯。kernel核函數(shù)寂诱,此處為線性核函數(shù);cost代表?yè)p失函數(shù)的值安聘,即之前講到的C
model_lin<-svm(V42~.,data=bdf_train,kernel="linear",cost=10)
model_lin$fitted #查看訓(xùn)練后的結(jié)果

#計(jì)算訓(xùn)練后的模型準(zhǔn)確度痰洒。可以看到浴韭,在訓(xùn)練集上有87.9%的準(zhǔn)確率丘喻。
mean(bdf_train[,42] == model_lin$fitted)
#查看混淆矩陣
table(actual = bdf_train[,42],predictions = model_lin$fitted) 

#在測(cè)試集上進(jìn)行預(yù)測(cè)
test_predictions <- predict(model_lin,bdf_test[,1:41])
#查看測(cè)試集的準(zhǔn)確度
mean(bdf_test[,42] == test_predictions)

可以看到,測(cè)試集上的準(zhǔn)確度達(dá)到了91.9%念颈。

這里有個(gè)問題泉粉。cost到底取多少算合適呢?所以榴芳,面臨一個(gè)參數(shù)調(diào)優(yōu)的問題嗡靡。參數(shù)調(diào)優(yōu),可以手工來進(jìn)行窟感,也可也自動(dòng)來進(jìn)行讨彼。
先看手工方式(線性核kernel="linear"):

#定義一函數(shù),用于計(jì)算不同cost下的準(zhǔn)確度
getAccuraciesOfLinearSVM<-function(cost) {
#線性核只需要控制cost柿祈,根據(jù)給定參數(shù)cost來擬合模型
model_lin<-svm(V42~.,data=bdf_train,kernel="linear",cost=cost)
#計(jì)算訓(xùn)練集的準(zhǔn)確度哈误。signif用于數(shù)據(jù)截取函數(shù),digits表示保留3位小數(shù) 
  train_accuracy <- signif(mean(bdf_train[,42] == model_lin$fitted), digits = 3)
  test_predictions <- predict(model_lin,bdf_test[,1:41]) #預(yù)測(cè)測(cè)試集
  test_accuracy <- signif(mean(bdf_test[,42] == test_predictions), digits = 3) #計(jì)算測(cè)試集準(zhǔn)確度
  return(list(training=train_accuracy, test=test_accuracy))
}

#手工取c為0.01, 0.1, 1, 10, 100, 1000這幾個(gè)數(shù)躏嚎,觀察效果
cost <- c(0.01, 0.1, 1, 10, 100, 1000)
linearPerformances <- sapply(cost, getAccuraciesOfLinearSVM)
colnames(linearPerformances) <- cost #給輸出結(jié)果取個(gè)列名
linearPerformances 

徑向核Radial Kernel蜜自,需要指定gamma

#徑向核指定gamma
model_radial<-svm(V42~., data=bdf_train, kernel="radial", cost=10, gamma=0.5)

mean(bdf_train[,42] == model_radial$fitted)
table(actual = bdf_train[,42],predictions = model_radial$fitted)

test_predictions <- predict(model_radial,bdf_test[,1:41])
mean(bdf_test[,42] == test_predictions)

定義一函數(shù),用于計(jì)算不同cost/gamma下的準(zhǔn)確度

getAccuraciesOfRadialSVM<-function(cost, gamma) {
  
  model_radial<-svm(V42~.,data=bdf_train,kernel="radial",cost=cost, gamma=gamma)
  train_accuracy <- signif(mean(bdf_train[,42] == model_radial$fitted), digits = 3)
  test_predictions <- predict(model_radial,bdf_test[,1:41])
  test_accuracy <- signif(mean(bdf_test[,42] == test_predictions), digits = 3)
  return(list(training=train_accuracy, test=test_accuracy))
}

cost <- c(0.01, 0.1, 1, 10, 100)
gamma <- c(0.01, 0.05, 0.1, 0.5, 1)
grid_params <- expand.grid(cost, gamma)
radialPerformances_u <- mapply(getAccuraciesOfRadialSVM, 
                               grid_params[,1], grid_params[,2])
radialPerformances <- t(data.frame(cost = grid_params[,1], 
                                   gamma = grid_params[,2], 
                                   t(radialPerformances_u)))
radialPerformances
library(caret)
# tune交叉檢驗(yàn)
bdf_radial_tune <- tune(svm,V42~.,data=bdf_train, kernel="radial", 
                        ranges = list(cost=c(0.01,0.1,1,10,100), 
                                      gamma=c(0.01,0.05,0.1,0.5,1)))

還可以使用caret包中的tune來自動(dòng)完成調(diào)參工作卢佣。

預(yù)測(cè)信用評(píng)分

  • 對(duì)銀行來說重荠,把一位高風(fēng)險(xiǎn)客戶錯(cuò)誤分類成為低風(fēng)險(xiǎn)客戶的成本比把一位低風(fēng)險(xiǎn)客戶錯(cuò)誤分類成為高風(fēng)險(xiǎn)客戶的成本要高5倍
    如:銀行發(fā)放了無法償還的貸款
    錯(cuò)過了能夠產(chǎn)生利息的貸款
  • svm()函數(shù)有一個(gè)class.weights參數(shù)
    指定把一條觀測(cè)數(shù)據(jù)錯(cuò)誤分類到每個(gè)類別的成本
#讀取數(shù)據(jù)(信貸數(shù)據(jù))
german_raw <- read.table("german.data", quote="\"")

#重新命名列名
names(german_raw) <- c("checking", "duration", "creditHistory", "purpose", "credit", "savings", "employment", "installmentRate", "personal", "debtors", "presentResidence", "property", "age", "otherPlans", "housing", "existingBankCredits", "job", "dependents", "telephone", "foreign", "risk")

library(caret)
#將一些因子變量變?yōu)樘摂M變量,同時(shí)將risk因子化珠漂,且變?yōu)?和1(之前是1和2)
dummies <- dummyVars(risk ~ ., data = german_raw)
german<- data.frame(predict(dummies, newdata = german_raw), risk=factor((german_raw$risk-1)))

#劃分訓(xùn)練集和測(cè)試集
set.seed(977)
german_sampling_vector <- createDataPartition(german$risk, p = 0.80, list = FALSE)
german_train <- german[german_sampling_vector,]
german_test <- german[-german_sampling_vector,]

#這里增加了權(quán)重晚缩。在信貸問題上,如果把一個(gè)高風(fēng)險(xiǎn)客戶識(shí)別為低風(fēng)險(xiǎn)客戶媳危,對(duì)銀行有可能造成較大損失,反之則不然冈敛。因此這里要對(duì)分類結(jié)果增加權(quán)重待笑。
#把分類為低風(fēng)險(xiǎn)客戶設(shè)置為5,高風(fēng)險(xiǎn)客戶設(shè)置為1抓谴,分到低風(fēng)險(xiǎn)客戶的懲罰項(xiàng)是高風(fēng)險(xiǎn)客戶的5倍
#結(jié)果會(huì)偏向于盡可能的被分為高風(fēng)險(xiǎn)客戶
class_weights <- c(1,5)
names(class_weights) <- c("0","1")
class_weights

set.seed(2423)
#使用tune進(jìn)行自動(dòng)調(diào)參
german_radial_tune <- tune(svm,risk~.,data=german_train, kernel="radial", ranges = list(cost=c(0.01,0.1,1,10,100), 
                           gamma=c(0.01,0.05,0.1,0.5,1)),
                           class.weights = class_weights)

#查看調(diào)參后的最優(yōu)參數(shù)組合
german_radial_tune$best.parameters
#在最優(yōu)參數(shù)組合下的性能
german_radial_tune$best.performance

#根據(jù)調(diào)參得到的最優(yōu)模型在測(cè)試集上進(jìn)行預(yù)測(cè)暮蹂,可以看到寞缝,在測(cè)試集上有75%的準(zhǔn)確率
german_model <- german_radial_tune$best.model
test_predictions <- predict(german_model,german_test[,1:61])
mean(test_predictions == german_test[,62])
table(predicted = test_predictions, actual = german_test[,62])

set.seed(2423)
#不設(shè)權(quán)重的結(jié)果
german_radial_tune_unbiased <- tune(svm,risk~.,data=german_train, kernel="radial", ranges = list(cost=c(0.01,0.1,1,10,100), gamma=c(0.01,0.05,0.1,0.5,1)))
german_radial_tune_unbiased$best.parameters
german_radial_tune_unbiased$best.performance
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市仰泻,隨后出現(xiàn)的幾起案子荆陆,更是在濱河造成了極大的恐慌,老刑警劉巖集侯,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件被啼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡棠枉,警方通過查閱死者的電腦和手機(jī)浓体,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辈讶,“玉大人命浴,你說我怎么就攤上這事〖” “怎么了生闲?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)月幌。 經(jīng)常有香客問我碍讯,道長(zhǎng),這世上最難降的妖魔是什么飞醉? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任冲茸,我火速辦了婚禮,結(jié)果婚禮上缅帘,老公的妹妹穿的比我還像新娘轴术。我一直安慰自己,他們只是感情好钦无,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布逗栽。 她就那樣靜靜地躺著,像睡著了一般失暂。 火紅的嫁衣襯著肌膚如雪彼宠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天弟塞,我揣著相機(jī)與錄音凭峡,去河邊找鬼。 笑死决记,一個(gè)胖子當(dāng)著我的面吹牛摧冀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼索昂,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼建车!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起椒惨,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤缤至,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后康谆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體领斥,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年秉宿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了戒突。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡描睦,死狀恐怖膊存,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情忱叭,我是刑警寧澤隔崎,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站韵丑,受9級(jí)特大地震影響爵卒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撵彻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一钓株、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧陌僵,春花似錦轴合、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至偎谁,卻和暖如春总滩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巡雨。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工闰渔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人铐望。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓澜建,卻偏偏與公主長(zhǎng)得像向挖,于是被迫代替她去往敵國(guó)和親蝌以。 傳聞我的和親對(duì)象是個(gè)殘疾皇子炕舵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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