加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

R语言之支持向量机

(2016-04-11 17:47:24)
分类: R语言学习
一、支持向量机概述:

支持向量机是一个相对较新和较先进的机器学习技术,最初提出是为了解决二类分类问题,现在被广泛用于解决多类非线性分类问题和回归问题。
 
支持向量机(SVM)是一种线性和非线性数据的分类方法,它使用非线性映射将原始数据映射到高维空间,在该空间内搜索最佳分离超平面。
  • 在线性可分的情况下,存在这样的超平面把空间中的类分开,并且该超平面与类的距离最大即最大边缘超平面,它等价于求解约束的凸二次最优化问题,此时是在原输入空间(n)内寻找最大边缘超平面
  • 在线性不可分的情况下,可以允许个别样本分类错误,但需要借助非线性映射把原输入数据变换到高维空间,在该空间搜索最大边缘超平面将该超平面对应到原输入空间的非线性超平面。
理解SVM有四个关键名词:分离超平面、最大边缘超平面、软边缘、核函数
  • 分离超平面(separating hyperplane:处理分类问题的时候需要一个决策边界,这种决策边界将两类事物相分离,而线性的决策边界就是分离超平面。
  • 最大边缘超平面(Maximal Margin Hyperplane)分离超平面可以有很多个,怎么找最好的那个呢,SVM的作法是找一个“最中间”的。换句话说,就是这个平面要尽量和两边保持距离,以留足余量,减小泛化误差,保证稳健性。在数学上找到这个最大边缘超平面的方法是一个二次规划问题
  • 软边缘(Soft Margin):在线性不可分情况下就要考虑软边缘了。软边缘可以破例允许个别样本跑到其它类别的地盘上去。但要使用参数来权衡两端,一个是要保持最大边缘的分离,另一个要使这种破例不能太离谱。这种参数就是对错误分类的惩罚程度C。
  • 核函数(Kernel Function),为了解决完美分离的问题,SVM还提出一种思路,就是将原始数据映射到高维空间中去,直觉上可以感觉高维空间中的数据变的稀疏,有利于“分清敌我”。那么映射的方法就是使用“核函数”。如果这种“核技术”选择得当,高维空间中的数据就变得容易线性分离了。而且可以证明,总是存在一种核函数能将数据集映射成可分离的高维数据。维数过高的害处就是会出现过度拟合。
所以选择合适的核函数以及软边缘参数C就是训练SVM的重要因素。一般来讲,核函数越复杂,模型越偏向于拟合过度。在参数C方面,它可以看作是LASSO算法中的lambda的倒数,C越大模型越偏向于拟合过度,反之则拟合不足。
常用的核函数有如下种类:
  • Linear:使用它的话就成为线性向量机,效果基本等价于Logistic回归。但它可以处理变量极多的情况,例如文本挖掘。
  • polynomial:多项式核函数,适用于图像处理问题。
  • Radial basis:高斯核函数,最流行易用选择。参数包括了sigma,其值若设置过小,会有过度拟合出现。
  • sigmoid:反曲核函数,多用于神经网络的激活函数。

http://s12/mw690/0024CtGngy70QEAsWG77b&690

二、支持向量机应用


       SVM训练速度较慢;SVM能够对复杂的非线性边界建模,不容易过分拟合;SVM总能发现全局最优解

       支持向量机可用于回归、分类和异常检验,前者即为支持向量机回归,后者为支持向量机分类。支持向量机应用在许多领域,包括手写数字识别、对象识别、演说人识别,以及基准时间序列预测检验。

       SVM的研究目标主要是提高训练和检验速度,使得SVM可以成为超大型数据集更可行的选择。其他问题包括,为给定的数据集确定最佳核函数,为多类问题找出更有效的方法。

      1、kernlab包:
        函数ksvm()通过Call接口,使用bsvm和libsvm库中的优化方法。
        对于分类,有C-SVM分类算法和v-SVM分类算法,同时还包括C分类器的有界约束的版本;
        对于回归,提供了ε-SVM回归算法和v-SVM回归算法;
        对于多类分类,有一对一(one-against-one)方法和原生多类分类方法。

## S4 method for signature 'formula'
ksvm(x, data = NULL, ..., subset, na.action = na.omit, scaled = TRUE)

## S4 method for signature 'vector'
ksvm(x, ...)

## S4 method for signature 'matrix'
ksvm(x, y = NULL, scaled = TRUE, type = NULL,kernel ="rbfdot", kpar = "automatic",
C = 1, nu = 0.2, epsilon = 0.1, prob.model = FALSE,class.weights = NULL, cross = 0, fit = TRUE, cache = 40,tol = 0.001, shrinking = TRUE, ...,subset, na.action = na.omit)

type的参数:

C-svc C classification;nu-svc nu classification;C-bsvc bound-constraint svm classification
spoc-svc Crammer, Singer native multi-class;kbb-svc Weston, Watkins native multi-class
one-svc novelty detection;
eps-svr epsilon regression
nu-svr nu regression;eps-bsvr bound-constraint svm regression

kernel的参数:
rbfdot Radial Basis kernel "Gaussian";polydot Polynomial kernel
vanilladot Linear kernel;tanhdot Hyperbolic tangent kernel
laplacedot Laplacian kernel;besseldot Bessel kernel
anovadot ANOVA RBF kernel;splinedot Spline kernel;stringdot String kernel
kpar的参数:the list of hyper-parameters (kernel parameters).
1)sigma inverse kernel width for the Radial Basis kernel function "rbfdot"and the Laplacian kernel "laplacedot".
2)degree, scale, offset for the Polynomial kernel "polydot"
3)scale, offset for the Hyperbolic tangent kernel function "tanhdot"
4)sigma, order, degree for the Bessel kernel "besseldot".
5)sigma, degree for the ANOVA kernel "anovadot".
6)length, lambda, normalized for the "stringdot" kernel where lengthis the length of the strings considered, lambda the decay factor and normalizeda logical parameter determining if the kernel evaluations should be normalized.
  • 分类算法

