决策树--深入浅出决策树算法

407 阅读5分钟

介绍决策树算法的文章很多,讲的也非常好,这篇文章从基础概念铺垫,到决策树算法的生成,决策树算法的剪枝,一步一步来描述决策树算法。

算法简介

决策树可以用来干嘛?当然是用来做决策,他可以用来处理两类问题:(1)处理分类问题(2)处理回归问题。本文只介绍分类问题的解决思路。

该算法的关键的是“树”,我们就是要找到这样一棵树,来帮助我们做决策。这里有很重要的一个过程,就是这棵树是怎么生成的。待会儿再详细说明。

生成这棵树以后,每一个分支代表一种情况,对每个新输入的样本进行预测的时候,只需要按照树的分支结构,一步一步妄下判断,就可以得到预测值了。

了解必要概念

为了更好的理解决策树算法,我们需要了解几个基础的概念。如果你已经了解相应概念,可以跳过概念部分。

在信息论与概率统计中,熵用来衡量一个变量的不确定性。 假设变量XX包含有限种可能性, 是一个离散随机变量,概率分布为:

p(x=xi)=pii=1,2,...,np(x=x_i) = p_i \quad\quad i = 1,2,...,n

那么随机变量XX的熵定义为:(注意:下式log 通常以 2 或者 e 为底。)

H(X)=i=1npilogpiH(X) = -\sum ^{n} _{i=1} p_i \log pi

为加深对熵的理解,我们举个例:

情形一:掷骰子(六个面都是1);

情形二:掷硬币(有正面或者反面);

情形三:掷骰子(六个面分别是1,2,3,4,5,6)。

我们分别来求解一下两种情况的熵。

情形一,由于只有一种可能性:

H1(X)=1log1=0H_1(X) = - 1·log 1 = 0

情形二,有2种可能:

H2(X)=(12log12+12log12)=log12=log2H_2(X) = - (\frac {1} {2} \log \frac {1} {2} + \frac {1} {2} \log \frac {1} {2}) =-\log \frac {1} {2} = \log 2

情形三,有6种可能:

H3(X)=(16log16+16log16+16log16+16log16+16log16+16log16)H_3(X) = - (\frac {1} {6} \log \frac {1} {6} + \frac {1} {6} \log \frac {1} {6}+ \frac {1} {6} \log \frac {1} {6}+ \frac {1} {6} \log \frac {1} {6}+ \frac {1} {6} \log \frac {1} {6}+ \frac {1} {6} \log \frac {1} {6})
=log16=-\log \frac {1} {6}
=log6= \log 6

对于三种情形

H1(X)<H2(X)<H3(X)H_1(X) < H_2(X) < H_3(X)

并且可以看到:

情形一每次可能出现1种情况,情形非常确定,熵是最低的。 情形二每次可能出现2种情况,熵的值排在中间。 情形三每次可能出现6种情况,情形最复杂,熵也是最高的。

所以得到规律:不确定性越高,熵越高;越确定的事物,熵越低

对于同一事件,有两种情况,一种肯定不会发生,另一种是肯定会发生,都表示事件的结果很确定,所以两种情况的熵都相对很低。所以通俗的讲,事件的结果越分散,各种结果出现的次数越平均,那么熵也就越高。

这点特别重要,待会儿也提到决策树是如何利用这一点的。

  • 信息增益

刚才我们提到了熵的概念,它表示事情的不确定性。接下来我们要讨论信息增益。

上一步中,每个情形只有单个事件。现在我们要提到一种情形,这种情形下,有两个事件XXYY,同时对系统产生影响。 那么总的熵:

H(D)表示:系统的不确定性 H(D) 表示: 系统的不确定性

D 表示系统的各种变量的集合。

现在我们把XX这件事先给“确定”下来,那么X确定以后,系统的熵:

H(DX)表示:在条件X下,系统的不确定性 \quad H(D|X)表示:在条件X下,系统的不确定性

从数值上看, H(DX)H(D|X)H(D)H(D)存在如下大小关系

H(DX)<H(D)H(D|X)<H(D)

那是因为

H(DX)H(D|X)表示的是XX确定,其他变量(也就是YY)不确定的情况下,系统的不确定性;

H(D)表示的是系统所有变量(XXYY)都不确定的情况下,系统的不确定性。

显而易见,H(D)H(D)更加“不确定”,因为当X确定下来以后,整个系统的不确定性H(DX)H(D|X)肯定是减少的。

而这个差值,就是变量X带来的信息增益,计算方法如下:

g(D,X)=H(D)H(DX)g(D,X) = H(D) - H(D|X)

表示得知X后,系统不确定性减少的程度。

  • 信息增益的计算公式

输入:训练数据集DD,特征XX,训练数据集对应的类型CC

输出:特征X对训练数据集D的信息增益g(D,X)g(D,X)

(1) 先计算数据集的经验熵H(D)

H(D)=k=1KCKDlogCKDH(D) = - \sum ^{K} _{k=1} \frac {|C_K|} {D} \log \frac {|C_K|} {D}

注意:经验熵的计算,更偏重的是结果出现的可能性,表示分类结果CkC_k的不确定性。这里的计算并不需要单个变量的变化性。

(2)计算特征X确定的情况下,经验条件熵H(DX)H(D|X)

H(DX)=i=1nDiDH(Di)H(D|X) = \sum ^{n} _{i=1} \frac {D_i} {D} {H(D_i)}

根据特征A的n个不同的取值,将数据集划分为n个子集。DiD_i表示的是第i个子集。

