决策树
•
决策树是一种树形结构
•
•
其中每个内部节点表示一个特征上的判断
•
•
每个分支代表一个判断结果的输出
•
•
最后每个叶节点代表一种分类结果
例子:

决策树-构造过程
•
选择一个特征 (如:是否有房产)
•
根据特征值对样本进行划分 (有房,无房)
•
目标:划分后的样本尽量在同一个类别
•
•
不断重复上述过程
•
•
关键点:
•
1.
如何选择最值得划分的特征
•
2.
如何选择划分点 (主要面向连续特征)
决策树-相关概念
•
纯度(purity)
•
含义:如果一个集合内的所有样本几乎都属于同一个类别,则认为纯度较高,反之则认为纯度较低
••

•
寻找高纯度叶节点的构造方式,是决策树的目标
•
信息熵
(information entropy)
•
含义:用来衡量一个集合纯度的高低,信息熵越小,纯度越高
•
公式:假设样本共有
K
个类别,属于每个类别的概率为
p
k
•

•
•
例:
D = {A, A, A, B, B, C}
•
Ent(D) = -(P
a
*log
2
P
a
+ P
b
*log
2
P
b
+ P
c
*log
2
P
c
)
•
P
a
= 1/2
P
b
= 1/3
P
c
= 1/6
Ent(D) = 1.459
•
信息增益
•
假设离散特征a有
v
个可能的取值{
a
1
, a
2
...a
v
},若使用a对样本数据集D进行划分,则会产生
v
个分支节点,其中第
n
个分直节点包含了D中所有在属性a上取值为
a
v
的样本,记为
Dv
•
则信息增益计算公式如下:

•
信息增益越大,则意味着使用属性 a 来进行划分所获得的纯度提升越大

