分类数据集采用iris,先用ggplot画出其分布情况,这里用了花萼宽度和花瓣长度作为输入,标签是花的种类
library(ggplot2)
ggplot(iris,aes(x=Sepal.Width,y=Petal.Length,col=Species))+geom_point()
可以看出其属于近似线性可分的情况,接下来用svm进行拟合,首先用默认的径向基核函数作为核函数进行模型拟合
library(e1071)
svm.fit<-svm(Species~Sepal.Width+Petal.Length,data=iris)#默认径向基核函数
summary(svm.fit)
可以看到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核函数的结果分别如下:
他们三个分别预测正确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')
可以看出次数越高,效果越差,而且奇次数比偶次数要好。
接下来针对径向基核函数分别优化正则项系数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')
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')
以上都是单个参数的优化,下面针对径向基核函数的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都拼错了)类别
回归采用的数据集是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')