library(kernlab)

irismodel <- ksvm(Species ~ ., data = iris,type = "C-bsvc", kernel = "rbfdot",kpar = list(sigma = 0.1), C = 10, prob.model = TRUE)
irismodel

fitted(irismodel) #拟合值

#预测值
predict(irismodel, iris[c(3, 10, 56, 68, 107, 120), -5], type = "probabilities")
#Ksvm支持自定义核函数。如
k <- function(x, y) { (sum(x * y) + 1) * exp(0.001 * sum((x - y)^2)) }
class(k) <- "kernel"

data(promotergene)
gene <- ksvm(Class ~ .,data=promotergene[c(1:20,80:100),],kernel = k,C = 10, cross = 5)

  • 回归算法

x <- seq(-20,20,0.1)
y <- sin(x)/x + rnorm(401,sd=0.03)

regm <- ksvm(x,y,epsilon=0.01,kpar=list(sigma=16),cross=3)


plot(x,y,type="l")
lines(x,predict(regm,x),col="red")
        2、e1071包:
        使用libsvm库中的优化方法。多分类通过一对一的投票机制(one-against-one voting scheme)实现。e1071包的tune()函数在指定的范围内选取合适的参数。
案例一:如何使用支持向量机实现二元分类器,使用的数据是来自MASS包的cats数据集。在本例中你将尝试使用体重和心脏重量来预测一只猫的性别。我们拿数据集中20%的数据点,用于测试模型的准确性(在其余的80%的数据上建立模型)。

library(e1071)

data(cats, package="MASS")

inputData <- data.frame(cats[, c (2,3)], response = as.factor(cats$Sex)) # response as factor

传递给函数svm()的关键参数是kernel、cost和gamma

Kernel指的是支持向量机的类型,它可能是线性SVM、多项式SVM、径向SVM或Sigmoid SVM。

Cost是违反约束时的成本函数

gamma是除线性SVM外其余所有SVM都使用的一个参数。

