决策树
决策树是一个树状的结构,每个节点代表一次判断,每个树枝是分枝节点判断的输出,每个叶子是最后的分类结果。其中重要的是每一个节点的分类特征如何选择。下面是决策树的构造过程:
- 特征选择:每个节点用哪个特征进行分类,是有选择标准的,根据标准的不同决策树建立方法分为了ID3,C4.5,CART
- 决策树生成:根据标准选择分类特征,不断的进行分类,直到不能再分
- 剪枝:可能存在过拟合,需要去掉一些分枝,减小模型复杂度
ID3算法
用信息增益(熵的变化)来作为选择分类节点的标准,熵可以衡量随机变量的不确定性,不确定性越强熵越大,条件熵是指根据这个特征进行分类后新的熵,熵和条件熵之间的差就是信息增益。具体计算方法如下:
集合D里含有K类,计算选取a为分类特征时的信息增益,a一共有v个可选值,
(
a
1
,
.
.
.
a
v
)
(a^1,...a^v)
(a1,...av)
样本集合D的信息熵:
E
n
t
(
D
)
=
−
∑
i
=
1
K
(
p
i
l
o
g
p
i
)
Ent(D) =-\sum_{i=1}^K(p_ilogp_i)
Ent(D)=−i=1∑K(pilogpi)
信息增益:
G
a
i
n
(
D
,
a
)
=
E
n
t
(
D
)
−
∑
j
=
1
v
∣
D
j
∣
∣
D
∣
E
n
t
(
D
j
)
Gain(D,a)=Ent(D)-\sum_{j=1}^v\frac{|D^j|}{|D|}Ent(D^j)
Gain(D,a)=Ent(D)−j=1∑v∣D∣∣Dj∣Ent(Dj)
信息增益越大代表着分类后样本集合的纯度提升越大
C4.5算法
用信息增益来进行特征选择时发现,特征的产生的分枝越多可能信息增益越大,对可取值数多的特征有所偏好,例如把样本名作为分类特征时,每个分枝里只有一个样本,此时纯度最大,但是这样训练出来的决策树没有泛化能力,所以引入了信息增益率。
信息增益率:
G
a
i
n
r
a
t
i
o
(
D
,
a
)
=
G
a
i
n
(
D
,
a
)
I
V
(
a
)
Gain_{ratio(D,a)}=\frac{Gain(D,a)}{IV(a)}
Gainratio(D,a)=IV(a)Gain(D,a)
I
V
(
a
)
=
−
∑
j
=
1
v
∣
D
j
∣
∣
D
∣
log
2
∣
D
j
∣
∣
D
∣
IV(a)=-\sum_{j=1}^v\frac{|D^j|}{|D|}\log_2{\frac{|D^j|}{|D|}}
IV(a)=−j=1∑v∣D∣∣Dj∣log2∣D∣∣Dj∣
IV(a)是属性a的固有值,属性a可能取值数目越多,IV(a)的值通常越大。但是选择信息增益率作为标准的时候,偏好于可取值少的特征。
所以,先从候选划分属性里找出信息增益高于平均水平的特征,再从中找到增益率最大的属性。
CART
使用基尼指数选择划分属性,用基尼值来衡量纯度,基尼值越小纯度越高
集合D的基尼值:
G
i
n
i
(
D
)
=
∑
i
=
1
∣
K
∣
∑
i
^
≠
i
p
i
p
i
^
=
1
−
∑
i
=
1
∣
K
∣
p
i
2
Gini(D)=\sum_{i=1}^{|K|}\sum_{\hat i\neq i}p_i p_{\hat i}=1-\sum_{i=1}^{|K|}p_i^2
Gini(D)=i=1∑∣K∣i^=i∑pipi^=1−i=1∑∣K∣pi2
基尼指数:
G
i
n
i
i
n
d
e
x
(
D
,
a
)
=
∑
j
=
1
v
∣
D
j
∣
∣
D
∣
G
i
n
i
(
D
j
)
Gini_{index}(D,a) =\sum_{j=1}^v\frac{|D^j|}{|D|}Gini(D^j)
Giniindex(D,a)=j=1∑v∣D∣∣Dj∣Gini(Dj)
选择划分后基尼指数最小的属性作为节点的分类属性。
剪枝
分为预剪枝和后剪枝
预剪枝:每次选定分类节点之后,对于分类前后的数据集进行比较,如果泛化能力没有增强则不进行分类,直接成为叶节点
后剪枝:生成决策树之后,从最后的叶节点开始,计算最后一个节点是否提高了泛化能力,如果没有把最后的分类节点变叶节点。
泛化能力:对于新的测试集进行分类的准确率
连续型特征应该如何处理?
上面提到的信息增益,信息增益率,基尼系数的公式都是基于离散型特征的。在处理连续型特征的时候,把样本中所有该变量的值按顺序列出来,算出相邻连两个数的平均值,把这些平均值按个作为阈值对样本进行二分类,分类后分别计算得到信息增益(信息增益率,基尼系数),经过比较选出合适的阈值。这样做的优点是,选择的分类阈值很准确;缺点是很慢,容易过拟合。
决策树优点
- 可解释性强,可以清楚地知道怎么生成的
- 速度快,鲁棒性强
决策树优点
- 容易过拟合,对测试数据未必有好的分类能力
例子
手写数据集
# 数据导入与划分
from sklearn.datasets import load_digits
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
iris = load_digits()
X = iris.data
Y = iris.target
x_train,x_test,y_train,y_test = train_test_split(X,Y,test_size=0.3,random_state=0)
# 模型训练
DST = DecisionTreeClassifier(criterion='entropy')# 信息熵
DST.fit(x_train,y_train)
from sklearn import metrics
pred = DST.predict(x_test)
accuracy = metrics.accuracy_score(y_test,pred)
print("The accuracy is %.3f"% accuracy)
The accuracy is 0.863
参数
DecisionTreeClassifier(criterion=’gini’, splitter=’best’, max_depth=None,
min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0,
max_features=None, random_state=None, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None, class_weight=None,
presort=False)
- criterion:‘entropy’,‘gini’默认‘gini’
- splitter:‘best‘,’random’默认’best’。‘best’在所有划分点中找出最优的划分点,random随机选出的在部分划分点中找局部最优的划分点。‘best’适合样本量不大的时候,而如果样本数据量非常大,选‘random’更好。
- max_depth:int, None默认None。数据比较少或者特征少的时候可以使用默认值,如果模型样本数量多,特征也多时,需要设置最大深度,具体取值取决于数据的分布。常用的可以取值10-100之间,用来解决过拟合。
- min_samples_split:int,float,默认值为2。内部节点(即判断条件)再划分所需最小样本数,如果是int,则取传入值本身作为最小样本数;如果是float,则取ceil(min_samples_split*样本数量)(向上取整)作为最小样本数
- min_samples_leaf:int,float。叶子节点(即分类)最少样本数。如果是int,则取传入值本身作为最小样本数;如果是float,则取ceil(min_samples_leaf*样本数量)的值作为最小样本数。这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。
- min_weight_fraction_leaf:float,默认是0。叶子节点(即分类)最小的样本权重和,这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。0就是不考虑权重问题,所有样本的权重相同。一般来说如果我们有较多样本有缺失值或者分类树样本的分布类别偏差很大,就会引入样本权重,这时就要注意此值。
- max_features:int,float。在划分数据集时考虑的最多的特征值数量,int,在每次split时最大特征float值】表示百分数,即(max_features*n_features)
- random_state:int, randomSate instance, None,默认是None。
- max_leaf_nodes:int, None默认值None,最大叶子节点数,通过设置最大叶子节点数,可以防止过拟合。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征多,可以加限制,具体的值可以通过交叉验证得到。
- min_impurity_decrease:float,默认值为‘0’。节点划分最小不纯度,限制决策树的增长,节点的不纯度(基尼系数,信息增益,均方差,绝对差)必须大于这个阈值,否则该节点不再生成子节点。
- class_weight:dict, list of dicts, balanced默认为None。类别权重(不适用于回归树,sklearn.tree.DecisionTreeRegressor)指定样本各类别的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。balanced,算法自己计算权重,样本量少的类别所对应的样本权重会更高。如果样本类别分布没有明显的偏倚,则可以不管这个参数。
- presort:bool,默认是False,表示在进行拟合之前,是否预分数据来加快树的构建。对于数据集非常庞大的分类,presort=true将导致整个分类变得缓慢;当数据集较小,且树的深度有限制,presort=true才会加速分类。