建立模型

svm()函数在建立支持向量机模型的时候有两种建立方式。简单地说,一种是根据既定公式建立模型;而另外一种方式则是根据所给的数据模型建立模型。

根据函数的第一种使用格式,针对上述数据建模时,应该先确定所建立的模型所使用的数据,然后再确定所建立模型的结果变量和特征变来那个。代码如下:

library(e1071)

data(iris)

#建立svm模型

model <- svm(Species~.,data = iris)

在使用第一种格式建立模型时,如果使用数据中的全部特征变量作为模型特征变量时,可以简要地使用“Species~.”中的“.”代替全部的特征变量。

根据函数的第二种使用格式,在针对iris数据建立模型时,首先应该将结果变量和特征变量分别提取出来。结果变量用一个向量表示,而特征向量用一个矩阵表示。在确定好数据后还应根据数据分析所使用的核函数以及核函数所对应的参数值,通常默认使用高斯内积函数作为核函数,具体分析代码如下:

#提取iris数据中除第5列以外的数据作为特征变量

x <- iris[,-5]

#提取iris数据中第5列数据作为结果变量

y <- iris[,5]

#建立svm模型

model <- svm(x,y,kernel = "radial", gamma = if(is.vector(x)) 1 else 1/ncol(x))

在使用第二种格式建立模型时,不需要特别强调所建立模型的哪个是,函数会自动将所有输入的特征变量数据作为建立模型所需要的特征变来那个。

在上述过程中,确定核函数的gamma系数时所使用的R语言所代表的意思为:如果特征向量是向量则gamma值取1,否则gamma值为特征向量个数的倒数。

结果分析

summary(model)

Call:

svm.default(x = x, y = y, kernel = "radial", gamma = if (is.vector(x)) 1 else 1/ncol(x))

Parameters:

SVM-Type: C-classification

SVM-Kernel: radial

cost: 1

gamma: 0.25

Number of Support Vectors: 51

( 8 22 21 )

Number of Classes: 3

Levels:

setosa versicolor virginica

通过summary()函数可以得到关于模型的相关信息。其中,SVM-Type项目说明本模型的诶别为C分类器模型;SVM-Kernel项目说明本模型所使用的核函数为高斯内积函数且核函数中参数gamma的取值为0.25;cost项目说明本模型确定的约束违反成本为1。

在输出结果中,我们还可以看到,对于该数据,模型找到了51个支持变量;第一类具有8个支持向量,第二类具有22个支持向量,第三类具有21个支持向量。最后说明了模型中的三个类别为:setosa、versicolor和virginica。

预测判别

通常我们利用样本数据建立模型之后,主要目的都是利用模型来进行相应的预测和判别。在利用svm()函数建立的模型进行预测时,我们将用到predict()函数对模型进行预测。在实用predict()函数时,应该首先确认将用于预测的样本数据,并将样本数据的特征变量整合放入同一个矩阵,代码如下:

#确认需要继续预测的样本特征矩阵

x <- iris[,1:4]

#根据模型model对x数据进行预测

pred <- predict(model, x)

#随机挑选8个预测结果进行展示

print(pred[sample(1:150, 8)])

1 131 133 41 79 49 47 93

setosa virginica virginica setosa versicolor setosa setosa versicolor

Levels: setosa versicolor virginica

在进行数据预测时,主要注意的问题就是必须保证用于预测的特征向量的个数应同模型建立时使用的特征向量个数一致,否则将无法预测结果。在使用predict()函数进行预测时,不用刻意去调整预测结果类型。

通过对预测结果的展示,我们可以看到predict()函数在预测时自动识别预测结果的类型,并自动生成了相应的类别名称。通常在进行预测之后,还需要检查模型预测的精度,这便需要用到table()函数对预测结果和真实结果做出对比展示。代码如下:

#模型预测精度展示

table(pred, y)

y

pred setosa versicolor virginica

setosa 50 0 0

versicolor 0 48 2

virginica 0 2 48

通过观察table()函数对模型预测精度的展示结果,我们可以看到在模型预测时,模型将所有属于setosa类型的花全部预测正确;模型将属于versicolor类型的花中的48朵预测正确,但将另外良多预测为virginica类型;同理,模型将属于virginica类型的花中的48朵预测正确,但也将另外良多预测为versicolor类型。

综合建模

