机器学习算法总结--决策树

简介

定义:分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点和有向边组成。结点有两种类型:内部结点和叶结点。内部结点表示一个特征或属性,叶结点表示一个类。

决策树学习通常包括3个步骤:特征选择、决策树的生成和决策树的修剪。

决策树学习本质上是从训练数据集中归纳出一组分类规则,也可以说是由训练数据集估计条件概率模型。它使用的损失函数通常是正则化的极大似然函数,其策略是以损失函数为目标函数的最小化。

决策树学习的算法通常是一个递归地选择最优特征,并根据该特征对训练数据进行分割,使得对各个子数据集有一个最好的分类的过程。

决策树的生成对应于模型的局部选择,决策树的剪枝对应于模型的全局选择。决策树的生成只考虑局部最优,相对地,决策树的剪枝则考虑全局最优。

特征选择

特征选择的准则通常是信息增益或者信息增益比。

首先是给出信息熵的计算公式 H(p)=ni=1pilogpi ,熵越大,随机变量的不确定性就越大。公式中 pi 表示随机变量X属于类别 i 的概率,因此 n 表示类别的总数。

条件熵的定义为: H(Y|X)=ni=1piH(Y|X=xi)

已经有了熵作为衡量训练样例集合纯度的标准,现在可以定义属性分类训练数据的效力的度量标准。这个标准被称为“信息增益(information gain)”。简单的说,一个属性的信息增益就是由于使用这个属性分割样例而导致的期望熵降低(或者说,样本按照某属性划分时造成熵减少的期望,个人结合前面理解,总结为用来衡量给定的属性区分训练样例的能力)。更精确地讲,一个属性A相对样例集合S的信息增益Gain(S,A)被定义为:
机器学习算法总结--决策树_第1张图片

其中 Values(A)是属性A所有可能值的集合,Sv是S中属性A的值为v的子集,注意上式第一项就是原集合S的熵,第二项是用A分类S后的熵的期望值,第二项描述的期望熵就是每个子集的熵的加权和,权值为属性Sv的样例占原始样例S的比例|Sv|/|S|,所以Gain(S,A)是由于知道属性A的值而导致的期望熵减少,换句话来讲,Gain(S,A)是由于给定属性A的值而得到的关于目标函数值的信息。

信息增益的缺点是存在偏向于选择取值较多的特征的问题。为了解决这个问题,可以使用信息增益比

因此,特征A对训练数据集D的信息增益比 gR(D,A) 的定义如下:

gR(D,A)=g(D,A)HA(D)

其中 g(D,A) 是信息增益,而 HA(D)=ni=1|Di||D|log2|Di||D| ,其中 n 是特征A取值的个数。

不过对于信息增益比,其也存在对可取值数目较少的属性有所偏好的问题

决策树的生成

接下来会介绍决策树生成的算法,包括ID3, C4.5算法。

ID3算法

ID3算法的核心是在决策树各个结点上应用信息增益准则选择特征,递归地构建决策树。具体步骤如下所示:
机器学习算法总结--决策树_第2张图片

ID3的算法思路总结如下:
1. 首先是针对当前的集合,计算每个特征的信息增益
2. 然后选择信息增益最大的特征作为当前节点的决策决策特征
3. 根据特征不同的类别划分到不同的子节点(比如年龄特征有青年,中年,老年,则划分到3颗子树)
4. 然后继续对子节点进行递归,直到所有特征都被划分

C4.5算法

C4.5算法继承了ID3算法的优点,并在以下几方面对ID3算法进行了改进:

  • 用信息增益率来选择属性,克服了用信息增益选择属性时偏向选择取值多的属性的不足;
  • 在树构造过程中进行剪枝;
  • 能够完成对连续属性的离散化处理;
  • 能够对不完整数据进行处理。

C4.5算法有如下优点:产生的分类规则易于理解,准确率较高。

其缺点是:在构造树的过程中,需要对数据集进行多次的顺序扫描和排序,因而导致算法的低效。此外,C4.5只适合于能够驻留于内存的数据集,当训练集大得无法在内存容纳时程序无法运行。

算法的实现过程如下:
机器学习算法总结--决策树_第3张图片

实际上由于信息增益比的缺点,C4.5算法并没有直接选择信息增益比最大的候选划分属性,而是先从候选划分属性中找出信息增益高于平均水平的属性,再从中选择信息增益比最高的。

剪枝

在生成树的过程中,如果没有剪枝的操作的话,就会长成每一个叶都是单独的一类的样子。这样对我们的训练集是完全拟合的,但是对测试集则是非常不友好的,泛化能力不行。因此,我们要减掉一些枝叶,使得模型泛化能力更强。
根据剪枝所出现的时间点不同,分为预剪枝和后剪枝。预剪枝是在决策树的生成过程中进行的;后剪枝是在决策树生成之后进行的。

