1、SVM相关#
基本概念#
- 超平面:比数据集的变量少一个维度的平面,也称为决策边界;
- 间隔:(对于硬间隔)训练数据中最接近决策边界的样本点与决策边界之间的距离;
- 支持向量:(对于硬间隔)接触间隔边界的数据样本,它们是支持超平面的位置。(对于软间隔)间隔内的样本点也属于支持向量,因为移动它们也会改变超平面的位置。
如下图所示,SVM算法将寻找一个最优的线性超平面进行分类。
超参数类别#
1、间隔与cost超参数#
(1)如上图所示的间隔内没有样本点,是比较理想的超平面。
(2)当类别并不能完美的分隔开,如果一味追求上述的结果,可能造成过拟合,甚至无法找到超平面。
(3)cost(C)超参数用于表示对间隔内存在的样本的惩罚。cost越大,代表越不允许间隔内存在样本,容易过拟合;cost越小,代表间隔内的样本数据就越多,容易欠拟合。
2、核函数与kernel超参数#
如果当前维度的数据找不到一个合适线性超平面,SVM通过核方法会引入一个新的维度,使变得线性可分。
常见的核方法有:多项式核函数、高斯径向基核函数、sigmoid核函数等
3、gamma超参数#
- gamma超参数越大,表明单个样本对决策边界的位置影响越大,导致决策边界越复杂,越容易过拟合。
SVM的分类性能确实比其他算法好,但同时SVM模型的计算开销也大,而且有多个超参数需要优化。所以训练处性能最优的SVM模型需要花费相当长的时间。
2、mlr建模#
2.1 垃圾邮件特征数据#
1
2
3
4
5
6
7
8
9
10
|
data(spam, package = "kernlab")
spamTib <- spam
head(spamTib)
dim(spamTib)
# [1] 4601 58
##最后一列为标签列:是否为垃圾数据
##前面的57列均为邮件的特征数据,且都是数值型。
table(spamTib$type)
# nonspam spam
# 2788 1813
|
Note: (1)SVM算法不能处理分类预测变量。(2)SVM算法对不同尺度的变量很敏感,需要归一化处理
2.2 确定预测目标与训练方法#
1
|
spamTask <- makeClassifTask(data = spamTib, target = "type")
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
##(1)定义学习器方法
svm <- makeLearner("classif.svm")
##(2)查看SVM算法的超参数
getParamSet("classif.svm")
# Type len Def Constr Req Tunable Trafo
# type discrete - C-classifica... C-classification,nu-classification - TRUE -
# cost numeric - 1 0 to Inf Y TRUE -
# kernel discrete - radial linear,polynomial,radial,sigmoid - TRUE -
# degree integer - 3 1 to Inf Y TRUE -
# gamma numeric - - 0 to Inf Y TRUE -
# scale logicalvector <NA> TRUE - - TRUE -
## Type列:超参数值的类型,可以是数值、整型、离散值或逻辑值
## Def列:默认值。如果不调节超参数,将使用默认值。
## Constr:取值范围
## Req:学习器是否需要超参数
## Tunable:学习器是否需要超参数
##(3)自定义超参数空间
svmParamSpace <- makeParamSet(
makeDiscreteParam("kernel", values = c("polynomial", "radial", "sigmoid")),
makeIntegerParam("degree", lower = 1, upper = 3),
makeNumericParam("cost", lower = 0.1, upper = 10),
makeDiscreteParam("gamma", values = seq(0.1,10, 0.1)))
# 共 3*3*100*100=90000种超参数组合
|
Note:(1)makeDiscreteParam()适用于接受特定值的超参数,可以是各种类型的。(2)makeIntegerParam与makeNumericParam的lower与upper参数分别指定最小值与最大值,步长分别是1、0.1。(3)对于SVM的kernel的linear等价于degree为1的polynomial。
1
2
3
4
5
6
7
|
##(1) 遍历组合:随机搜索(不能确保找到最优组合,可找到良好的组合)
randSearch <- makeTuneControlRandom(maxit = 50)
# maxit = 50 表示从90000种组合中随机挑选50种组合,取其中性能最优的。
##(2) 交叉验证
cvForTuning <- makeResampleDesc("Holdout", split = 2/3)
#如上使用了留出法的交叉验证方法
|
Note:在计算资源与时间允许的情况下应该尽可能遍历多组超参数组合,并且使用10折交叉验证方式。
2.3 模型训练#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
#由于训练SVM模型耗时,使用下面的并行策略,不足就是无法查看进程
library(parallel)
library(parallelMap)
detectCores() #查看当前电脑的核数
##(1)开始训练:设置调用的进程数
parallelStartSocket(cpus = 8)
tunedSvmPars <- tuneParams("classif.svm", task = spamTask,
resampling = cvForTuning,
par.set = svmParamSpace,
control = randSearch)
##(2)训练结束,停止进程
parallelStop()
##(3) 查看随机搜索的最佳超参数组合
tunedSvmPars
# Tune result:
# Op. pars: kernel=polynomial; degree=1; cost=6.93; gamma=4.4
# mmce.test.mean=0.0651890
tunedSvmPars$x
# $kernel
# [1] "polynomial"
# $degree
# [1] 1
# $cost
# [1] 6.933503
# $gamma
# [1] 4.4
SvmTuningData <- generateHyperParsEffectData(tunedSvmPars,partial.dep=T)
head(SvmTuningData$data)
# kernel degree cost gamma mmce.test.mean iteration exec.time
# 1 sigmoid 3 0.5896223 3.1 0.2314211 1 2.50
# 2 polynomial 2 5.1783061 4.6 0.1264668 2 8.68
# 3 polynomial 2 9.0000612 5.4 0.1264668 3 13.31
# 4 sigmoid 2 7.4176505 6.3 0.2353325 4 2.37
# 5 sigmoid 1 7.4689163 1.9 0.2392438 5 2.62
# 6 radial 3 7.8813946 1.7 0.2327249 6 7.88
|
2.4 嵌套交叉验证#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#inner
inner <- makeResampleDesc("Holdout", split = 2/3)
#outer
outer <- makeResampleDesc("CV", iters = 3)
#在内循环寻找最佳的超参数交给外循环
svmWrapper <- makeTuneWrapper("classif.svm", resampling = inner,
par.set = svmParamSpace,
control = randSearch)
parallelStartSocket(cpus = 8)
cvWithTuning <- resample(svmWrapper, spamTask, resampling = outer)
parallelStop()
##查看结果
cvWithTuning
# Resample Result
# Task: spamTib
# Learner: classif.svm.tuned
# Aggr perf: mmce.test.mean=0.0710711
# Runtime: 66.8189
|