通过之前对支持向量机理论及支持向量机模型具体应用的介绍,现基于iris数据集 ,综合介绍利用R语言建立模型的完整过程。

分析数据可以看出,数据需要判别的是三个类别,且三个类别属于字符类型,所以我们可以选择的支持向量机分类机就有三类:C-classification、nu-classification、one-classification。同时,可以选择的核函数有四类:线性核函数(linear)、多项式核函数(polynomial)、径向基核函数(radial basis,RBF)和神经网络核函数(sigmoid)。所以在时间和精力允许的情况下,应该尽可能建立所有可能的模型,最后通过比较选出判别结果最优的模型。根据上述分析,利用R语言实现的具体程序代码如下:

library(e1071)

#将数据集iris按列单独确认为向量

attach(iris)

#确定特征变量为数据集iris中除去Species中的其他项

x <- subset(iris, select = -Species)

#确定结果变量为数据集iris中的Species项

y <- Species

#确定将要使用的分类方式

type <- c("C-classification","nu-classification","one-classification")

#确定将要使用的核函数

kernel <- c("linear","polynomial","radial","sigmoid")

#初始化预测结果矩阵的三维长度分别为150,3,4

pred <- array(0,dim = c(150,3,4))

#初始化模型精准度矩阵的二维分别为3,4

accuracy <- matrix(0,3,4)

#为方便模型精度计算,将结果变量数量化为1,2,3

yy <- as.integer(y)

#确认i影响的维度代表分类方式

for(i in 1:3){

  • #确认j影响的维度代表核函数

  • for(j in 1:4){

  • #对每一模型进行预测

  • pred[,i,j] <- predict(svm(x,y.type=type[i],kernel=kernel[j]),x)

  • if (i>2) {

  • accuracy[i,j] <- sum(pred[,i,j]!=1)

  • } else {

  • accuracy[i,j] <- sum(pred[,i,j]!=yy)

  • }

  • }

  • }

#确定模型精度变量的列名和行名

dimnames(accuracy)=list(type,kernel)

在运行程序中,if语句的使用是因为C-classification和nu-classification与one-classification的模型预测精度精算方式不同,所以应该分别进行计算。在运行程序之后,可以得到所有12个模型所对应的预测精度。程序中accuracy所代表的是模型预测错误的个数。

我们将根据这个预测结果挑选出预测错误最少的一些 模型,然后再根据实际情况进行详细分析,最终决定得出最适合本次研究目的的模型。

相应的预测结果如下:

R语言数据挖掘实践——支持向量机代码实战

从表中的模型预测结果可以看出,利用one-classification方式无论采取何种核函数得出的结果错误都非常多,所以可以看出该方式不适合这类数据类型的判别。使用one-classification方式进行建模时,数据通常情况下为一个类别的特征,建立的模型主要用于判别其他样本是否属于这类。

利用C-classification与高斯核函数结合的模型判别错误最少,如果我们建立模型的目的主要是为了总体误判率最低,并且各种类型判错的代价是相同的,那么就可以直接选择这个模型作为最有模型。那么将利用C-classification与高斯核函数介个的模型的预测结果示例代码如下:

table(pred, y)

y

pred setosa versicolor virginica

setosa 50 0 0

versicolor 0 48 2

virginica 0 2 48

在得到这个较优模型之后,我们将针对这一模型在进行具体的分析和讨论,力图进一步提高模型的预测精度。

可视化分析

在建立支持向量机模型之后,我们来进一步分析模型。在分析过程中将会使用模型可视化以便于对模型的分析。在对模型进行可视化的过程中,我们使用plot()函数对模型进行可视化绘制,代码如下:

plot(cmdscale(dist(iris[,-5])),

  • col=c("lightgray","black","gray")[as.integer(iris[,5])],

  • pch=c("o","+")[1:150 %in% model$index + 1])

legend(2,-0.8,c("setosa","versicolor","virginica"),col = c("lightgray","black","gray"),lty=1)

R语言数据挖掘实践——支持向量机代码实战

通过plot()函数对所建立的支持向量机模型进行可视化之后,所得到的图像是对模型数据类别的一个总体观察。图中"+"表示的是支持向量,“0”表示的是普通样本点。