决策树的剪枝往往是通过极小化决策树整体的损失函数或代价函数来实现的。简单来说,就是对比剪枝前后整体树的损失函数或者是准确率大小来判断是否需要进行剪枝。

决策树剪枝算法有多种,具体参考决策树剪枝算法这篇文章。

CART

分类回归树(Classification And Regression Tree)是一个决策二叉树,在通过递归的方式建立,每个节点在分裂的时候都是希望通过最好的方式将剩余的样本划分成两类,这里的分类指标:

  1. 分类树:基尼指数最小化(gini_index)
  2. 回归树:平方误差最小化

分类树的生成步骤如下所示:
机器学习算法总结--决策树_第4张图片

简单总结如下:

  1. 首先是根据当前特征计算他们的基尼增益
  2. 选择基尼增益最小的特征作为划分特征
  3. 从该特征中查找基尼指数最小的分类类别作为最优划分点
  4. 将当前样本划分成两类,一类是划分特征的类别等于最优划分点,另一类就是不等于
  5. 针对这两类递归进行上述的划分工作,直达所有叶子指向同一样本目标或者叶子个数小于一定的阈值

基尼指数的计算公式为 Gini(p)=1Kk=1p2k 。K是类别的数目, pk 表示样本属于第k类的概率值。它可以用来度量分布不均匀性(或者说不纯),总体的类别越杂乱,GINI指数就越大(跟熵的概念很相似)。

给定一个数据集D,在特征A的条件下,其基尼指数定义为 Gini(D,A)=ni=1|Di||D|Gini(Di)

回归树:

回归树是以平方误差最小化的准则划分为两块区域

  1. 遍历特征计算最优的划分点s,
    使其最小化的平方误差是: min{min(R1i((yic1)2))+min(R2i((yic2)2))}
    计算根据s划分到左侧和右侧子树的目标值与预测值之差的平方和最小,这里的预测值是两个子树上输入 xi 样本对应 yi 的均值

  2. 找到最小的划分特征j以及其最优的划分点s,根据特征j以及划分点s将现有的样本划分为两个区域,一个是在特征j上小于等于s,另一个在在特征j上大于s

    R1(j)={x|x(j)s}R2(j)={x|x(j)>s}

  3. 进入两个子区域按上述方法继续划分,直到到达停止条件

关于CART剪枝的方法可以参考决策树系列(五)——CART。

停止条件

  1. 直到每个叶子节点都只有一种类型的记录时停止,(这种方式很容易过拟合)
  2. 另一种是当叶子节点的样本数目小于一定的阈值或者节点的信息增益小于一定的阈值时停止

关于特征与目标值

  1. 特征离散 目标值离散:可以使用ID3,cart
  2. 特征连续 目标值离散:将连续的特征离散化 可以使用ID3,cart

决策树的分类与回归

  • 分类树
    输出叶子节点中所属类别最多的那一类
  • 回归树
    输出叶子节点中各个样本值的平均值

理想的决策树

  1. 叶子节点数尽量少
  2. 叶子节点的深度尽量小(太深可能会过拟合)

解决决策树的过拟合

  1. 剪枝
    1. 前置剪枝:在分裂节点的时候设计比较苛刻的条件,如不满足则直接停止分裂(这样干决策树无法到最优,也无法得到比较好的效果)
    2. 后置剪枝:在树建立完之后,用单个节点代替子树,节点的分类采用子树中主要的分类(这种方法比较浪费前面的建立过程)
  2. 交叉验证
  3. 随机森林

优缺点

优点:

  1. 计算量简单,可解释性强,比较适合处理有缺失属性值的样本,能够处理不相关的特征;

缺点:

  1. 单颗决策树分类能力弱,并且对连续值变量难以处理;
  2. 容易过拟合(后续出现了随机森林,减小了过拟合现象);

代码实现

使用sklearn中决策树函数的简单代码例子如下所示:

#Import Library
#Import other necessary libraries like pandas, numpy...

from sklearn import tree
#Assumed you have, X (predictor) and Y (target) for training data set and x_test(predictor) of test_dataset

# Create tree object 
model = tree.DecisionTreeClassifier(criterion='gini') # for classification, here you can change the algorithm as gini or entropy (information gain) by default it is gini  

# model = tree.DecisionTreeRegressor() for regression

# Train the model using the training sets and check score
model.fit(X, y)
model.score(X, y)

#Predict Output
predicted= model.predict(x_test)

决策树的代码在开源库OpenCV中有实现,具体的源码分析可以参考Opencv2.4.9源码分析——Decision Trees,这篇文章也比较详细总结了决策树的知识点以及对OpenCV中决策树部分的源码进行了分析。

你可能感兴趣的:(机器学习,算法)