机器学习--有监督--支持向量机SVM

支持向量机Support vector machine,SVM是一种有监督的机器学习算法,可用于分类或者回归。本次笔记以分类任务为例主要学习。

1、简单理解

  • 假设对于特征空间的样本坐标分,以样本标签为目的,存在一个超平面,将样本分为两大类,从而最大化区分两类样本。该超平面即为决策边界,而间隔就是指训练数据中最接近决策边界的样本点与决策边界之间的距离。

  • SVM过程:以间隔最大化为目的,让决策边界尽可能远离样本。然后根据这个决策边界进行样本分类预测。
    根据样本数据的复杂程度,SVM建模的过程也有所不同,具体可分为如下三类

1.1 线性可分--硬间隔

hard margin classifier,HML:此类样本数据是最简单的情况,即数据集样本可以明显地使用线性边界区分开。可参考下图,分为3个步骤

  • step1:为每个类别的分布情况绘制出外轮廓多边形;
  • step2:找出连接两个轮廓最近的两个数据点,连接;
  • step3:绘制出该连线的垂直平分线,即为最优的决策边界。而连线长度的一半即为间隔(M)

HML的特点是不允许有样本点位于间隔区内,即必须干净的划分;即不能有样本距决策边界的距离比间隔的长度还短,甚至在决策边界的另一端(误分类)

1.2 线性不可完全分--软间隔

  • 当两个类别的边界不是很明显,或者存在离群点时,如严格按照HMC,会使模型过拟合,泛化能力降低。


  • soft margin classifier,SML通过设置超参数 C表示允许间隔内存在样本的数目,优化决策边界,提高模型的泛化能力。如上所示,左图为C=0的硬间隔方法;右图为C取最大值的分类结果;
  • 针对当前数据集,可交叉验证不同C取值下的模型性能,从而确定最佳的指标。

1.3 线性不可分-核技巧

  • 上述例子数据集的决策平面都是线性的。当决策边界是一个曲线等复杂模式时,使用上述的方法无法得到满意的分类效果;

  • 针对此类情况,支持向量机可通过核方法(kernel method)寻找到合适的非线性决策边界。可分为两个步骤:



    (1)将线性不可分的数据(n个特征向量,n维)增加一个维度(enlarged kernel-induced feature space),从而成为线性可分数据(n+1)维;
    (2)在n+1 维的空间里确定合适的决策边界(线性);然后投射到原来n维空间中,即得到我们真正需要的决策平面(非线性)

  • 常见的核方法有:Radial basis function(径向基函数)、d-th degree polynomial、Hyperbolic tangent等,但通常建议使用径向基函数(extremely flexible)试一试。该方法的超参数,除了C值外,还有一个sigma,在下面代码实操中会介绍到。

2、代码实操

(1)示例数据:预测员工是否离职

library(modeldata)
data(attrition)
# initial dimension
dim(attrition)
## [1] 1470   31
library(dplyr)
df <- attrition %>%
  mutate_if(is.ordered, factor, ordered = FALSE)
# Create training (70%) and test (30%) sets
set.seed(123) # for reproducibility
library(rsample)
churn_split <- initial_split(df, prop = 0.7, strata = "Attrition")
churn_train <- training(churn_split)
churn_test <- testing(churn_split)

(2)caret包建模

  • 如上,我们使用径向基函数的核方法寻找非线性决策边界,从而建立支持向量机模型。
  • 对于超参数σ,会自动根据样本数据寻找最合适的值;对超参数C,可以通过交叉验证选择,一般备选方案为2的指数系列值(2e-2, 2e-1,2e0,2e1,2e2...)
library(caret)
set.seed(1111) # for reproducibility
# Control params for SVM
ctrl <- trainControl(
  method = "cv",
  number = 10,
  classProbs = TRUE,  #表示返回分类概率,而不是直接分类标签结果
  summaryFunction = twoClassSummary # also needed for AUC/ROC
)

churn_svm <- train(
  Attrition ~ .,
  data = churn_train,
  method = "svmRadial",
  preProcess = c("center", "scale"),
  trControl = ctrl,
  metric = "ROC", # area under ROC curve (AUC)
  tuneLength = 10) #遍历C的10次取值,即从2的-2次方到2的7次方

#如下 C取4时,模型最优
churn_svm$results %>% arrange(desc(ROC)) %>% head(1)
#     sigma C       ROC      Sens      Spec      ROCSD     SensSD     SpecSD
# 1 0.009522278 4 0.8234039 0.9791767 0.2738971 0.07462533 0.02019714 0.08679811

# Plot results
ggplot(churn_svm) 
(3)测试集验证
pred = predict(churn_svm, churn_test)
table(pred)
# pred
# No Yes 
# 415  27
table(churn_test$Attrition)
# No Yes 
# 370  72
caret::confusionMatrix(pred, churn_test$Attrition, positive="Yes")
# Accuracy : 0.871           
# 95% CI : (0.8362, 0.9008)
# No Information Rate : 0.8371          
# P-Value [Acc > NIR] : 0.02819         
# 
# Kappa : 0.3681          
# 
# Mcnemar's Test P-Value : 5.611e-09       
#                                           
#             Sensitivity : 0.29167         
#             Specificity : 0.98378         
#          Pos Pred Value : 0.77778         
#          Neg Pred Value : 0.87711         
#              Prevalence : 0.16290         
#          Detection Rate : 0.04751         
#    Detection Prevalence : 0.06109         
#       Balanced Accuracy : 0.63773         
#                                           
#        'Positive' Class : Yes

(4)衡量特征重要性

  • SVM算法本身不提供有衡量特征重要性的计算方法;
  • 可使用vip包提供的permutation test置换检验的方法,随机调整某一列(特征)值的顺序,观察预测准确率是否明显下降,从而判断特征变量的重要性。
library(vip)
prob_yes <- function(object, newdata) {
  predict(object, newdata = newdata, type = "prob")[, "Yes"]
}
# Variable importance plot
set.seed(2827) # for reproducibility
vip(churn_svm, method = "permute", nsim = 5, train = churn_train,
    target = "Attrition", metric = "auc", reference_class = "Yes",
    pred_wrapper = prob_yes)
  • pdp包观察具体某一个特征变量对于预测结果的影响
library(pdp)
features <- c("OverTime", "JobRole")
pdps <- lapply(features, function(x) {
  partial(churn_svm, pred.var = x, which.class = 2,
          prob = TRUE, plot = TRUE, plot.engine = "ggplot2") +
    coord_flip()
})
grid.arrange(grobs = pdps, nrow = 1)

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,809评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,189评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,290评论 0 359
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,399评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,425评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,116评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,710评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,629评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,155评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,261评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,399评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,068评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,758评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,252评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,381评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,747评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,402评论 2 358

推荐阅读更多精彩内容