决策树 简单理解入门

决策树

  • 介绍

    决策树是基于树状结构来进行决策的。决策过程提出的每个判定问题都是对某个属性的测试,测试的结果,或导出决策结果,或导出下一个判定问题,其考虑范围是上一次决策结果的限定范围内
    例如:一个瓜是否为好瓜,可以先判定瓜的色泽=?,然后根据判定结果,导出结果或者下一个判定问题。
    一棵决策树包含一个根节点,若干个内部节点和若干个叶节点。叶节点对应于决策结果,而其他每个节点则对应于一个属性测试。 每个节点包含的样本集合根据属性测试分到子节点中,根节点包含样本节点全集

  • 涉及问题

  1. 属性测试划分,应该如何选择划分属性,即每次属性的划分如何选出最优的划分属性,什么情况下它是最优的。
  2. 如何处理拟合问题。(预剪枝,后剪枝的差别)
  3. 属性集中使用连续属性和当属性值缺失时如何处理。

决策树的基本流程遵循“分而治之”的策略,决策树基本算法是一个递归的过程,三种情况导致递归返回:

  1. 当前节点数据集只包含同一类别的数据
  2. 当前属性集为空或在所有样本在所有属性上取值相同,无法划分。(分类为含样本数最多的类)
  3. 当前节点包含数据集为空。(把当前节点标记为叶节点,但类别设定为其父节点所含样本最多的类别)
 输入: 训练集D={(x_1,y_1),(x_2,y_2),...,(x_m,y_m)}
      属性集A={a_1,a_2,...a_d}
      过程:函数TreeGenerate(D,A)
      生成节点node;
      if D中的样本属于同一类别C:
      	将node标记为C类叶节点;return;
      if A==空集 or D中样本在A中的取值都相同
      	将node标记为叶节点,其类别为D中样本数最多的类;
      	return;
      从A中选择最优划分属性a*
      for a* 的每个值 a*v:
      	为node生成一个分支,令D_v表示D中在a上取值为a*v的样本子集;
      	if D_v 为空
      		将分支标记为叶节点,其类别为D中样本数最多的类;return;
      	else:
      		以TreeGenerate(D_v, A\{a*});
      	输出:以node为根节点的一棵决策树。`
   

由上面的算法可知,决策树学习最关键的是如何选择最优的属性a*然后进行划分。
一般随着划分过程的进行,我们希望决策树分支节点所包含的类别尽可能的属于同一类别,即纯度越来越高。

  • 划分的选择
    先给出信息熵的定义:样本集合纯度常用的一种指标
    Ent(D)=−∑k=1∣y∣Pklog2PkEnt(D)=-\sum_{k=1}^{|y|}{P_klog_2P_k}Ent(D)=k=1yPklog2Pk
    PkP_kPk : D 中 k 类样本所占比例

属性划分选择 离散属性a有V个取值{a1,…av}。 若使用 a 属性来划分样本集 D,则有 V 个分支节点,其中第v个节点包含了 D 中所有在属性 a 上取值为 av 的样本,记为 Dv考虑到不同分支所包含的样本数不同,给分支节点赋予权重 |Dv| / |D|,即样本数越多的分支节点影响越大。
信息增益(ID3算法)
D: 当前样本集
k:样本第k类。k取值为1~|y|
V: 属性a的可能取值

信息增益:

Gain(D,a)=Ent(D)−∑v=1V∣Dv∣∣D∣Ent(Dv)Gain(D,a)=Ent(D)-\sum_{v=1}^V{\frac{|D^v|}{|D|}Ent(D^v)}Gain(D,a)=Ent(D)v=1VDDvEnt(Dv)

信息增益越大,使用该属性划分所获得的纯度提升越大。 信息增益准则对可取值数目较多的属性有所偏好
增益率(C4.5决策树算法)

GainRatio(D,a)=Gain(D,a)IV(a)GainRatio(D,a)=\frac{Gain(D,a)}{IV(a)}GainRatio(D,a)=IV(a)Gain(D,a)

IV(a)=−∑v=1V∣Dv∣∣D∣log2∣Dv∣∣D∣IV(a)=-\sum_{v=1}^{V}{\frac{|D^v|}{|D|}log_2\frac{|D_v|}{|D|}}IV(a)=v=1VDDvlog2DDv

其中 IV 为属性 a 的固有值,属性 a 的可能值越多,IV(a) 的值通常会越大。 增益率准则对可取值较少的属性有所偏好,因此C4.5算法并不直接选择增益率最大的属性来划分属性,而是先从候选划分属性中找出信息增益高于平均值的属性,再从中选择增益率最高的。
基尼指数(基尼不纯度):

Gini(D)=1−∑k=1∣y∣pk2Gini(D)=1-\sum_{k=1}^{|y|}{p_k^2}Gini(D)=1k=1ypk2

Gini(D)反映了从数据集D中随机抽取两个样本,其类别标记不一致的概率,因此,Gini(D)越小,则数据集D的纯度越高。 属性a的基尼指数定义为:
GiniIndex(D,a)=∑v=1V∣Dv∣∣D∣Gini(Dv)GiniIndex(D,a)=\sum_{v=1}^{V}{\frac{|D_v|}{|D|}Gini(D^v)}GiniIndex(D,a)=v=1VDDvGini(Dv)

我们在候选集A中,选择那个使得划分后基尼指数最小的属性作为最优划分属性。

  • 剪枝处理
    剪枝是决策树算法对付过拟合的一种策略,决策树在进行节点划分的时候,有时候会由于分支过多而导致模型在训练集上学习得太好了,从而导致过拟合。
  • 预剪枝
    预剪枝指的是在决策树生成的分支的时候,先估计分支前的的决策树的泛化能力,在估计分支后的泛化能力,如果当前的分支不能时决策树的泛化能力提升,则不进行分支。
  • 后剪枝
    后剪枝指在决策树模型训练完毕后,自底向上的对所有非叶节点进行考察,若该非叶节点替换成叶节点,能使模型的泛化能力提升,则进行剪枝,将该节点替换为叶节点。
    如何对模型的泛化能力进行估计呢,我们可以采用留出法,即在训练集中分出一部分验证集(区分于测试集),训练的时候用验证集进行估计,然后进行前后比较(信息增益,信息率或者基尼指数,主要看采用了那个算法)。
    后剪枝决策树通常比预剪枝决策树保留了更多的分支,所以后剪枝的欠拟合风险可能更小,但是由于后剪枝是在训练完整个决策树后进行处理的,所以训练时间开销要更大一点
  • 连续值的处理
    训练数据通常会有一些属性是连续(密度,含糖率之类的)的而不是离散的。连续属性的取值是无限的,所以不能对连续属性的可能取值来对节点进行划分。在 C4.5 算法中采用二分法来讲连续属性离散化。
    即先对连续属性 aaa 进行排序,然后在相邻属性 ai−1a^{i-1}ai1aia^{i}ai 中取任意值,这样对所产生的划分结果是相同的,因此对连续属性(假设有 n 个取值)我们可以有 n-1 个候选划分集合。
    Ta=ai+ai−12∣1≦i≦n−1T_a=\frac{{a^i + a^{i-1}}}{2} |1≦i≦n-1Ta=2ai+ai11in1
    然后使用信息增益时,选择某个划分点,然后对左右进行划分,计算出信息增益
    Gain(D,a)=Ent(D)−∑λ∈{−,+}∣Dv∣∣D∣Ent(Dv)Gain(D,a)=Ent(D)-\sum_{λ∈\{-,+\}}{\frac{|D^v|}{|D|}Ent(D^v)}Gain(D,a)=Ent(D)λ{,+}DDvEnt(Dv)
    然后选择最优的划分点。
    需要注意的是连续属性在进行划分后,该属性还可以作为后代节点的划分属性。
  • 缺失值的处理
    需要解决的问题是:(1)如何在属性值缺失的情况下进行划分属性选择。(2)给定划分属性,若该样本在属性的值缺失,如何对样本进行划分。
    (不太理解,后面补充)
  • 使用 sklearn 加深对决策树的印象
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import export_graphviz
from sklearn import preprocessing

def draw(model,X,y):
    h = 0.01
    x_min, x_max = iris_X[:, 0].min() - 1, iris_X[:, 0].max() + 1
    y_min, y_max = iris_X[:, 1].min() - 1, iris_X[:, 1].max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))  # 一维数组变为矩阵将第一个变为行向量,第二个为列向量
    Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape(xx.shape)
    plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
    plt.scatter(X[y == 2, 0], X[y == 2, 1], c='y', marker='*', label='2')
    plt.scatter(X[y == 1, 0], X[y == 1, 1], c='b', marker='x', label='1')
    plt.scatter(X[y == 0, 0], X[y == 0, 1], c='r', marker='o', label='0')
    plt.show()

iris = load_iris()
iris_X = iris.data[:, [2, 3]]
iris_y = iris.target
iris_X = preprocessing.scale(iris_X)#标准化
'''
criterion : string,optional(default =“gini”)
衡量划节点分的功能。支持的标准是基尼杂质的“gini”和信息增益的“entropy”。
splitter : string,optional(default =“best”)
用于在每个节点处选择拆分的策略。支持的策略是“best”选择最佳分割和“random”选择最佳随机分割
max_depth : int或None,可选(默认=无)
树的最大深度。如果为None,则扩展节点直到所有叶子都是纯的或直到所有叶子包含少于min_samples_split样本。
min_samples_split : int,float,optional(default = 2)
拆分内部节点所需的最小样本数:
'''
tree = DecisionTreeClassifier(criterion='entropy', max_depth=3, random_state=0)
tree.fit(iris_X, iris_y)
draw(tree,iris_X,iris_y)
export_graphviz(tree, out_file='tree.dot', feature_names=['petal length', 'petal width'])#安装graphviz做可视化树图 dot -Tpng tree.dot -o tree.png

'''
随机森林
    使用bootstrap抽样方法随机选择n个样本用于训练(随机可重复)
    (2)不重复随机选取d个特征,根据目标函数要求,如最大化信息增益,使用所选取的特征进行节点划分
    重复(2)多次
    汇总每课决策树的类标进行多数投票。
'''
'''
n_estimators : 整数,可选(默认= 10)
森林里的树木数量
criterion :(同上)
max_depth :(同上)
n_jobs: int或None,可选(默认=无)
处理器内核数量
'''
# from sklearn.ensemble import RandomForestClassifier
# forest = RandomForestClassifier(criterion='gini', n_estimators=5, random_state=1,n_jobs=2)
# forest.fit(iris_X,iris_y)
# draw(forest, iris_X, iris_y)

决策树分类:

在这里插入图片描述
随机森林:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值