《Machine Learning in Action》—— Taoye给你讲讲决策树到底是支什么“鬼”

前面我们已经详细讲解了线性SVM以及SMO的初步优化过程,具体可看:

关于SVM非线性相关的内容,我们留着下个星期来撕

这篇文章我们先来看看决策树的内容,决策树相对于SVM来讲要简单不少,也没有多么复杂的公式。我理解的决策树,简单来说就是通过已有的数据集训练出一个树形结构的模型,以便我们能够依据该模型对不知分类结果的数据进行预测。简单的决策树就有点类似于我们在学习数据结构时候的二叉排序树。当然了,决策树除了能够进行分类之外,还能进行回归,这里主要讨论的是分类问题。

关于决策树相关的内容,可能会肝两篇文章来介绍。第一篇主要是讲解决策树先关的基本知识,及其决策训练的过程,也就是我们的这篇文章,重在理论及推导,也重在理解。而第二篇文章写的主要内容是决策树的代码实战,而代码实战是在熟悉理论基础的前提之下来进行的,所以对于决策树相关的理论知识还是有必要了解的。可能的话,还会有第三篇,主要是关羽防止决策树过拟合的剪枝操作的内容。

一、什么是决策树

关于决策树的定义,李航——《统计学习方法》(第二版)这本书中是这样描述的:

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