从图中我们可以看到,鸢尾属中的第一种setosa类别同其他两种区别较大,而剩下的versicolor和virginica类别却相差很小,甚至存在交叉难以区分。这也在另一个角度解释了在模型预测过程中出现的问题,这正是为什么模型将两朵versicolor类别的话预测成了virginica类别,并将两朵virginica类别的花预测成了versicolor类别的原因。

在使用plot()函数对所建立的模型进行了总体的观察后,我们还可以利用plot()函数对模型进行其他角度的可视化分析。我们可以利用plot()函数对模型类别关于模型中任意两个特征向量的变动过程进行绘图。绘图过程如下:

data(iris)

model <- svm(Species~., data = iris)

plot(model, iris, Petal.Width~Petal.Length,fill = FALSE,

  • symbolPalette = c("lightgray","black","grey"),svSymbol = "+")

legend(1,2.5,c("setosa","versicolor","virginica"),col = c("lightgray","black","gray"),lty=1)

R语言数据挖掘实践——支持向量机代码实战

通过对模型关于花瓣的宽度和长度对模型类别分类影响的可视化后,我们仍然可以得到一致的结果:setosa类别的花瓣同另外两个类别相差较大,而versicolor类别的花瓣同virginica类别的花瓣相差较小。

通过模型可视化可以看出,virginica类别的花瓣在长度和宽度的总体水平上都高于其他两个类别,而versicolor类别的花瓣在长度和宽度的总体水平上处于居中的位置,而setosa类别的花瓣在长度和宽度上都比另外两个类别小。

优化模型

在模型预测精度结果中我们发现,尽管模型的预测错误已经很少,但是所建立的模型还是出现了4个预测错误,那么为了寻找到一个最优的支持向量机模型,我们是否能通过一些方式来进一步提高模型的预测精度,最理想的情况就是将模型的预测错误率减少为零。

通过对模型的可视化分析后,无论是从总体的总体的角度观察,还是从模型个别特征的角度观察,我们都可以得到一致的结论:类别setosa同其他两个类别的差异较大,而类别versicolor和类别virginica的差异非常小,而且直观上能看到两部分出现少许交叉,并且在预测结果中,模型出现判别错误的地方也是混淆了累呗versicolor和类别virginica。

因此,针对这种情况,我们可以向导通过改变模型各个类别的比重来对数据进行调整。由于类别setosa同其他两个类别相差很大,所以我们可以考虑降低类别setosa在模型中的额比重,而提高另外两个类别的比重,即适当牺牲类别setosa的精度来提高其他两个类别的精度。这种方法在R语言中可以通过svm()函数中的class.weights参数来进行调整。特别强调的是,class.weights参数所需要的数据必须为向量,并且具有列名,具体过程如下:

#确定模型各个类别的比重为1:1:1

wts <- c(1,1,1)

#确定各个比重对应的类别

names(wts) <- c("setosa","versicolor","virginica")

#建立模型

model1 <- svm(x,y,class.weights = wts)

当模型的各个类别的比重为1:1:1时,则模型就是最原始的模型,预测结果即之前的预测模型。接下来我们适当提高类别versicolor和类别virginica的比重,以观察对模型的预测精度是否产生影响,是否为正向影响。

首先,我们先将这两种类别的比重扩大100倍(具体倍数可根据自行调整修改):

wts <- c(1,100,100)

names(wts) <- c("setosa","versicolor","virginica")

model2 <- svm(x,y,class.weights = wts)

pred2 <- predict(model2,x)

table(pred2,y)

y

pred2 setosa versicolor virginica

setosa 50 0 0

versicolor 0 49 1

virginica 0 1 49

通过预测结果的展示发现,通过提高类别versicolor和virginica的比重却能能对模型的预测精度产生影响,并且能产生正向影响。所以我们可以继续通过改变权重的方法来视图提高模型的预测精度。

接下来,我们将这两个类别的权重在扩大5倍,即相对于原始数据,这两个类别的权重总共扩大了500倍:

wts <- c(1,500,500)

names(wts) <- c("setosa","versicolor","virginica")

model3 <- svm(x,y,class.weights = wts)

pred3 <- predict(model3,x)

table(pred3,y)

y

pred3 setosa versicolor virginica

setosa 50 0 0

versicolor 0 50 0

virginica 0 0 50

通过对权重的调整之后,我们建立的支持向量机模型能够将所有样本全部预测正确。所以在实际构建模型的过程中,在必要的时候可以通过改变各样本之间的权重比例来提高模型的预测精度。