支持向量机的kernlab::ksvm实现
准备工作
支持向量机常用包
1 | library(e1071) |
二维情形下的支持向量机
最简单的是对一个二维点列, 所有点分为两类, 构造支持向量机模型来进行分类预测
1 | set.seed(3) |
1 | svmdata <- data.frame(x,y,z) |
以上为构造数据, x和y分别是这个二维点列的横纵坐标, 彼此间隔较远, z代表这些点的分类. 最后我们把所有数据按列构成数据框svmdata
1 | kernmodel <- ksvm(z ~ ., data = svmdata) ## 调用kernlab::ksvm构造支持向量机 |
1 | ## |
可以看到, 对原数据回测的准确率为100%.
1 | plot(kernmodel, data = svmdata) |
通过图形, 我们可以轻易辨别出支持向量都是谁(实心点).
高维情形下的支持向量机
二维情形能够较容易推广到高维. 以下为推广到三维的情况
1 | set.seed(3.1) |
1 | ## |
可以看出, 预测准确率仍然是100%. 但是三维及更高维无法直接作图.
对模型的各种测试
学会最简单的使用ksvm来建模之后, 我们要对不同情况下的模型进行测试.
两个分类点靠近时, 回判率的变化
刚才在二维和三维情形下的准确率一直保持100%, 是因为两个分类点距离较远. 如果要让两个分类点逐渐靠近, 甚至有交叉时, 则预测的准确率(回判率)应该会下降.
1 | set.seed(3.14) |
1 | par(mfrow = c(1,1)) |
上图所示, 为四组点列逐渐靠拢的情况. 在两类点有交叉时, 让我们看一下回判率如何.
1 | set.seed(3.14) |
1 | ksvm.precision |
1 | ## [1] 1.0000 0.9875 0.9250 0.5750 |
可以看到, 无论是从数值上, 还是图形上, 随着两类点的不断靠近, ksvm模型的回判率逐渐下降.
不同的kernel对模型的影响
在ksvm函数中可以使用的kernel有很多, 最简单的线性核为vanilladot
1 | set.seed(3.141) |
1 | plot(ksvm.kernel, data = data.kernel) |
1 | table(predict(ksvm.kernel, data.kernel), data.kernel$z) |
1 | ## |
当数据线性可分时, 使用线性核最好不过了. 支持向量机的数量也不会太多.
对上述数据, 可以使用其他核来依次建模, 可以比较出不同的核的区别.
1 | kernelselect <- c("rbfdot","polydot","vanilladot","tanhdot", |
惩罚因子C
对于不同的实际问题, 误判的后果有时严重, 有时问题不大. 所以根据处理的问题不同, 我们对惩罚因子C的选择也不同. 当C变化时, 模型也会有所变化.
下例展示了调节惩罚因子导致模型变化, 最终将误判率降低的情况.
1 | set.seed(3.1415) |
上面两类点中, 靠近中间的一个红色点距离黑色点类比较近, 如果使用默认的C = 1, 可能会将其误判为黑色点类.
1 | ksvm.c <- ksvm(z~x+y, data = data.c, kernel = "vanilladot") |
1 | plot(ksvm.c, data = data.c) |
1 | table(predict(ksvm.c, data.c), data.c$z) |
1 | ## |
通过使用线性核以及默认的惩罚因子, 我们看到的确有一个点误判了, 此点就是我们刚提到的标注为”错误点”的那个.
1 | ksvm.c <- ksvm(z~x+y, data = data.c, C = 2, kernel = "vanilladot") |
1 | plot(ksvm.c, data = data.c) |
1 | table(predict(ksvm.c, data.c), data.c$z) |
1 | ## |
将惩罚因子调整为2, 加大了惩罚力度, 仍然使用线性核, 可以看到误判率降低为零. 从图中也可以看到分类面有所移动.
specc聚类
在kernlab包中有一个specc函数, 该函数的Description为
A spectral clustering algorithm. Clustering is performed by embedding the data into the subspace of the eigenvectors of an affinity matrix.
可见是一个聚类算法. 只不过用到了核. 在该函数的帮助文档中, 使用到了kernlab包中的spirals数据集. 我们先看一下该数据集.
1 | data("spirals") |
1 | ## [,1] [,2] |
1 | plot(spirals) |
从图上可以看出, 数据有点像星云的螺旋状. 而且是两股螺旋的力量. 使用specc聚类:
1 | set.seed(3.14159) |
聚类的效果很好, 按照两类来做也是最妥当的. 当然可以把centers参数改为其他值, 以调整类的数量.
sc此时是一个S4类型的specc类变量. 从中提取分类信息, 并保存到z中, 以便做ksvm.
1 | z <- as.factor(sc@.Data) |
1 | ## x y z |
1 | spmodel <- ksvm(z ~ x + y, data = spdata) |
1 | ## z |
1 | plot(spmodel, data = spdata) |
使用ksvm分类的结果还是比较好的.