一、简介
决策树分类算法(decision tree)通过树状结构对具有某特征属性的样本进行分类。其典型算法包括ID3算法、C4.5算法、C5.0算法、CART算法等。每一个决策树包括根节点(root node),内部节点(internal node)以及叶子节点(leaf node)。
根节点:表示第一个特征属性,只有出边没有入边,通常用矩形框表示。
内部节点:表示特征属性,有一条入边至少两条出边,通常用圆圈表示。
叶子节点:表示类别,只有一条入边没有出边,通常用三角表示。
决策树算法主要用于分类,也可用于回归,当决策树的输出变量是分类变量时,是分类树;当决策树输出变量是连续变量时,是回归树。虽然回归树的因变量是连续的,但叶节点数是有穷的,因此输出值也是这个叶节点上观测值的平均。
二、基本思想
决策树算法基本思想可以归纳如下:
第一步,对特征空间按照特征属性进行划分;
第二步,对分类后的子集递归第一步。
分类过程看起来很简单,但是要想得到【完全纯净】的子集,也就是每一个子集中的样本都属于同一个分类,还需要一个评价指标对分类效果好坏进行评估——熵。
熵,是系统一种无组织、无序的状态,广泛应用于信息论中。熵值越大,表明数据的纯度越低。当熵等于0,表明样本数据都是同一个类别。其计算公式如下:
其中,P(Xi)表示概率,b此处取值为2。熵的单位为比特bite。
信息增益(information gain):代表的是一次划分对数据纯度的提升效果,也就是划分以后,熵减少越多,说明增益越大,那么这次划分也就越有价值,增益的计算公式如下:
其中D表示样本集,假定属性a有v个可能的取值(离散或连续)。进行最有划分属性时,比如先找到了属性a,对a进行评价,接下来对其他属性重复a的过程,分别得到一个评分,选择评分最高的那个,即信息增益最大的作为最有划分属性。简言之,信息增益就是分割属性前的熵值与分割后的熵值进行差异比较。
需要注意的是,计算子集的熵之和需要乘上各个子集的权重,权重的计算方法是子集的规模占分割前父集的比重。如,分割前的熵为e,分割子集为a和b,大小分别为m和n,熵分别为e1和e2,则信息增益为e-e1*m/(m+n)-e2*n/(m+n)。
三、ID3算法实现
分类的本质是对特征空间的划分。根据决策树的基本思想,其算法实现主要有以下三步:
1.选择特征属性,样本分割。
2.计算信息增益,选取最大增益作为决策树的子节点。
3.递归执行上两步,直至分类完成。
下面将介绍ID3算法在R语言中实现过程。
一组14天天气数据(指标包括outlook,temperature,humidity,windy),并已知这些天气是否打球(play)。如果给出新一天的气象指标数据:sunny,cool,high,TRUE,判断一下会不会去打球。
Outlook |
temperature |
humidity |
windy |
play |
Sunny |
hot |
high |
FALSE |
no |
Sunny |
hot |
high |
TRUE |
no |
Overcast |
hot |
high |
FALSE |
yes |
Rainy |
mild |
high |
FALSE |
yes |
Rainy |
cool |
normal |
FALSE |
yes |
Rainy |
cool |
normal |
TRUE |
no |
Overcast |
cool |
normal |
TRUE |
yes |
Sunny |
mild |
high |
FALSE |
no |
Sunny |
cool |
normal |
FALSE |
yes |
Rainy |
mild |
normal |
FALSE |
yes |
Sunny |
mild |
normal |
TRUE |
yes |
Overcast |
mild |
high |
TRUE |
yes |
Overcast |
hot |
normal |
FALSE |
yes |
Rainy |
mild |
high |
TRUE |
no |
在没有给定任何天气信息时,根据历史数据,我们只知道新的一天打球的概率是9/14,不打的概率是5/14。此时的熵为:
属性有4个:outlook,temperature,humidity,windy。我们首先要决定哪个属性作为树的根节点。
统计在不同天气状况下打球和不打球的次数:
outlook |
temperature |
humidity |
windy |
play |
|||||||||
yes |
no |
yes |
no |
yes |
no |
yes |
no |
yes |
no |
||||
sunny |
2 |
3 |
hot |
2 |
2 |
high |
3 |
4 |
FALSE |
6 |
2 |
9 |
5 |
overcast |
4 |
0 |
mild |
4 |
2 |
normal |
6 |
1 |
TRUR |
3 |
3 |
||
rainy |
3 |
2 |
cool |
3 |
1 |
代码:
##决策树模型之ID3算法 #从粘贴板读取表格数据
weather <- read.table("clipboard",T)
#查看数据结构
str(weather)
#将windy指标转换成因子型
weather$windy <- as.factor(weather$windy)
#未分割前信息熵
q <- matrix(table(weather$play),nrow = 1,dimnames = list('play',unique(weather$play)))/
sum(matrix(table(weather$play),nrow = 1))
e <- -sum(q*log2(q))
#计算各特征属性的信息熵
myfun <- function(x,y){
t <- table(x,y)
m <- matrix(t,nrow = length(levels(x)),2,dimnames = list(levels(x),levels(y)))
#权重计算
n <- apply(m,1,sum)/sum(m)
#分割后各子集的熵
freq <- -rowSums((m/rowSums(m))*log2(m/rowSums(m)))
#分割后的最终熵
entropy <- sum(n*freq,na.rm = T)
return(entropy)
}
#计算信息增益information gain
y <- weather[,5]
gain <- vector()
for (i in 1:(length(weather)-1)) {
x <- weather[,i]
gain[i] <- e-myfun(x,y)
}
names(gain) <- colnames(weather[,1:4])
gain
运行结果:
根据各特征属性的信息增益比较得到,outlook信息增益最大,即熵变化越大,所以决策树的根节点应选择outlook。
接下来选择各子节点N1,N2,N3的特征属性。
用属性outlook划分样本后,三个属性值sunny,overcast,rainy把样本划分为三部分,在每一部分下分别计算gain(temperature)、gain(humidity)、gain(windy)
代码:
#选择子节点特征属性
level <- levels(weather$outlook)
son_gain <- data.frame()
for(j in 1:length(level)){
son_q <- matrix(table(weather[weather$outlook==level[j],]$play),nrow = 1,
dimnames = list('play',unique(weather$play)))/
sum(matrix(table(weather[weather$outlook==level[j],]$play),nrow = 1))
son_e[j]<- -sum(son_q*log2(son_q))
}
for (j in 1:length(level)) {
for (i in 1:length(level)) {
sl <- weather[weather$outlook==level[j],]
son_x <- sl[,i+1]
son_y <- sl[,5]
son_gain[j,i] <- son_e[j]-myfun(x=son_x,y=son_y)
}
}
colnames(son_gain) <- colnames(weather[,-c(1,5)])
rownames(son_gain) <- level
son_gain
信息增益结果:
根据上述结果,在Sunny分支上,humidity的信息增益最大,即熵减少得越快,因此应当将humidity作为子节点N1处的特征属性。
此时,humidity=normal以及humidity=high最终得到的分类结果均为同一中类别,无需在humidity节点下进行再分类,该节点为叶子节点。
同样在rainy分支下的子节点N3应选择windy。且在该节点下无需再进行分类。
在overcast分支下,所有的样本都属于同一个分类,因此该节点为叶子节点。
最终的分类树为: