决策树(decision tree)
理论
决策树就是用树状结构来进行分类的一种机器学习算法,是有监督学习的一种。以二分类学习为例子, 如果我们要对一个瓜是好瓜还是坏瓜进行分类, 通常要经过一系列决策。我们首先要判断“它是什么颜色的?”, 如果是青绿色,再判断“它的根蒂是什么形状的?”, 如果根蒂是蜷缩的,还要判断“敲击这个瓜的声音是浊响的么?”,如果是浊响的,那么判断为是好瓜。
一般的,一个决策树包括一个根结点,若干内部结点和若干叶结点;叶节点对应决策结果,其它结点则对应一个属性测试。从根结点到每个叶子结点的路径对应了一个测试判定序列。决策树学习的目的是为了产生一棵泛化能力强的决策树。基本原理遵循分而治之。
划分选择
一般的随着划分的不断进行,我们希望决策树的分支结点所包含的样本尽可能属于同一类别,即结点的纯度(purity)越来越高。
信息增益
信息熵(information entropy)是度量样本集合纯度的最常用的一种指标,假设当前样本集合
中第
类样本所占的比例
, 则
的信息熵为
Ent(D)的值越小,则D的纯度就越高。
from math import log
def calcShannonEnt(dataset):
num_entries = len(dataset)
lable_counts = {}
for feat_vec in dataset:
current_label = feat_vec[-1]
if current_label not in lable_counts.keys():
lable_counts[current_label] = 0
lable_counts[current_label] += 1
shannon_ent = 0.0
for key in lable_counts:
prob = float(lable_counts[key]) / num_entries
shannon_ent -= prob * log(prob, 2)
return shannon_ent
def createDataset():
dataSet = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no sufacing', 'flippers']
return dataSet, labels
if __name__ == "__main__":
dataSet, labels = createDataset()
# dataSet[0][-1] = 'maybe'
print(calcShannonEnt(dataSet))
当我将main函数里的dataSet[0][-1] = ‘maybe’注释掉之后,我们的label共有两种可能性‘yes’ ‘no’。这是结果是: 0.9709505944546686
当我解除注释, 我们的label有三种可能性:’yes’, ‘no’, ‘maybe’三种。此时结果是1.3709505944546687
也就是说,分类的类数就越多,熵越大。
假设离散属性a有V个可能的取值{
}, 若使用a来对样本集D进行划分,则会产生V个分支结点,其中第v个分支结点包含D中所有在属性a 上取值为
的样本, 记为
.
这个如果看不懂可以看下面这个, 我用了一个例子带入进去,比较好理解。
——————————————————————————————————————————
假设一个银行贷款的案例,有三个特征分别是:1. 是否有房 2. 是否有工作 3. 年龄(青年,中年,老年)。分类的结果是准许贷款和不许贷款。
有房否 | 有工作否 | 年龄 | 贷款/不贷款 |
---|
年龄这个属性有3个可能的取值,青年,中年,老年。如果要用年龄这个属性对来对样本集D进行划分,则会产生3个分支结点。其中第一个分支记为
,包括的就是D中所有青年的数据集,第二个分支记为
, 是D中所有中年的数据集,
包括所有D中老年的数据集。 我们可以根据上面公式计算出
的信息熵。再考虑到不同分支包含样本数不一样,给分支结点赋予权重
。(这句话的意思应该是比如我们的第一个结点是是否有房,有房的所有人都被批准了贷款,之后这部分人我们就不考虑他们了,我们只从没房的人里继续向下分析,可能没房的下一个结点就是年龄,此时没房的样本数目少于总体的样本数目)即样本数越多的分支结点的影响越大。
——————————————————————————————————————————
![](/qrcode.jpg)
对于属性a(例如年龄)对样本集D进行划分所获得的信息增益(information gain)。
一般而言,信息增益越大,则意味着使用属性a来进行划分所获得的“纯度提升”越大。
以上图为例,该数据集包括17个训练样例,用以学习一棵能预测没剖开的是不是好瓜的决策树。显然,分类结果的个数为 。
在决策树开始的时候,根结点包含D中所有样例,其中正例 , 负例为 ,于是计算根结点交叉熵:
计算当前属性集合{色泽, 根蒂, 敲声, 纹理, 脐部, 触感}中每个属性的信息增益。以属性色泽为例,它有三个可能的取值:{青绿,乌黑,浅白}。若使用该属性对D进行划分,则可得3个子集,分别记为 。子集 包含编号{1,4, 6,10,13,17} 的6个例子,其中正例占 ,反例 ; 包含编号{2,3, 7, 8,9, 15}的6个样例,其中正例占 ,反例 ; 包含编号{5,11,12,14,16}的5个样例。其中正例占 ,反例 ;
色泽的信息增益为:
类似的,我们也可以计算其它属性的信息增益:
属性纹理的信息增益最大,故它被选为划分属性。
然后决策树算法,对每个分支结点做进一步划分。
增益率
如果把编号那一列也作为一个候选划分属性,可算出他的信息增益为0.998,远大于其它候选划分。理解起来就是编号会产生17个分支,每个分支结点仅仅包含一个样本,这些分支结点的纯度已达到最大,然而这样的决策树显然不具有泛化能力,无法对新样本进行有效预测。
实际上,信息增益的准则对可取值数目较多的属性有偏好, 为减少这种偏好可能带来的不利影响,著名的C4.5决策树算法不直接用信息增益,而是使用增益率来选择最优划分属性,增益率为:
IV(a) 称为属性a的固有值。 属性a可能取值数目越多(V越大),IV(a)的值通常会越大。例如:IV(触感)=0.874 (V=2), IV(色泽)=1.580 (V=3), IV(编号)= 4.088 (V=17)
需要注意的是增益率准则对可取数值数目较小的属性有所偏好,因此C4.5算法并不是直接选择增益率最大的候选划分属性,而是使用了一个启发式:先从候选划分属性中找出信息增益高于平均水平的属性, 再从中选择增益率最高的。
实践
决策树的构造
优点:计算法复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特征数据。
缺点:可能产生过度匹配问题
适用数据类型:
数值型(数值型目标变量则可以从无限的数值集合中取值,如0.100,42.001等 (数值型目标变量主要用于回归分析))
标称型(标称型目标变量的结果只在有限目标集中取值,如真与假(标称型目标变量主要用于分类))。
决策树的一般流程
- 收集数据: 可以用任意方法。
- 准备数据: 树构造算法只适用于标称型数据,因此数值型数据必须离散化
- 分析数据: 可以使用任意方法,构造树完成之后,我们应该检查图形是否符合预期。
- 训练算法: 构造树的数据结构
- 测试算法: 使用经验树计算错误率
- 使用算法: 此步骤可以用于任何监督学习算法, 而使用决策树可以更好的理解数据的内在含义。