还有一个类型参数,用于指定该模型是用于回归、分类还是异常检测。但是这个参数不需要显式地设置,因为支持向量机会基于响应变量的类别自动检测这个参数,响应变量的类别可能是一个因子或一个连续变量。所以对于分类问题,一定要把你的响应变量作为一个因子。

线性支持向量机:

svmfit <- svm(response ~ ., data = inputData, kernel = "linear", cost = 10, scale = FALSE) # linear svm, scaling turned OFF


print(svmfit)
plot(svmfit, inputData) compareTable <- table (inputData$response, predict(svmfit))  # tabulate

mean(inputData$response != predict(svmfit)) # 19.44% misclassification error

径向支持向量机:径向基函数作为一个受欢迎的内核函数,可以通过设置内核参数作为“radial”来使用。当使用一个带有“radial”的内核时,结果中的超平面就不需要是一个线性的了。通常定义一个弯曲的区域来界定类别之间的分隔,这也往往导致相同的训练数据,更高的准确度。

svmfit <- svm(response ~ ., data = inputData, kernel = "radial", cost = 10, scale = FALSE) # radial svm, scaling turned OFF

print(svmfit)
plot(svmfit, inputData)

compareTable <- table (inputData$response, predict(svmfit))  # tabulate

mean(inputData$response != predict(svmfit)) # 18.75% misclassification error

寻找最优参数:可以使用tune.svm()函数,来寻找svm()函数的最优参数。

set.seed(100) # for reproducing results

rowIndices <- 1 : nrow(inputData) # prepare row indices


sampleSize <- 0.8 * length(rowIndices) # training sample size

trainingRows<- sample (rowIndices, sampleSize) # random sampling

trainingData <- inputData[trainingRows, ] # training data

testData <- inputData[-trainingRows, ] # test data


tuned <- tune.svm(response ~., data = trainingData, gamma = 10^(-6:-1), cost = 10^(1:2)) # tune

summary (tuned) # to select best gamma and cost


结果证明,当cost为100,gamma为0.001时产生最小的错误率。利用这些参数训练径向支持向量机。


svmfit <- svm (response ~ ., data = trainingData, kernel = "radial", cost = 100, gamma=0.001, scale = FALSE) # radial svm, scaling turned OFF

print(svmfit)
plot(svmfit, trainingData)
compareTable <- table (testData$response, predict(svmfit, testData))  # comparison table
mean(testData$response != predict(svmfit, testData)) # 13.79% misclassification error

  • 分类算法

library(e1071)
set.seed(1234)
ind<-sample(2,nrow(iris),replace=TRUE,prob=c(0.7,0.3))
train<-iris[ind==1,]
test<-iris[ind==2,]
svm<-svm(train[,1:4],train[,5],type="C-classification",cost=10,kernel="radial",probability=TRUE,scale=FALSE)
pred<-predict(svm,test[,1:4],decision.values=TRUE)
或者
model <- svm(Species ~ ., data = iris,method = "C-classification", kernel = "radial",cost = 10, gamma = 0.1)
summary(model)
plot(model, iris, Petal.Width ~Petal.Length, slice = list(Sepal.Width = 3,Sepal.Length = 4))
pre=predict(model, iris,type='class')
table(pre,iris$Species)
  • 回归算法

library(e1071)


library(DMwR) 

algae <- algae[-manyNAs(algae), ] 
clean.algae <- knnImputation(algae[,1:12],k=10) 
norm.data <- scale(clean.algae[,4:12]) #数据标准化 
library(e1071)
model.svm <- svm(a1~., norm.data) 
preds <- predict(model.svm, norm.data)
plot(preds~ scale(clean.algae$a1))

        3、klaR包:
         klaR对库SVMlight进行了简单的包装,提供了函数svmlight()以分类,可视化。
         Svmlight()支持C-SVM进行分类,ε-SVM进行回归;以一对所有(one-against-all)进行多类分类。SVMlight支持高斯核,多项式,线性和sigmoid核。Svmlight()的参数形式为字符串形式。

install.packages("klaR")

library(MASS)
library(klaR)

 

 
        4、svmpath包:
        svmpath包里的函数可用来选取支持向量机的cost参数C







0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有