(3)

g(D,X)=H(D)H(DX)g(D, X) = H(D) - H(D|X)

信息增益的概念和计算方法,已经介绍完了。下一小节就进入正题了。

决策树的生成

决策树算法的核心,就在于决策树的生成和剪枝。

决策树的生成算法有2种:(1)ID3 算法(2)C4.5算法

那么我们先介绍ID3算法:

输入: 训练数据集DD,特征集AA,阈值ϵ\epsilon 输出:决策树TT

步骤如下:

(1)若D中所有实例都属于同一类CkC_k,则TT为单节点树,并将(Ck)作为该节点的类标记,返回(C_k)作为该节点的类标记,返回T$;

(2)若A=A=\varnothing ,则TT为单节点树,并将D中的实例数最大的类CkC_k作为该节点的类标记,返回TT

(3)否则,按照信息增益公式,计算信息增益最大的特征AgA_g;

(4)如果AgA_g的信息增益小于阈值ϵ\epsilon,则置T为单节点树,并将D中实例数最大的类CkC_k作为该节点的类标记,返回TT

(5)否则,对AgA_g的每一个可能值aia_i,依Ag=aiA_g = a_iDD分割为若干非空子集DiD_i,将D_i中的实例数最大的类作为标记,构建子节点,由节点及其子节点构成树TT,返回TT

(6)对第i个子节点,以DiD_i为训练集,以AAgA-A_g为特征集,递归调用步骤(1)~(5)

以上就是ID3算法生成决策树的过程,C4.5的过程类似,仅仅是把衡量信息增益的指标,从信息增益“量”,替换为信息增益“比”,即信息增益的比例。

决策树的剪枝

决策树的坚持往往通过及消化决策树整体的损失函数,或者代价函数来实现。

设树T的叶节点个数为|T|,t是树的叶节点,该叶节点有NtN_t个样本点,其中k类的样本点有Ntk个,k=1,2,...,K,Ht(T)N_{tk}个,k=1,2,...,K, H_t(T)为叶节点t熵的经验熵,α0\alpha \leqslant 0为参数,则决策树学习的损失函数可以定义为:

Cα(T)=t=1TNtHt(T)+αTC_\alpha(T) = \sum _ {t=1} ^ {|T|} N_t H_t(T) + \alpha |T|

其中经验熵为

Ht(T)=kNtkNtlogNtkNtH_t(T) = -\sum _{k} \frac {N_{tk}} {N_t} \log \frac {N_{tk}} {N_t}

在损失函数中,将右端第一项记作

C(T)=t=1TNtHt(T)=t=1Tk=1KNtklogNtkNtC(T) = \sum ^{|T|} _{t=1} N_t H_t (T) = - \sum ^{|T|} _{t=1} \sum ^{K} _{k=1} N_{tk} \log \frac {N_{tk}} {N_t}

于是损失函数为:

Cα(T)=C(T)+αT C_{\alpha}(T) = C(T) + \alpha |T|

其中C(T) 表示模型对训练集的预测误差,即模型与训练集的拟合程度。T|T| 表示模型复杂度,参数α0\alpha \geqslant 0 控制两者之间的影响力。

决策树的剪枝,就是通过控制alphaalpha的大小,来调整两者之间的平衡。

具体算法如下:

输入:决策树生成算法产生的整个树TT,参数\alpha;

输出:修剪后的树TαT_\alpha

(1)计算每个节点的经验熵。

(2)递归地从树的叶节点往上回缩。 设一组夜间点回缩到父节点之前和之后的整体树分别为TBT_B TAT_A,其对应的损失函数分别为Cα(TB)C_\alpha(T_B)Cα(TA)C_\alpha(T_A), 如果

Cα(TA)Cα(TB)C_\alpha(T_A) \leqslant C_\alpha(T_B)

则进行剪枝,即将父节点变为新的叶节点。

(3)返回(2),直到不能继续为止,得到损失函数最小的子树TαT_\alpha

利用sklearn中的决策树算法,拟合鸢尾花数据集

首先导入数据集,特征一共包含0,1,2,3列,我们取2,3两列为特征进行分析,画出其数据点的分布:

import numpy as np
import matplotlib.pyplot as plt

from sklearn import datasets

iris = datasets.load_iris()
X = iris.data[:,2:]
y = iris.target

plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.scatter(X[y==2,0], X[y==2,1])
plt.show()

结果如下:

然后,导入决策树算法,进行拟合

from sklearn.tree import DecisionTreeClassifier

dt_clf = DecisionTreeClassifier(max_depth=2, criterion="entropy", random_state=42)
dt_clf.fit(X, y)

DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=2,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False, random_state=42,
            splitter='best')
            

这里借助一个工具函数,用来画决策树的边界

def plot_decision_boundary(model, axis):
    
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1, 1),
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]

    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)

    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
    
    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)

然后我们划出决策树算法生成的分布图:

plot_decision_boundary(dt_clf, axis=[0.5, 7.5, 0, 3])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.scatter(X[y==2,0], X[y==2,1])
plt.show()

结果如下:

结果显示: 我们把横坐标表示的点记作x,纵坐标表示的点记作y 利用决策树进行决策的过程如下:那么

if (x < 2.4) {
    return '红色点'
}

if (y > 1.6) {
    return '绿色点'
}

return '红色点'

总结

决策树的生成过程,利用了ID3 的算法,C4.5算法也是比较类似的,采用的是信息增益比。

此外,还可以使用CART算法对决策树进行生成和剪枝。本文暂未介绍到。