一、SVM与RF所使用的工具包加载
library(e1071)
library(klaR) # 导入支持向量机包
library(randomForest) # 导入随机森林包
library(gbm)
library(RODBC) # 导入gbm包
library(AppliedPredictiveModeling)
二、鲍鱼数据读取与预处理
#数据预处理
#数据说明
data(abalone)
head(abalone) # 获取并载入UCL鲍鱼数据
## Type LongestShell Diameter Height WholeWeight ShuckedWeight
## 1 M 0.455 0.365 0.095 0.5140 0.2245
## 2 M 0.350 0.265 0.090 0.2255 0.0995
## 3 F 0.530 0.420 0.135 0.6770 0.2565
## 4 M 0.440 0.365 0.125 0.5160 0.2155
## 5 I 0.330 0.255 0.080 0.2050 0.0895
## 6 I 0.425 0.300 0.095 0.3515 0.1410
## VisceraWeight ShellWeight Rings
## 1 0.1010 0.150 15
## 2 0.0485 0.070 7
## 3 0.1415 0.210 9
## 4 0.1140 0.155 10
## 5 0.0395 0.055 7
## 6 0.0775 0.120 8
str(abalone)
## 'data.frame': 4177 obs. of 9 variables:
## $ Type : Factor w/ 3 levels "F","I","M": 3 3 1 3 2 2 1 1 3 1 ...
## $ LongestShell : num 0.455 0.35 0.53 0.44 0.33 0.425 0.53 0.545 0.475 0.55 ...
## $ Diameter : num 0.365 0.265 0.42 0.365 0.255 0.3 0.415 0.425 0.37 0.44 ...
## $ Height : num 0.095 0.09 0.135 0.125 0.08 0.095 0.15 0.125 0.125 0.15 ...
## $ WholeWeight : num 0.514 0.226 0.677 0.516 0.205 ...
## $ ShuckedWeight: num 0.2245 0.0995 0.2565 0.2155 0.0895 ...
## $ VisceraWeight: num 0.101 0.0485 0.1415 0.114 0.0395 ...
## $ ShellWeight : num 0.15 0.07 0.21 0.155 0.055 0.12 0.33 0.26 0.165 0.32 ...
## $ Rings : int 15 7 9 10 7 8 20 16 9 19 ...
abalone=na.omit(abalone) # 去除所有缺失值
三、鲍鱼性别分类——支持向量机SVM
3.1 支持向量机模型建立
###第一种格式建立模型
summary(abalone) # 查看鲍鱼数据总括
## Type LongestShell Diameter Height
## F:1307 Min. :0.075 Min. :0.0550 Min. :0.0000
## I:1342 1st Qu.:0.450 1st Qu.:0.3500 1st Qu.:0.1150
## M:1528 Median :0.545 Median :0.4250 Median :0.1400
## Mean :0.524 Mean :0.4079 Mean :0.1395
## 3rd Qu.:0.615 3rd Qu.:0.4800 3rd Qu.:0.1650
## Max. :0.815 Max. :0.6500 Max. :1.1300
## WholeWeight ShuckedWeight VisceraWeight ShellWeight
## Min. :0.0020 Min. :0.0010 Min. :0.0005 Min. :0.0015
## 1st Qu.:0.4415 1st Qu.:0.1860 1st Qu.:0.0935 1st Qu.:0.1300
## Median :0.7995 Median :0.3360 Median :0.1710 Median :0.2340
## Mean :0.8287 Mean :0.3594 Mean :0.1806 Mean :0.2388
## 3rd Qu.:1.1530 3rd Qu.:0.5020 3rd Qu.:0.2530 3rd Qu.:0.3290
## Max. :2.8255 Max. :1.4880 Max. :0.7600 Max. :1.0050
## Rings
## Min. : 1.000
## 1st Qu.: 8.000
## Median : 9.000
## Mean : 9.934
## 3rd Qu.:11.000
## Max. :29.000
model=svm(Type~.,data=abalone) # 利用第一种形式建模
###第二种格式建立模型
x=abalone[,-1] # 提取abalone数据中除第1列以外的数据作为特征变量
y=abalone[,1] # 提取abalone数据中的第1列数据作为监督的分类变量
model=svm(x,y,kernel ="radial",gamma =if(is.vector(x)) 1 else 1/ncol(x)) # 利用高斯核函数进行建模
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.125
##
## Number of Support Vectors: 3400
##
## ( 1451 1285 664 )
##
##
## Number of Classes: 3
##
## Levels:
## F I M
3.2 鲍鱼数据SVM模型模式选择
attach(abalone) # 将数据abalone按列单独确认为向量
x=subset(abalone,select=-Type) # 确定特征变量为abalone中除去Type的其他项
y=Type # 确定结果变量为数据iris中的Species项
type=c("C-classification","nu-classification") # 分类方式
kernel=c("linear","polynomial","radial","sigmoid")
pred=array(0,dim=c(4177,2,4)) #初始化预测结果矩阵的三维长度150,2,4
err=matrix(0,2,4) #初始化模型错误矩阵的两维分别为2,4
yy=as.integer(y) #为方便模型精度计算,将结果变量数量化为1,2,3
\(~~~~~~~\)可以从模型比较结果中看到,利用测试数据集在模型中使用高斯核radial以及利用nu-classification分类的测试集的分类泛化误差最小,所以在鲍鱼数据集中的SVM模型建立中使用这种模型进行分析。
for(i in 1:2) #确认i影响的维度代表分类方式
{
for(j in 1:4) #确认j影响的维度代表核函数
{
pred[,i,j]=predict(svm(x,y,type=type[i],kernel=kernel[j]),x)
err[i,j]=sum(pred[,i,j]!=yy)
}
}
dimnames(err)=list(type,kernel)#确定模型精度变量的列名和行名
err # 在此模型中利用高斯核和nu-classification分类效果最好,查询分类名称
## linear polynomial radial sigmoid
## C-classification 1845 1998 1768 2203
## nu-classification 1933 1841 1598 2062
table(pred[,2,3],y) # 模型预测精度展示,改正行名
## y
## F I M
## 1 718 107 390
## 2 213 1067 344
## 3 376 168 794
# 展示混淆矩阵。进行可视化
# 计算错误分类率
3.3 鲍鱼数据SVM模型可视化结果
###模型可视化
plot(cmdscale(dist(abalone[1:200,-1])),col=c("red","black", "blue")[as.integer(abalone[,1])],pch= c("o","+")[1:200 %in% model$index + 1])
# 绘制模型分类散点图,利用dist函数计算前200个样本的样本间欧氏距离(euclidean),利用多维标度法将高维数据降低到2维方便可视化
legend("bottomright",-0.5,c("F","I","M"),col=c("red","black","blue"),
cex=0.75,lty=1)
data(abalone)
model=svm(Type~., data = abalone)
plot(model,abalone,LongestShell~Height,fill=FALSE,symbolPalette=c("red","black","blue"),svSymbol="+",xlim=c(0,0.3))
# 绘制支持向量机模型类别关于LongestShell长度和Height重量的分类情况,利用两个向量分类效果并不怎么好
legend("bottomright",c("F","I","M"), col=c("red","black","blue"), lty=1) # 标签类型选择直线
3.4 鲍鱼数据SVM模型变量权重优化
\(~~~~~~~\)从SVM模型的混淆矩阵建立和可视化结果来看,向量机模型对鲍鱼测试集的泛化结果并不好,正确预测率只有可怜的不到50%,比随机预估33%只好了一点,尤其是在对F和M的判别上改观比较小,所以考虑进行模型的优化,加大模型的F,M的比重,使分错F,M的惩罚加大。
###模型进一步优化,设置权重比重
wts=c(1,1,1) # 确定模型各个类别的比重为1:1:1
names(wts)=c("F","I","M") #确定各个比重对应的类别
model1=svm(x,y,class.weights=wts)
pred1=predict(model1,x)
table(pred1,y) #显示混淆矩阵
## y
## pred1 F I M
## F 354 34 240
## I 180 1075 308
## M 773 233 980
#展示混淆矩阵图形
#计算每一类别的错分率
wts=c(5,1,5) # 由于F和M的错分比重较大,所以将模型各个类别的比重更改为5:1:5,
names(wts)=c("F","I","M") #确定各个比重对应的类别
model2=svm(x,y,class.weights=wts)
pred2=predict(model2,x)
table(pred2,y) #显示混淆矩阵,错分更大
## y
## pred2 F I M
## F 421 63 266
## I 13 528 43
## M 873 751 1219
#可视化混淆矩阵
#计算每一个类别的错分率
wts=c(5,3,5) # 进行再次进行优化,三种比重都进行调整,使不易分错的M的权重减小
names(wts)=c("F","I","M")
model3=svm(x,y,class.weights=wts)
pred3=predict(model3,x)
table(pred3,y)
## y
## pred3 F I M
## F 421 61 266
## I 88 940 169
## M 798 341 1093
\(~~~~~~~\)从上述的鲍鱼SVM模型的优化过程中可以看出,无论怎样进行向量机各类型变量的优化,都无法使得基于测试集所生成的SVM模型,在测试集上的泛华效果表现更好。又因为支持向量机从机器学习算法的本质上讲,其实是隐层为1的神经网络模型,也就是所谓的感知机模型。所以在接下来的部分将在python中进行神经网络的构建。判断实际的鲍鱼性别预测效果。
四、鲍鱼性别分类——随机森林RF
4.1 鲍鱼数据展示与预处理
\(~~~~~~~\)将鲍鱼数据进行查看,并将Type性别分类数据进行因子化,使得随机森林模型可以识别,并且划分以70%和30%的比例形成测试集和训练集。
head(abalone) #查看鲍鱼数据变量
## Type LongestShell Diameter Height WholeWeight ShuckedWeight
## 1 M 0.455 0.365 0.095 0.5140 0.2245
## 2 M 0.350 0.265 0.090 0.2255 0.0995
## 3 F 0.530 0.420 0.135 0.6770 0.2565
## 4 M 0.440 0.365 0.125 0.5160 0.2155
## 5 I 0.330 0.255 0.080 0.2050 0.0895
## 6 I 0.425 0.300 0.095 0.3515 0.1410
## VisceraWeight ShellWeight Rings
## 1 0.1010 0.150 15
## 2 0.0485 0.070 7
## 3 0.1415 0.210 9
## 4 0.1140 0.155 10
## 5 0.0395 0.055 7
## 6 0.0775 0.120 8
dim(abalone) #观察维度
## [1] 4177 9
#将变量Type性别转化为因子型变量,以便进行随机森林的构建
abalone$Type=as.factor(abalone$Type)
#将数据分为训练集和测试集,按照数据集的70%划分为训练数据,30%为测试数据作为样本划分标准
set.seed(100)
train=abalone[sample(1:dim(abalone)[1],ceiling(dim(abalone)[1]*0.7)),]
test=abalone[-sample(1:dim(abalone)[1],ceiling(dim(abalone)[1]*0.7)),]
4.2 构建随机森林模型评价函数
#定义随机森林模型测试集结果评价函数,
#包含Accuracy,recall,precision,F_measure四个评价指标
#Accuracy总正确率,recall后验准确率,precision先验准确率
index2=function(table) {
Accuracy=table[1,1]+table[2,2]+table[3,3]
precision=table[2,2]/sum(table[,2])
recall=table[2,2]/sum(table[2,])
F_measure=2*precision*recall/(precision+recall)#计算Recall,Precision和F-measure
results=data.frame(Accuracy=Accuracy,recall=recall,precision=precision,F_measure=F_measure)
return(results)
}
4.3 随机森林模型的选择
\(~~~~~~~\)通过模型的三维比较来选取对于鲍鱼数据最为适合的随机森林模型。随机森林的决策树的构建所使用的变量以及所形成的树的棵数,分别如下述代码所示。最终的选取结果为每棵树的所使用的变量为4棵,总共生成100棵树。
#随机森林建模
summary(abalone$Type) #查看abalone数据集的性别分布
## F I M
## 1307 1342 1528
var=c(3,4,5) #基本弱分类器决策树的变量选择方式分别为选取3,4,5变量
tree=c(80,100,120) #随机森林中的树的棵数分别为80,100,120棵数
acc=matrix(0,3,3) #初始化模型错误矩阵的两维分别为3,3
for(i in 1:3) #确认i影响的是每次生成决策树所选取的变量数量
{
for(j in 1:3) #确认j影响的是随机森林所含有的树的棵数
{
rf.abalone=randomForest(Type~.,data=train,mtry=var[i],importance=TRUE,ntree=tree[j])
rf.pred= predict(rf.abalone,newdata=test[,-1]) ####利用随机森林进行测试集的预测
rf.real=test$Type
table_RF=table(rf.real,rf.pred)/nrow(test)
a=index2(table_RF) #总准确率Accuracy都高达86%以上,说明集成算法对鲍鱼的分类效果较好
acc[i,j]<-a$Accuracy
}
}
dimnames(acc)=list(as.factor(var),as.factor(tree))#确定模型精度变量的列名和行名
acc # 在此模型中利用4个变量100棵数的分类效果最好,总正确率高达87.629%
## 80 100 120
## 3 0.8739026 0.8675180 0.8762969
## 4 0.8715084 0.8762969 0.8723065
## 5 0.8754988 0.8794892 0.8754988
4.4 鲍鱼性别分类随机森林模型构建
rf.abalone=randomForest(Type~.,data=train,mtry=4,importance=TRUE,ntree=100)
rf.pred= predict(rf.abalone,newdata=test[,-1]) ####利用随机森林进行测试集的预测
rf.real=test$Type
table_RF=table(rf.real,rf.pred)/nrow(test)
4.5 随机森林模型结果分析
\(~~~~~~~\)通过a,b,c,d四个模型输出结果比较,a为总的预测结果,b为混淆数量矩阵,c为判断各成分所占比例,d为各个性别的判断正确率。从a的总预测结果看出总的判别正确率为87.015%,混淆矩阵和各成分所占百分比也可以看出,在测试集中的泛化误差并不大。在变量重要性图中可以看出rings环数和VisceraWeight内脏重量两个变量在构架随机森林的过程中发挥的效果比较高。对于该随机森林来说,对幼年的鲍鱼性别判断较为精准,达到93.38%。
a=index2(table_RF) #详细模型结果
a
## Accuracy recall precision F_measure
## 1 0.8762969 0.9387255 0.9364303 0.9375765
b<-table(rf.pred,rf.real) #混淆数量矩阵
b
## rf.real
## rf.pred F I M
## F 328 9 46
## I 7 383 19
## M 58 16 387
row.names(b)<-c("雌性","幼体","雄性")
colnames(b)<-c("雌性","幼体","雄性")
c<-b/dim(test)[1] #各判断成分所占比例
c
## rf.real
## rf.pred 雌性 幼体 雄性
## 雌性 0.261771748 0.007182761 0.036711891
## 幼体 0.005586592 0.305666401 0.015163607
## 雄性 0.046288907 0.012769354 0.308858739
plot(rf.abalone) #查看随机森林各统计量误差图
round(importance(rf.abalone), 2)
## F I M MeanDecreaseAccuracy MeanDecreaseGini
## LongestShell 0.32 6.86 3.50 9.25 186.82
## Diameter 5.28 5.47 0.68 8.72 178.61
## Height -3.86 9.23 1.75 8.72 145.23
## WholeWeight 5.22 12.77 1.58 14.87 325.82
## ShuckedWeight -2.77 6.21 6.93 9.50 254.63
## VisceraWeight 2.46 15.31 -0.18 17.46 381.50
## ShellWeight 2.50 10.00 -2.02 9.51 292.48
## Rings -4.19 29.80 0.61 26.70 178.54
varImpPlot(rf.abalone) #生成变量重要性比较图
#从变量重要性图中可以看出,rings鲍鱼鲍鱼环数的重要性很高,
#这可能是由于rings环数与年龄有关,而年龄自然能够区别成年与幼年。
d<-data.frame(matrix(NA,3,3))
d[1,]<-b[1,]/(summary(test$Type)[1]) #判断雌性正确率:82.70%
d[2,]<-b[2,]/(summary(test$Type)[2]) #判断幼年正确率:93.38%
d[3,]<-b[3,]/(summary(test$Type)[3]) #判断雄性正确率:85.39%
row.names(d)<-c("雌性","幼体","雄性")
colnames(d)<-c("雌性","幼体","雄性")
d
## 雌性 幼体 雄性
## 雌性 0.83460560 0.02290076 0.11704835
## 幼体 0.01715686 0.93872549 0.04656863
## 雄性 0.12831858 0.03539823 0.85619469