分类算法是基于有类标号的训练集数据建立分类模型并使用其对新观测值(测试数据集)进行分类的算法,属于有监督学习。
对于有监督学习,主要需要建立合适的分类器,对不同类型的数据集进行恰当的分类,达到较高的准确率或召回率或F-score值。
同时不同方法,对于不同问题带来的效果是不同的,比如决策树算法有明确的规则输出而使得模型通俗易懂,能得到一些维度的重要性程度等,或许准确率有待提高,但是也是一种很有价值的算法。
汽车已经成为了人们出行必不可少的工具之一。现在各个汽车销售商也是想方设法提高汽车的销售量。但汽车的销售量是由什么决定的呢?
换而言之,汽车的销售量是由客户的满意度来决定的。我们又想问,汽车的满意度是主要由什么决定的呢?汽车的价格,质量,舒服度哪个因素起的作用更大呢?
有这样一份数据集:
> head(car)
buy main doors capacity lug_boot safety accept
1 vhigh vhigh 2 2 small low unacc
2 vhigh vhigh 2 2 small med unacc
3 vhigh vhigh 2 2 small high unacc
4 vhigh vhigh 2 2 med low unacc
5 vhigh vhigh 2 2 med med unacc
6 vhigh vhigh 2 2 med high unacc
我们根据buy, main,doors, capacity, lug_boot, safety来预测accept的值 ,其中自变量和因变量为均为有序变量。
朴素贝叶斯分类是一种十分简单的分类算法,是一个基于概率的分类器,源于贝叶斯理论。
它的前提假设是:样本属性之间相互独立。
思路: 对于给出的待分类项,求解在此项出现的条件下的各个类别出现的概率,哪个最大,就认为此待分类项属于哪个类别。
# 朴素贝叶斯分类
# 导入car数据集
car <- read.table("car.data",sep = ",")
# 对变量重命名
colnames(car) <- c("buy","main","doors","capacity",
"lug_boot","safety","accept")
# 随机选取75%的数据作为训练集建立模型,25%的数据作为测试集用来验证模型
library(caret)
# 构建训练集的下标集
ind <- createDataPartition(car$accept,times=1,p=0.75,list=FALSE)
# 构建测试集数据好训练集数据
carTR <- car[ind,]
carTE <- car[-ind,]
# 使用naiveBayes函数建立朴素贝叶斯分类器
library(e1071)
naiveBayes.model <- naiveBayes(accept~.,data=carTR)
# 预测结果
carTR_predict <- predict(naiveBayes.model,newdata=carTR) # 训练集数据
carTE_predict <- predict(naiveBayes.model,newdata=carTE) # 测试集数据
# 构建混淆矩阵
tableTR <- table(actual=carTR$accept,predict=carTR_predict)
tableTE <- table(actual=carTE$accept,predict=carTE_predict)
# 计算误差率
errTR <- paste0(round((sum(tableTR)-sum(diag(tableTR)))*100/sum(tableTR),2),"%")
errTE <- paste0(round((sum(tableTE)-sum(diag(tableTE)))*100/sum(tableTE),2),"%")
errTR;errTE
结果如下:
> tableTR
predict
actual acc good unacc vgood
acc 201 8 79 0
good 34 16 0 2
unacc 27 2 879 0
vgood 18 1 0 30
> tableTE
predict
actual acc good unacc vgood
acc 71 2 23 0
good 11 6 0 0
unacc 7 0 295 0
vgood 7 1 0 8
> errTR;errTE
[1] "13.18%"
[1] "11.83%"
主要优点有:
主要缺点有:
决策树是一种树状分类结构模型。它是一种通过拆分变量值建立分类规则,又利用树形图分割形成概念路径的数据分析技术。
决策树的基本思想:
决策树主要用于分类,也可以用于回归,与分类的主要差异在于选择变量的标准不是分类的效果,而是预测误差。
当决策树的输出变量是分类变量时,叫分类树,当决策树的输出变量为连续变量时,称为回归树。
虽然回归树的因变量是连续变量,但是叶节点数据是有穷的。
且回归树不用假定经典回归中的诸如独立性,正态性,线性等特性,无论自变量是定性还是定量数据都适用。
# 使用决策树算法建立分类树
# 使用C50函数实现C5.0算法
library(C50)
C5.0.model <- C5.0(accept~.,data=carTR)
# 使用rpart函数实现CART算法
library(rpart)
rpart.model <- rpart(accept~.,data=carTR)
# 使用ctree函数实现条件推理决策树算法
library(party)
ctree.model <- ctree(accept~.,data=carTR)
# 预测结果,并构建混淆矩阵,查看准确率
# 构建result,存放预测结果
result <- data.frame(arithmetic=c("C5.0","CART","ctree"),
errTR=rep(0,3),errTE=rep(0,3))
for(i in 1:3){
# 预测结果
carTR_predict <- predict(switch(i,C5.0.model,rpart.model,ctree.model),
newdata=carTR,
type=switch(i,"class","class","response")) # 训练集数据
carTE_predict <- predict(switch(i,C5.0.model,rpart.model,ctree.model),
newdata=carTE,
type=switch(i,"class","class","response")) # 测试集数据
# 构建混淆矩阵
tableTR <- table(actual=carTR$accept,predict=carTR_predict)
tableTE <- table(actual=carTE$accept,predict=carTE_predict)
# 计算误差率
result[i,2] <- paste0(round((sum(tableTR)-sum(diag(tableTR)))*100/sum(tableTR),
2),"%")
result[i,3] <- paste0(round((sum(tableTE)-sum(diag(tableTE)))*100/sum(tableTE),
2),"%")
}
# 查看结果
result
结果如下:
> result
arithmetic errTR errTE
1 C5.0 1.16% 1.86%
2 CART 6.09% 4.18%
3 ctree 5.09% 3.94%
可得:决策树算法优于前面的朴素贝叶斯算法,而C5.0算法优于其他两种决策树算法。
library(sparkline)
library(visNetwork)
## 通过可视化参数复杂性图像进行参数选择
plotcp(rpart.model)
visTree(rpart.model,main = "决策树模型",height = "400px",
colorY = c("red","blue","green"))
每一个深度的决策树(图的上横坐标)都对应着一个复杂性程度的阈值(图的横坐标),而且每个cp取值会对一个相对误差(图的纵坐标),所以可以通过设置参数cp的取值对决策树模型进行剪枝优化。根据图中曲线的变化情况,可发现当cp取值为0.013时,模型的相对误差最低,所以可以根据该参数的取值训练新的决策树分类器。
放大到局部便可观察:
library(ggplot2)
## 可视化每个变量的重要性
varimp <- rpart.model$variable.importance
varimpdf <- data.frame(var = names(varimp),
impor = varimp)
ggplot(varimpdf,aes(x = reorder(var,-impor), y = impor))+
geom_col(colour = "lightblue",fill = "lightblue")+
labs(x = "变量", y = "重要性")
可根据可视化图形,判断节点的重要性。
优点:
缺点:
library(ggpol)
ggplot() + geom_confmat(aes(x = carTE$accept, y = carTE_predict),
normalize = TRUE, text.perc = TRUE)+
labs(x = "Reference",y = "Prediction")+
scale_fill_gradient2(low="darkblue", high="lightgreen")