决策树构建(三)
对以下数据构建一颗决策树
构建原则
通过以上章节的学习,我们了解到构建决策树的原则:
-
构建原则:
每次构建的时候都选择一个信息增益最大化的方式。
如果信息增益度的值越大——>以该特征进行分裂后的条件熵越小——>分割后的信息熵越低——>越纯——>在该特征属性上损失的纯度越大(如果用该属性进行分裂会变得更纯)——>用该属性进行分裂,该属性应该在决策树的上层。 -
信息增益度计算公式
D为目标属性,A为某一划分的特征属性:Gain为A为特征对训练数据D的信息增益(集合D的经验熵H(D)与特征A给定条件下D的经验条件熵H(D|A)之差)
- 信息熵计算公式:
- 条件熵计算公式:
构建步骤
步骤:
- 计算出分割前数据集D的信息熵H(D)。(这个信息熵代表的就是分割以前集合的不纯度值)
- 计算出以每个特征A分割,分割后的条件熵H(D|A)。(条件熵的总和就是以当前特征A对D进行分割,分割后的不纯度)
- 计算以每一个特征进行分割,分割前后信息熵的差值,即为:信息增益度
- 选择信息增益度最大的特征进行分割
- 对分割好的节点对剩下的特征(特征也可以重复使用)迭代1,2,3,4步,直到达到迭代终止条件。
补充: 对于纯度的度量,我们可以用信息熵,基尼系数,错误率。这些都可以用,这里我们用信息熵
这里我们用暴力方式,但是只计算两个看看效果就OK了。正常用暴力方式应该计算7个,然后选择效果最好的作为最后的值
下面我们看一下具体的代码实现过程:
# 一、第一个判断节点的选择
# 1.0 计算整个数据集的纯度(样本数10个,3个是,7个否)
h0 = h([0.7, 0.3])
# 1.1 计算以房产作为分割点的时候条件熵(遍历数据计算x1为是和否的概率)
# 第一个分支: 是;样本数目:4,全部为否
p11 = 0.4
h11 = h([1.0])
# 第二个分支:否;样本数目:6,3个是,3个否
p12 = 0.6
h12 = h([0.5, 0.5])
h1 = p11 * h11 + p12 * h12
g1 = h0 - h1
# todo:信息增益率
print("以房产作为划分特征的时候,信息增益为:{}".format(g1))
# 1.2 计算以婚姻情况作为分割点的时候条件熵(遍历数据计算x2为单身、离婚、已婚的概率)
# 第一个分支: 单身;样本数目:4,2个是,2个否
p21 = 0.4
h21 = h([0.5, 0.5])
# 第二个分支:离婚;样本数目:3,1个是,2个否
p22 = 0.3
h22 = h([1.0 / 3, 2.0 / 3])
# 第三个分支: 已婚,样本数目:3,3个否
p23 = 0.3
h23 = h([1.0])
h2 = p21 * h21 + p22 * h22 + p23 * h23
g2 = h0 - h2
print("以婚姻作为划分特征的时候,信息增益为:{}".format(g2))
# 1.3. 以年收入80作为划分值
# 第一个分支: 小于等于80;样本数目:2,2个否
p31 = 0.2
h31 = h([1.0])
# 第二个分支:大于80;样本数目:8,3个是,5个否
p32 = 0.8
h32 = h([3.0 / 8, 5.0 / 8])
h3 = p31 * h31 + p32 * h32
g3 = h0 - h3
print("以年收入80作为划分特征的时候,信息增益为:{}".format(g3))
# 1.4. 以年收入97.5作为划分值
# 第一个分支: 小于等于97.5;样本数目:5,3个是,2个否
p41 = 0.5
h41 = h([2.0 / 5, 3.0 / 5])
# 第二个分支:大于97.5;样本数目:5,5个否
p42 = 0.5
h42 = h([1.0])
h4 = p41 * h41 + p42 * h42
g4 = h0 - h4
print("以年收入97.5作为划分特征的时候,信息增益为:{}".format(g4))
# sys.exit()
print("=" * 100)
# 二、针对于左子树继续划分(年收入小于等于97.5的数据;样本数目:5,3个是,2个否)
h0 = h41
# 2.1 计算以房产作为分割点的时候条件熵
# 第一个分支: 是;样本数目:1,全部为否
p11 = 0.2
h11 = h([1.0])
# 第二个分支:否;样本数目:4,3个是,1个否
p12 = 0.8
h12 = h([0.75, 0.25])
h1 = p11 * h11 + p12 * h12
g1 = h0 - h1
print("以房产作为划分特征的时候,信息增益为:{}".format(g1))
# 2.2 计算以婚姻情况作为分割点的时候条件熵(遍历数据计算x2为单身、离婚、已婚的概率)
# 第一个分支: 单身;样本数目:2,2个是
p21 = 0.4
h21 = h([1.0])
# 第二个分支:离婚;样本数目:2,1个是,1个否
p22 = 0.4
h22 = h([0.5, 0.5])
# 第三个分支: 已婚,样本数目:1,1个否
p23 = 0.2
h23 = h([1.0])
h2 = p21 * h21 + p22 * h22 + p23 * h23
g2 = h0 - h2
print("以婚姻作为划分特征的时候,信息增益为:{}".format(g2))
输出;
特征划分补充
- 划分的特征可以重复使用,即对子节点进行划分的时候,上层已经用过的特征属性也可以再用
- 连续特征划分方式:例如:
在对特征“年均收入”作为分割属性进行划分的时候,年收入不是离散值,是一个连续值,如何划分?怎么来找他的分裂点?
对于连续特征,不管有没有离散化最后一定要分裂成:二叉树- 暴力方式,从大到小排序分成二叉树,每两个节点中都可以进行划分,就有多种划分方式,然后都训练了,选择一个效果最好的作为分裂点。
- 排序之后取中位数
- 连续特征离散化
- 离散特征划分划分多少个分支由特征下类别的个数决定
- 如果只允许二叉树的话类似连续值暴力方式,然后选择一个最优的方式
到这,一棵普通的决策树就已经构建完了
决策树优点
- 直观,可视化
- 效率快