R语言随机森林
回归树模型(CART)
决策树是一种倒立的树结构,它由内部节点、叶子节点和边组成。其中最上面的一个节点叫根节点。 构造一棵决策树需要一个训练集,一些例子组成,每个例子用一些属性(或特征)和一个类别标记来描述。构造决策树的目的是找出属性和类别间的关系,一旦这种关系找出,就能用它来预测将来未知类别的记录的类别。这种具有预测功能的系统叫决策树分类器。其算法的优点在于:1)可以生成可以理解的规则。2)计算量相对来说不是很大。3)可以处理多种数据类型。4)决策树可以清晰的显示哪些变量较重要。
实例
为了预测身体的肥胖程度,可以从身体的其它指标得到线索,例如:腰围、臀围、肘宽、膝宽、年龄
#首先载入所需软件包
library(mboost)
library(rpart)
library(maptree)
#读入样本数据
data("bodyfat", package = "TH.data")
#肥胖程度DEXfat-年龄age、腰围waistcirc、臀围hipcirc、肘宽elbowbreadth、膝宽kneebreadth、
#建立公式DEXfat分类
formular=DEXfat~age+waistcirc+hipcirc+elbowbreadth+kneebreadth
#用rpart命令构建树模型,结果存在fit变量中-method='anova'方差分析
fit=rpart(formular,method='anova',data=bodyfat)
#直接调用fit可以看到结果
fit
#也可以用画图方式将结果表达得更清楚一些
draw.tree(fit)
#建立树模型要权衡两方面问题,一个是要拟合得使分组后的变异较小,另一个是要防止过度拟合,而使模型的误差过大,
#前者的参数是CP,后者的参数是Xerror。所以要在Xerror最小的情况下,也使CP尽量小。如果认为树模型过于复杂,我们需要对其进行修剪
#首先观察模型的误差等数据
printcp(fit)
#调用CP(complexity parameter)与xerror的相关图,一种方法是寻找最小xerror点所对应的CP值,并由此CP值决定树的大小, #另一种方法是利用1SE方法,寻找xerror+SE的最小点对应的CP值。
plotcp(fit)
#用prune命令对树模型进行修剪(本例的树模型不复杂,并不需要修剪)
pfit=prune(fit,cp= fit$cptable[which.min(fit$cptable[,"xerror"]),"CP"])
#模型初步解释:腰围和臀围较大的人,肥胖程度较高,而其中腰围是最主要的因素。
#利用模型预测某个人的肥胖程度
ndata=data.frame(waistcirc=99,hipcirc=110,elbowbreadth=6,kneebreadth=8,age=60)
predict(fit,newdata=ndata)
回归树模型(CART)
装袋算法与随机森林相对而言会生成多个树模型,再进行组合预测,其效果远大于单个树模型
装袋算法(bagging)采取自助法的思路,从样本中随机抽样,形成多个训练样本,生成多个树模型。然后以多数投票的方式来预测结果。
随机森林则(randomForest)更进一步,不仅对样本进行抽样,还对变量进行抽样
预测
#首先读入必要的程序包
library(DMwR)
library(rpart)
library(ipred)
library(randomForest)
#前二种算法可以计算缺失数据,但随机森林不行,所以还需将数据进行清洗整理
data(algae) #读入样本数据--载入包才有该数据
algae <- algae[-manyNAs(algae), ] #去掉缺失值manyNAs返回缺失值的行数
clean.algae <- knnImputation(algae,k=10) #缺失值由距离最近10个邻居的均值(可选中位数)代替
#回归树模型计算
model.tree=rpart(a1 ~ ., data = clean.algae[, 1:12]) #生成模型
pre.tree <- predict(model.tree, clean.algae) #模型预测
plot(pre.tree~clean.algae$a1) #分类分布
nmse1 <- mean((pre.tree- clean.algae[,'a1'])^2)/mean((mean(clean.algae[,'a1'])- clean.algae[,'a1'])^2) #误差比 0.354118
#装袋算法计算
model.bagging <- bagging(a1 ~ ., data = clean.algae[, 1:12], nbagg=1000)
pre.bagging=predict(model.bagging,clean.algae)
plot(pre.bagging~clean.algae$a1)
nmse2 <- mean((pre.bagging- clean.algae[,'a1'])^2)/mean((mean(clean.algae[,'a1'])- clean.algae[,'a1'])^2) #误差比0.3106142
#随机森林计算
model.forest <-randomForest(a1 ~ ., data = clean.algae)
#若有缺失数据需加入: na.action=na.omit 忽略缺失值
pre.forest=predict(model.forest, clean.algae)
plot(pre.forest~ clean.algae$a1)
nmse3 <- mean((pre.forest- clean.algae[,'a1'])^2)/mean((mean( clean.algae[,'a1'])- clean.algae[,'a1'])^2) #误差比 0.1002377
print(c(nmse1,nmse2,nmse3))
#用预测值与真值之间的相对离差平方和来作为测量误差的指标,其结果分别为:0.3541180 0.3103366 0.1002235 可以看出随机森林是最有效的。
#查看重要性
importance(model.forest )
varImpPlot(model.forest )
分类
再来看看处理分类数据的表现,利用iris数据来判断花的种类
library(randomForest)
model.forest <-randomForest(Species ~ ., data = iris) #生成模型
pre.forest=predict(model.forest, iris) #模型预测
table(pre.forest,iris$Species) #table(a,b) a中的数据在b中位置出现的次数
library(rpart)
model.tree=rpart(Species ~ ., data = iris,method='class')
pre.tree=predict(model.tree, data = iris,type='class')
table(pre.tree,iris$Species)
随机森林算法预测全对,而分类树模型则有六处错误
library(randomForest)
library(foreign)
training <-iris
ind<-sample(2,nrow(training),replace=TRUE,prob=c(0.7,0.3)) #对数据分成两部分,70%训练数据,30%检测数据
traindata<- training [ind==1,] #训练集
testdata<- training [ind==2,] #测试集
rf <- randomForest(Species ~ ., data=training, ntree=100, proximity=TRUE) #Species是因变量
table(predict(rf), training$Species)
print(rf)
plot(rf)
importance(rf)
varImpPlot(rf)
预测概率
p<-predict(iris.rf,iris[,-5],type = "prob")