总样本数为10,其中三个正样本。信息熵如下:
决策树-连续特征的处理
决策树的剪枝
•
剪枝的目的:
•
增强模型的泛化能力
•
•
剪枝的分类:
•
分为
预剪枝和后剪枝。预剪枝是在决策树的生成过程中进行的;后剪枝是在决策树生成之后进行的
决策树的预剪枝
•
通过
提前停止树的构建
而对树剪枝,一旦停止,节点就是树叶,该树叶为持有子集
最频繁的类
。
•
•
停止决策树生长最简单的方法有:
•
•
1.
定义一个高度,当决策树达到该高度时就停止决策树的生长
•
•
2.
达到某个节点的实例具有相同的特征向量,及时这些实例不属于同一类,也可以停止决策树的生长。
•
通过
提前停止树的构建
而对树剪枝,一旦停止,节点就是树叶,该树叶为持有子集
最频繁的类
。
•
•
停止决策树生长最简单的方法有:
•
•
3.
定义一个阈值,当达到某个节点的实例个数小于阈值时就可以停止决策树的生长
•
•
4.
定义一个阈值,通过计算每次扩张对系统性能的增益,并比较增益值与该阈值大小来决定是否停止决策树的生长。
决策树的后剪枝
•
后剪枝首先
构造完整的决策树,允许树过度拟合训练数据,然后对那些置信度不够的结点子树用叶子结点来代替,该叶子的类标号用该结点子树中最频繁的类
标记
•
•
比预剪枝更加实用,因为预剪枝需要许多人工设定的阈值来决定何时停止继续建树
•
•
缺点是运算量大
•
Reduced-Error
Pruning(REP)
•
将数据分成训练集和测试集,训练集上建树,之后使用测试集来评估每个节点对这个
决策树的影响
。
•
•
对于每个节点:
•
1
:删除以此结点为根的子
树
•
2
:使其成为叶子
结点
•
3
:赋予该结点关联的训练数据的最常见
分类
•
4
:当修剪后的树对于验证集合的性能不会比原来的树差时,才真正删除该结点
决策树的优点
•
1. 决策树易于理解和解释,可以可视化分析,容易提取出规则
•
•
2. 可以同时处理离散特征和连续特征
•
•
3. 比较适合处理有缺失属性的样本
•
•
4. 适合处理互不相关的特征
•
•
5
. 运行
速度比较快
决策树的缺点
•
1
.
对于各类别样本数量不一致的数据, 信息增益偏向于那些更多数值的特征,但这类特征不一定有价值
•
•
2
.
容易发生过拟合
•
•
3
.
容易忽略特征之间的相关性
•
•
4.
对于新增训练样本可能需要调整整个树
随机森林
集成学习
为了解决单个模型或者某一组参数的模型所固有的缺陷,从而整合起更多的模型,取长补短,避免局限性。
随机森林
1)从样本集中有放回随机采样选出n个样本(bootstrap);
2)从所有特征中随机选择k个特征,对选出的样本利用这些特征建立决策树;
3)重复以上两步m次,即生成m棵决策树,形成随机森林;
4)对于新数据,经过每棵树决策,最后投票确认分到哪一类。( majority voting )
随机森林的优势
1) 每棵树都选择部分样本及部分特征,一定程度避免过拟合;
2) 每棵树随机选择样本并随机选择特征,使得具有很好的抗噪能力,性能稳定;
3) 能处理很高维度的数据,并且不用做特征选择;
4) 适合并行计算;
5) 实现比较简单;
随机森林的缺点
•
1
)计算开销增大
•
•
2
)可解释性丧失
•
•
3
)决策树的固有问题
Bagging
•Bagging也叫自举汇聚法(bootstrap aggregating)
评价指标
代码实现
import math
'''
计算一个集合的信息熵
'''
#计算信息熵
def entropy_infomation(elements):
ent = 0
for element in set(elements):
p = elements.count(element) / len(elements)
ent += p * math.log(p, 2)
return -ent
# elements = [1, 1, 1, 1, 1, 1]
# print(entropy_infomation(elements))
# elements = [1, 1, 1, 2, 2, 2]
# print(entropy_infomation(elements))
# elements = [1, 2, 3, 4, 5, 6]
# print(entropy_infomation(elements))
# elements = [1, 1, 1, 1, 1, 2]
# print(entropy_infomation(elements))
#计算信息增益
#离散变量
def entropy_gain_discrete(features, labels):
#样本总信息熵Ent(D)
ent_d = entropy_infomation(labels)
for feature in set(features):
#选出特征值=feature的样本
feature_elements = [label for i, label in enumerate(labels) if features[i] == feature]
#计算信息熵
ent_d_feature = entropy_infomation(feature_elements)
ent_d -= len(feature_elements) / len(labels) * ent_d_feature
return ent_d
#计算信息增益
#连续变量
def entropy_gain_continuous(features, labels):
ent_d = entropy_infomation(labels)
#计算划分点
splits = []
uni_features = sorted(list(set(features)))
for i in range(len(uni_features) - 1):
splits.append((uni_features[i] + uni_features[i + 1]) / 2)
gains = []
for split in splits:
#大于切分值的样本
sample_bigger = [label for i, label in enumerate(labels) if features[i] >= split]
#小于切分值的样本
sample_smaller = [label for i, label in enumerate(labels) if features[i] < split]
ent_bigger = entropy_infomation(sample_bigger)
ent_smaller = entropy_infomation(sample_smaller)
split_gains = ent_d - (len(sample_smaller) / len(labels) * ent_smaller
+ len(sample_bigger) / len(labels) * ent_bigger)
gains.append(split_gains)
# 选择切分后信息增益最大的切分点
gain = max(gains) #最大增益值
split = splits[gains.index(gain)] #最大切分点
return gain, split
#”是否有房产“, 1 = 是, 0 = 否
feature_fangchan = [1,0,0,1,0,0,1,0,0,0]
#"婚姻状况", 结婚 = 0, 单身 = 1, 离婚 = 2
feature_hunyin = [1,0,1,0,2,0,2,1,0,1]
#“收入” 连续变量
feature_shouru = [125, 100, 70, 120, 95, 60, 220, 85, 75, 90]
#标签 “是否无法偿还” 0=否 1=是
labels = [0,0,0,0,1,0,0,1,0,1]
print(entropy_gain_discrete(feature_fangchan, labels))
print(entropy_gain_discrete(feature_hunyin, labels))
print(entropy_gain_continuous(feature_shouru, labels))