上述提到的内部节点可以理解成样本的属性特征,而叶节点可以理解成样本的标签,而有向边可以理解成不同的属性特征结果。一般我们在绘制决策树的时候,内部节点用方框或长方形表示,而叶节点用圆形或椭圆表示。(注意:这个并不是绝对的,在不同资料中可能有不同的表示方法,比如《统计学习方法》一书中用圆表示内部节点,用方形表示叶子节点,而在《机器学习实战》一书中表示方式正好相反

枯燥的文字说明总是会降低读者的阅读欲望,下面我们不妨通过一个实际的例子来说明下,从而加强读者对决策树的理解。

比如说,形容女生美与丑的时候一般会存在多个指标,这个例子感觉有点危险,还是换个吧。

例子来源:李航——《统计学习方法》(第二版)

比如说,我们没Money用了,想要去银行贷款,这个时候银行就会根据你自己的个人附带特征来决定是否给你放款。假设这里的属性特征有四个,分别是年纪、是否工作、是否有房子、信用情况,这些属性特征就相当于是内部节点,标签(结果)是否放款相当于叶子节点,而不同属性特征的结果表示有向边,像年纪中有青年、中年、老年,信用情况有好、一般、非常好等表示不同的有向边。

对此,我们可以根据自己的感觉来手动绘制一个简单的决策树模型:

我们知道,上述决策树仅仅是我们自己手动来实现的,不一定能够运用于解决实际问题。而决策树的任务,则是根据已有的数据样本集训练得到这么一颗树形结构模型,以此来对未知分类的数据进行类别预测。对此,我们要向得到这么一颗尽可能理想的决策树,则不得不考虑以下几个问题:

  • 决策树的指标(属性特征)选择的顺序应该是怎样的的?哪个特征应当被优先考虑呢?
  • 如果构建出的决策树出现了过拟合问题,也就说我们的训练的时候还不错,但是一测试就GG,这个时候我们应当怎么解决呢?

本篇文章,主要内容是属性特征的优先选取问题。

二、属性特征的选择

对于属性特征的选择,我们应当优先选取对训练数据集具有明显分类能力的特征,这样可以提高我们决策树的学习效率。假如说一个属性特征的分类结果与随机分类基本没什么差别,则我们可以说这个属性特征基本是没有分类能力的。

比如说,我们这里有12个关于女生美与丑的数据样本,其中六个是丑女,另外六个是美女,六个丑女身高有三个是165cm、三个是185cm,而另外六个美女身高同样如此,这样的话,我们仅仅通过身高来对女生美貌的判断基本是没有分类能力的。(仅仅是个例子,不代表任何观点

所以,我们理想情况下决策树的生成理应是这样的:随着决策过程的不断进行,我们希望决策树的分支节点所包含的样本尽可能的属于同一类别(标签相同),也就是节点的“纯度”越来越高。

所以,决策树的关键技术在于属性特征的选择。对于属性特征的选择,我们通常有三个准则:信息增益、信息增益比(增益率)和基尼指数。

2.1 信息增益

上面提到了样本浓度,比如说我这里有10个女生,10个都是美女,那就说此时的样本浓度高,假如美女和丑女五五分,那这个时候的浓度就比较低了。这里的“浓度”表达的就是这个意思,它主要针对的是标签(结果)

而表示样本“浓度”的指标,最常用的就是“信息熵”了。假定当前样本集合\(D\)中第\(k\)类(总共\(n\)类)样本所占的比例为\(p_k\),则此时样本\(D\)的信息熵为:

\[Ent(D) = -\sum_{k=1}^np_klog_2(p_k) \tag{2-1}
\]

通过上述公式,我们可以知道10个美女(一个类别)的信息熵为

\[Ent(D)=-1 * log_21=0
\]

美女丑女五五分(两类)的信息熵为:

\[Ent(D) = -\frac{1}{2}log_2\frac{1}{2}-\frac{1}{2}log_2\frac{1}{2}=1
\]

通过上面信息熵的简单计算,我们可以知道,信息熵的值越小,则纯度越高。

既然我们已经了解了信息增益的计算公式及其所表达的意义,那么对于一个数据样本集,我们应当如何用代码来进行计算呢?下面我们来试试吧。

本次使用到的数据样本来自 李航——《统计学习方法》(第二版),数据是关于贷款申请的,具体如下:

那么现在我们来通过代码形式计算下这个数据样本集的信息熵吧:

首先创建一个establish_data方法来建立一个二维数组用于存储上述数据样本集的相关信息(关于属性特征所对于的值0,1,2之类的,大家可以参考上述表格对号入座,这里就不做过多解释了):

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:创建训数据集
"""
def establish_data():
data = [[0, 0, 0, 0, 'N'], # 样本数据集相关信息,前面几项代表属性特征,最后一项表示是否放款
[0, 0, 0, 1, 'N'],
[0, 1, 0, 1, 'Y'],
[0, 1, 1, 0, 'Y'],
[0, 0, 0, 0, 'N'],
[1, 0, 0, 0, 'N'],
[1, 0, 0, 1, 'N'],
[1, 1, 1, 1, 'Y'],
[1, 0, 1, 2, 'Y'],
[1, 0, 1, 2, 'Y'],
[2, 0, 1, 2, 'Y'],
[2, 0, 1, 1, 'Y'],
[2, 1, 0, 1, 'Y'],
[2, 1, 0, 2, 'Y'],
[2, 0, 0, 0, 'N']]
return np.array(data)

随后,我们创建一个calc_information_entropy方法用于计算信息熵,计算过程的代码可结合上述的公式来看。另外,需要说一点的是,为了方便对放款结果进行分类,我们使用pandas包进行处理,关于pandas的使用,大伙可以参考文档,Taoye后期也会整理一份。当然了,不用pandas模块也能实现这个功能,有兴趣的读者可自行尝试,也不难。calc_information_entropy具体代码如下:

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算信息熵
"""
def calc_information_entropy(data):
data_number, _ = data.shape
information_entropy = 0
for item in pd.DataFrame(data).groupby(_ - 1):
print(item[1])
proportion = item[1].shape[0] / data_number
information_entropy += - proportion * np.log2(proportion)
return information_entropy

我们运行上述代码,来看看具体的信息熵结果:

相比大家都了解了信息熵的概念,并能够手动计算样本集的信息熵了,现在我们再来把信息增益搬出来吧。

假设一个属性特征\(a\)有\(V\)个可能的取值\(\{a^1, a^2,.., a^V\}\),若使用\(a\)来对样本集\(D\)进行划分,这样的话就会产生\(V\)个分支节点,其中第\(v\)个 分支节点包含了\(D\)中所有在属性\(a\)上取值为\(a^V\)的样本,记为\(D^V\)。于是可计算出用属性特征\(a\)对样本集\(D\)进行划分所获得的“信息增益”(information gain)为:

\[Gain(D, a)=Ent(D)-\sum_{v=1}^V\frac{D^v}{D}Ent(D^v) \tag{2-2}
\]

以上是周志华——《机器学习》一书中对信息增益的相关说明。

枯燥的文字说明总是会降低读者的阅读欲望,上述符号也是有点多,我们不妨拿上面的贷款数据来进一步理解下上述信息增益的内容:

我们单独拿年龄这一个属性特征来计算其信息增益吧,其有青年、中年、老年三个可能的值,也就是说上述的\(a=年龄\),\(\{a^1,a^2,...,a^V\}=\{青年,中年,老年\}\),而数据样本集\(D\)为上述15个数据样本,由于年龄有三个可能的值,所以此时会产生三个分支,即\(V=3\)。之前我们已经计算得到\(Ent(D)=0.971\),现在我们只要计算出后一项\(\sum_{v=1}^V\frac{D^v}{D}Ent(D^v)\)的值即可得到该属性特征所对应的信息增益

通过数据,我们观察得到如下信息:

  • 对于年龄这个属性特征来讲,青年、中年、老年分别有5个。
  • 5个青年中有2个允许贷款,有三个不允许贷款;中年中有3个允许贷款,2个不允许贷款;老年中有4个允许贷款,有1个不允许贷款。

对此,我们可以计算:

\[\begin{aligned}
\sum_{v=1}^V\frac{D^v}{D}Ent(D^v) & = \frac{5}{15}(-\frac{2}{5}log_2\frac{2}{5}-\frac{3}{5}log_2\frac{3}{5})\\
& +\frac{5}{15}(-\frac{3}{5}log_2\frac{3}{5}-\frac{2}{5}log_2\frac{2}{5}) \\
& +\frac{5}{15}(-\frac{4}{5}log_2\frac{4}{5}-\frac{1}{5}log_2\frac{1}{5}) \\
& = 0.883
\end{aligned}
\]

对此,我们的计算处年龄这个属性特征所对应的信息增益值为:

\[Gain(D, 年龄) = 0.971-0.883=0.083
\]

我们可以把后一项的内容理解成条件概率。另外,信息增益越大,则其所对应的属性特征的分类能力也就越强,也就是我们应当优先选取的特征。

同理,我们可以计算出工作、房子、信用属性特征所对应的信息增益:

\[\begin{aligned}
& Gain(D, 工作)=0.324 \\
& Gain(D, 房子)=0.420 \\
& Gain(D, 信用)=0.363
\end{aligned}
\]

我们比较哥哥属性特征的信息增益值,可以发现房子这个属性特征最大,所以它应该是我们优先选择的属性特征。

了解了信息增益的计算及其意义,下面我们来通过代码计算一下(代码含义见注释):

import numpy as np
import pandas as pd np.__version__
pd.__version__ """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:创建训数据集
"""
def establish_data():
data = [[0, 0, 0, 0, 'N'], # 样本数据集相关信息,前面几项代表属性特征,最后一项表示是否放款
[0, 0, 0, 1, 'N'],
[0, 1, 0, 1, 'Y'],
[0, 1, 1, 0, 'Y'],
[0, 0, 0, 0, 'N'],
[1, 0, 0, 0, 'N'],
[1, 0, 0, 1, 'N'],
[1, 1, 1, 1, 'Y'],
[1, 0, 1, 2, 'Y'],
[1, 0, 1, 2, 'Y'],
[2, 0, 1, 2, 'Y'],
[2, 0, 1, 1, 'Y'],
[2, 1, 0, 1, 'Y'],
[2, 1, 0, 2, 'Y'],
[2, 0, 0, 0, 'N']]
return np.array(data) """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算信息熵
"""
def calc_information_entropy(data):
data_number, _ = data.shape
information_entropy = 0
for item in pd.DataFrame(data).groupby(_ - 1):
proportion = item[1].shape[0] / data_number
information_entropy += - proportion * np.log2(proportion)
return information_entropy """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:找出对应属性特征值的样本,比如找出所有年纪为青年的样本数据集
"""
def handle_data(data, axis, value):
result_data = list()
for item in data:
if item[axis] == value: result_data.append(item)
return result_data """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算最大的信息增益,并输出其所对应的特征索引
"""
def calc_information_gain(data):
feature_number = data.shape[1] - 1 # 属性特征的数量
base_entropy = calc_information_entropy(data) # 计算总体数据集的信息熵
max_information_gain, best_feature = 0.0, -1 # 初始化最大信息增益和对应的特征索引
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy = 0.0
for set_item in feat_set: # 计算属性特征划分后的信息增益
sub_data = handle_data(data, index, set_item)
proportion = len(sub_data) / float(data.shape[0]) # 计算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
temp_information_gain = base_entropy - new_entropy # 计算信息增益
print("第%d个属性特征所对应的的增益为%.3f" % (index + 1, temp_information_gain)) # 输出每个特征的信息增益
if (temp_information_gain > max_information_gain):
max_information_gain, best_feature = temp_information_gain, index # 更新信息增益,确定的最大的信息增益对应的索引
return best_feature if __name__ == "__main__":
data = establish_data()
print("属性特征对应的最大的信息增益对应的索引为:%d" % calc_information_gain(data))

运行上述代码,可见输出的各个属性特征的信息增益,以及最大信息增益对应的特征索引:

可以发现,和我们手动计算的如出一辙,所以此时我们应当优先选取索引为2的属性特征作为决策标准,也就是房子。

2.2 信息增益比(增益率)

我们使用信息增益作为选取特征指标的时候,存在偏向于选择取值较多的特征的问题。

比如我们将id作为上述数据集的一个分类属性,通过计算可以发现该信息增益最大,但实际上该id对类别不具有什么分类能力,所以这样得到的决策树不具有泛化能力,无法对新样本进行有效预测。

为了解决信息增益存在的这个问题,我们就引入了信息增益比(增益率)的概念,著名的C4.5算法就是用“增益率”来作为选取最优划分属性。增益率定义为:

\[Gain_ratio(D, a)=\frac{Gain(D, a)}{IV(a)} \tag{2-3}
\]
\[其中,IV(a)=-\sum_{v=1}^V\frac{|D^v|}{|D|}log_2\frac{|D^v|}{|D|} \tag{2-4}
\]

\(IV(a)\)称为\(a\)的“固有值”(intrinsic value)。通常\(a\)的取值数目越多,则\(IV(a)\)的值会越大。其中的\(a\)的取值比如说:上述的年纪有青年、中年、老年三种取值。

对于上述的贷款数据集来说,信用情况有一般、好和非常好三种,比例分为是\(\frac{5}{15}、\frac{6}{15}、\frac{4}{15}\)。毒刺,我们可以计算信用情况的“固有值”:

\[\begin{aligned}
IV(信用) & =-\sum_{v=1}^V\frac{|D^v|}{|D|}log_2\frac{|D^v|}{|D|} \\
& =-\frac{5}{15}log_2\frac{5}{15}-\frac{6}{15}log_2\frac{6}{15}-\frac{4}{15}log_2\frac{4}{15} \\
& = 1.566
\end{aligned}
\]

所以,对于信用属性来讲,其增益率为:

\[\begin{aligned}
Gain\_ratio(D, 信用) & =\frac{Gain(D, 信用)}{IV(信用)} \\
& = \frac{0.363}{1.566} \\
& = 0.232
\end{aligned}
\]

同理,我们可以计算出其他属性特征的增益率:

\[\begin{aligned}
Gain\_ratio(D, 年龄) & =0.052 \\
Gain\_ratio(D, 工作) & =0.352 \\
Gain\_ratio(D, 房子) & =0.433 \\
\end{aligned}
\]

计算增益率的具体代码可参考如下:

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算增益率
"""
def calc_gain_ratio(data):
feature_number = data.shape[1] - 1 # 属性特征的数量
base_entropy = calc_information_entropy(data) # 计算总体数据集的信息熵
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy, iv = 0.0, 0.0
for set_item in feat_set: # 计算属性特征划分后的信息增益
sub_data = handle_data(data, index, set_item)
proportion = len(sub_data) / float(data.shape[0]) # 计算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
iv += -proportion * np.log2(proportion)
temp_information_gain = base_entropy - new_entropy # 计算信息增益
gain_ratio = temp_information_gain / iv
print("第%d个属性特征所对应的增益率为%.3f,信息增益为%.3f" % (index + 1, gain_ratio, temp_information_gain)) # 输出每个特征的信息增益

运行结果如下:

在C4.5算法中,并不是直接单一的使用增益率来对属性特征的选取进行决策,而是先在信息增益中选取高于平均水平的属性作为候选,然后从候选中选取增益率最高的。

关于C4.5算法,我们后期会讲到。

2.3 基尼指数

基尼指数是另外一种选取属性的指标。

前面我们提到了,信息熵是描述数据样本纯度一个标准,而在基尼指数中的基尼值同样可以体现数据样本的纯度。数据样本集\(D\)的基尼值可以用\(Gini(D)\)来表示(其中\(k\)表示有\(k\)个标签结果):

\[Gini(D)=1-\sum_{k=1}^{|y|}p_k^2 \tag{2-5}
\]

基尼值\(Gini(D)\)越小,说明数据样本纯度越高。而属性\(a\)对应的基尼指数\(Gini\_index(D,a)\)可以定义为:

\[Gini\_index(D, a)=\sum_{v=1}^V\frac{|D^v|}{|D|}Gini(D^v) \tag{2-6}
\]

我们同样来分别计算下上述贷款数据集的基尼指数。

对于信用情况这一属性特征来讲,其基尼指数的手动计算过程如下所示:

\[\begin{aligned}
Gini\_index(D, 信用) & = \sum_{v=1}^{V}\frac{|D^v|}{|D|}Gini(D^v) \\
& = \frac{5}{15}(1-(\frac{4}{5})^2 - (\frac{1}{5})^2)+\frac{6}{15}(1-(\frac{2}{6})^2 - (\frac{4}{6})^2)+\frac{4}{15}(1-(\frac{4}{4})^2 - (\frac{0}{4})^2) \\
& =
\end{aligned}
\]

对于其他属性的基尼指数,读者可自行根据上述过程进行计算(真的很简单)。关于基尼指数的计算代码,可参考如下:

"""
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算基尼指数
"""
def calc_gini_index(data):
feature_number = data.shape[1] - 1 # 属性特征的数量
base_entropy = calc_information_entropy(data) # 计算总体数据集的信息熵
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy, iv, gini_index = 0.0, 0.0, 0.0
for set_item in feat_set: # 计算属性特征划分后的信息增益
sub_data = handle_data(data, index, set_item)
temp_df = pd.DataFrame(sub_data)
yes_proportion = temp_df[temp_df[temp_df.shape[1]-1] == "Y"].shape[0] / len(sub_data)
gini_value = 1 - (yes_proportion ** 2) - ((1- yes_proportion) ** 2)
proportion = len(sub_data) / float(data.shape[0]) # 计算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
iv += -proportion * np.log2(proportion)
gini_index += gini_value * proportion # 计算基尼指数
temp_information_gain = base_entropy - new_entropy # 计算信息增益
gain_ratio = temp_information_gain / iv
print("第%d个属性特征所对应的信息增益为%.3f,增益率为%.3f, 基尼指数为%.3f" % (index + 1, temp_information_gain, gain_ratio, gini_index))

运行结果:

以上就是基尼指数的计算及其相关代码,一般来讲,基尼指数越小就优先被划分。

上述内容的完整代码如下:

import numpy as np
import pandas as pd np.__version__
pd.__version__ """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:创建训数据集
"""
def establish_data():
data = [[0, 0, 0, 0, 'N'], # 样本数据集相关信息,前面几项代表属性特征,最后一项表示是否放款
[0, 0, 0, 1, 'N'],
[0, 1, 0, 1, 'Y'],
[0, 1, 1, 0, 'Y'],
[0, 0, 0, 0, 'N'],
[1, 0, 0, 0, 'N'],
[1, 0, 0, 1, 'N'],
[1, 1, 1, 1, 'Y'],
[1, 0, 1, 2, 'Y'],
[1, 0, 1, 2, 'Y'],
[2, 0, 1, 2, 'Y'],
[2, 0, 1, 1, 'Y'],
[2, 1, 0, 1, 'Y'],
[2, 1, 0, 2, 'Y'],
[2, 0, 0, 0, 'N']]
return np.array(data) """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算信息熵
"""
def calc_information_entropy(data):
data_number, _ = data.shape
information_entropy = 0
for item in pd.DataFrame(data).groupby(_ - 1):
proportion = item[1].shape[0] / data_number
information_entropy += - proportion * np.log2(proportion)
return information_entropy """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:找出对应属性特征值的样本,比如找出所有年纪为青年的样本数据集
"""
def handle_data(data, axis, value):
result_data = list()
for item in data:
if item[axis] == value: result_data.append(item)
return result_data """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算最大的信息增益,并输出其所对应的特征索引
"""
def calc_information_gain(data):
feature_number = data.shape[1] - 1 # 属性特征的数量
base_entropy = calc_information_entropy(data) # 计算总体数据集的信息熵
max_information_gain, best_feature = 0.0, -1 # 初始化最大信息增益和对应的特征索引
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy = 0.0
for set_item in feat_set: # 计算属性特征划分后的信息增益
sub_data = handle_data(data, index, set_item)
proportion = len(sub_data) / float(data.shape[0]) # 计算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
temp_information_gain = base_entropy - new_entropy # 计算信息增益
print("第%d个属性特征所对应的的增益为%.3f" % (index + 1, temp_information_gain)) # 输出每个特征的信息增益
if (temp_information_gain > max_information_gain):
max_information_gain, best_feature = temp_information_gain, index # 更新信息增益,确定的最大的信息增益对应的索引
return best_feature """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算增益率
"""
def calc_gain_ratio(data):
feature_number = data.shape[1] - 1 # 属性特征的数量
base_entropy = calc_information_entropy(data) # 计算总体数据集的信息熵
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy, iv = 0.0, 0.0
for set_item in feat_set: # 计算属性特征划分后的信息增益
sub_data = handle_data(data, index, set_item)
proportion = len(sub_data) / float(data.shape[0]) # 计算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
iv += -proportion * np.log2(proportion)
temp_information_gain = base_entropy - new_entropy # 计算信息增益
gain_ratio = temp_information_gain / iv
print("第%d个属性特征所对应的增益率为%.3f,信息增益为%.3f" % (index + 1, gain_ratio, temp_information_gain)) # 输出每个特征的信息增益 """
Author: Taoye
微信公众号: 玩世不恭的Coder
Explain:计算基尼指数
"""
def calc_gini_index(data):
feature_number = data.shape[1] - 1 # 属性特征的数量
base_entropy = calc_information_entropy(data) # 计算总体数据集的信息熵
for index in range(feature_number):
feat_list = [item[index] for item in data]
feat_set = set(feat_list)
new_entropy, iv, gini_index = 0.0, 0.0, 0.0
for set_item in feat_set: # 计算属性特征划分后的信息增益
sub_data = handle_data(data, index, set_item)
temp_df = pd.DataFrame(sub_data)
yes_proportion = temp_df[temp_df[temp_df.shape[1]-1] == "Y"].shape[0] / len(sub_data)
gini_value = 1 - (yes_proportion ** 2) - ((1- yes_proportion) ** 2)
proportion = len(sub_data) / float(data.shape[0]) # 计算子集的比例
new_entropy += proportion * calc_information_entropy(np.array(sub_data))
iv += -proportion * np.log2(proportion)
gini_index += gini_value * proportion
temp_information_gain = base_entropy - new_entropy # 计算信息增益
gain_ratio = temp_information_gain / iv
print("第%d个属性特征所对应的信息增益为%.3f,增益率为%.3f, 基尼指数为%.3f" % (index + 1, temp_information_gain, gain_ratio, gini_index)) if __name__ == "__main__":
data = establish_data()
calc_gini_index(data)

优先选取属性特征的指标主要有三个,分别是信息增益、增益率、基尼指数。对上述内容做个简单的总结吧:

  • 属性特征的信息增益越高,按道理来讲应当被优先选取,常用于\(ID3\)算法
  • 属性特征的增益率越高,按道理来讲应当被优先选取,常用与\(C4.5\)算法
  • 属性特征的尼基指数低,按道理来讲应当被优先选取,常用于\(CART\)算法

本文主要是决策树的理论部分内容,介绍了什么决策树,以及生成决策树时所需要优先选取的三种决策标准。有学习的过SVM,或阅读过Taoye之前写的几篇SVM内容的文章可以发现,决策树相对于SVM来讲要简单很多,没有太多且复杂的公式推导。关于决策树的其他内容,比如决策树的生成、可视化、剪枝等,我们放在后面几篇文章来写。

我是Taoye,爱专研,爱分享,热衷于各种技术,学习之余喜欢下象棋、听音乐、聊动漫,希望借此一亩三分地记录自己的成长过程以及生活点滴,也希望能结实更多志同道合的圈内朋友,更多内容欢迎来访微信公主号:玩世不恭的Coder

最新文章

  1. VMware创建Linux虚拟机并安装CentOS(一)
  2. jquery记住密码,记住账号,自动登录
  3. 翻译:深入 AngularUI Router
  4. [转]修改maven本地仓库路径
  5. Iptables網路連線限制及攻擊防護和相關設定
  6. jquery easyui的datagrid在初始化的时候会请求两次URL?
  7. Atom的追踪函数插件和自定义语法
  8. android应用资源预编译,编译和打包全解析
  9. PHP异步请求
  10. Java 基本语法,标识符,修饰符,关键字
  11. JavaScript中的ononline事件和onoffline事件
  12. 阿里云 ECS centos java timer进程异常/混乱......的解决方法
  13. js同步-异步-回调
  14. Navicat(数据库可视化操作软件)安装、配置、测试
  15. Linux基础命令---sysctl修改内核参数
  16. uva-10041-水题
  17. idea_2018.1.5版本的激活使用
  18. [leetcode]Text Justification @ Python
  19. AIX6.1配置etherchannel
  20. PAT乙级1016

热门文章

  1. selenium基础--五种定位方式
  2. Spring源码解析之基础应用(三)
  3. Seaborn中几种作图方式
  4. git -- Authentication failed for 报错如何解决?
  5. python自测100题
  6. 第12天 | 12天搞定Python,让excel飞起来
  7. 普通人如何站在时代风口学好AI?这是我看过最好的答案
  8. c语言创建dll以及使用
  9. 修改Anaconda中Jupyter Notebook默认工作路径
  10. C语言实例-能组成多少个三位数?