多种核函数分类及参数优化

分类数据集采用iris,先用ggplot画出其分布情况,这里用了花萼宽度和花瓣长度作为输入,标签是花的种类

library(ggplot2)
ggplot(iris,aes(x=Sepal.Width,y=Petal.Length,col=Species))+geom_point()

 

R语言核密度比较图 核函数r语言_支持向量机

可以看出其属于近似线性可分的情况,接下来用svm进行拟合,首先用默认的径向基核函数作为核函数进行模型拟合

library(e1071)
svm.fit<-svm(Species~Sepal.Width+Petal.Length,data=iris)#默认径向基核函数
summary(svm.fit)

R语言核密度比较图 核函数r语言_R语言_02

可以看到cost默认为1,有59个支持向量。

接下来我们来算一下我们的模型预测对了多少数据

pre<-predict(svm.fit)
pre

n<-nrow(iris)
num = 0
for(i in 1:n){
  if(pre[i]==iris[i,'Species']) num<-num+1
}
num
num/n

得到的结果是num=142,准确率为0.9466667。然后我们来查看分类的结果

myiris<-cbind(iris,pre)
head(myiris)
tf<-c()
for(i in 1:n){
  if(pre[i]==iris[i,'Species']) tf[i]<-as.character(iris[i,'Species'])
  else tf[i]<-'fasle'
}

myiris$tf<-factor(tf)
ggplot(myiris)+geom_point(aes(x=Sepal.Width,y=Petal.Length,col=tf))



同样的方法也可以得到线性核函数、多项式核函数和sigmoid核函数的结果分别如下:

R语言核密度比较图 核函数r语言_支持向量机_03

R语言核密度比较图 核函数r语言_数据集_04

R语言核密度比较图 核函数r语言_支持向量机_05

他们三个分别预测正确143、136、135个,sigmoid效果最差,甚至犯了一些很明显的错误,这是由于sigmoid更适合非线性较强数据集的原因。接下来我们对参数进行优化,先单个参数优化,再整体优化。

首先是多项式核函数的degree,也就是他的最高次数,这里选了1:20来算准确率画出曲线

cur<-c()
for(i in 1:20){
  svm.poly<-svm(Species~Sepal.Width+Petal.Length,data=iris,
                kernel='polynomial',degree=i)
  pre<-predict(svm.poly)
  n<-nrow(iris)
  num = 0
  for(j in 1:n){
    if(pre[j]==iris[j,'Species']) num<-num+1
  }
  cur[i]<-num/n
}
plot(cur,type='l')

R语言核密度比较图 核函数r语言_数据集_06

可以看出次数越高,效果越差,而且奇次数比偶次数要好。

接下来针对径向基核函数分别优化正则项系数cost和核函数中的参数gamma

cur<-c()
for(i in 1:10){
  svm.poly<-svm(Species~Sepal.Width+Petal.Length,data=iris,cost=i)
  pre<-predict(svm.poly)
  n<-nrow(iris)
  num = 0
  for(j in 1:n){
    if(pre[j]==iris[j,'Species']) num<-num+1
  }
  cur[i]<-num/n
}
plot(cur,type='l')

R语言核密度比较图 核函数r语言_R语言核密度比较图_07

cur<-c()
for(i in seq(0.5,10,0.5)){
  svm.poly<-svm(Species~Sepal.Width+Petal.Length,data=iris,gamma=i)
  pre<-predict(svm.poly)
  n<-nrow(iris)
  num = 0
  for(j in 1:n){
    if(pre[j]==iris[j,'Species']) num<-num+1
  }
  cur[i]<-num/n
}
plot(cur,type='l')

R语言核密度比较图 核函数r语言_核函数_08

以上都是单个参数的优化,下面针对径向基核函数的svm,同时优化cost和gamma,并划分训练集测试集进行检验。

set.seed(1)
id<-sample(150,120)
train<-iris[id,]
test<-iris[-id,]

res<-data.frame(matrix(NA,nrow=400,ncol=3))
names(res)<-c('cost','gamma','cur')
for(i in 1:20){
  for(j in seq(0.5,10,0.5)){
    svmfit<-svm(Species~Sepal.Width+Petal.Length,data=train,cost=i,gamma=j)
    pre<-predict(svmfit)
    n<-nrow(train)
    num = 0
    for(k in 1:n){
      if(pre[k]==train[k,'Species']) num<-num+1
    }
    res[(i-1)*20+j*2,]<-c(i,j,num)
  }
}
maxres<-res[which(res[,3]==max(res[,3])),]

上面的代码构造了一个参数和预测正确个数的数据框,并把最高正确率的参数挑选了出来

然后我们用上面得到的第一组最优参数在测试集上进行预测,输出正确个数和准确率并画出结果图

svmbest<-svm(Species~Sepal.Width+Petal.Length,data=test,
             cost=maxres[1,1],gamma=maxres[1,2])
summary(svmbest)
pre<-predict(svmbest)

n<-nrow(test)
num = 0
for(i in 1:n){
  if(pre[i]==test[i,'Species']) num<-num+1
}
num
num/n

myiris<-cbind(test,pre)
tf<-c()
for(i in 1:n){
  if(pre[i]==test[i,'Species']) tf[i]<-as.character(test[i,'Species'])
  else tf[i]<-'fasle'
}
myiris$tf<-factor(tf)
head(myiris)
ggplot(myiris)+geom_point(aes(x=Sepal.Width,y=Petal.Length,col=tf))

得到的正确个数是30,也就是全部预测正确,结果图如下,可以看到没有false(突然发现前面的false都拼错了)类别

R语言核密度比较图 核函数r语言_R语言核密度比较图_09

回归

回归采用的数据集是macars,用hp做自变量,mpg为因变量,核函数采用默认的径向基核函数,结果如下

head(mtcars)
attach(mtcars)
svr<-svm(mpg ~ hp)
pre<-predict(svr,hp)
summary(svr)
mycar<-cbind(mtcars,pre)
ggplot(mycar)+geom_point(aes(hp,mpg))+geom_line(aes(hp,pre),col='red')

R语言核密度比较图 核函数r语言_数据集_10