决策树采用的是信息熵或者Gini系数来作为分类标准。
信息熵公式:
Gini系数公式:
一般构造一个分类器(sklearn.tree.DecisionTreeClassifier),默认参数criterion有{“gini”, “entropy”}, 其中default=”gini”。这两个计算公式不一样而已。
我在这里计算的是信息熵的公式,另外的一个也都一样,换一个公式而已。
我们在提到概率问题的时候都会有一个前提假设,假设这些变量或者特征都是相互之间没有关系的,就不会存在组合的情况,不然就没办法计算概率了
信息熵它是用来描述信息的紊乱程度,也就是不确定度。当所有数据都是一种类别的时候,他的紊乱度为0,也就是信息熵为0.信息熵可以大于1,通过公式可以看出,这里的log是以2为底。
比如有一组数据(1,1,1,1,0,0,0,0),四个1四个0,他的信息熵是多少?
通过公式我们先计算1出现概率为1/2,那么有 -1/2*(log(1/2)),
再计算0出现概率为1/2,那么有 -1/2*(log(1/2))。接着把他们求和就是-1.这就是这组数的信息熵。
如果是[1,1,1,1,2,2,2,2,3,3,3,3]也是一样的计算方法:
-1/3 * log(1/3) -1/3 * log(1/3) -1/3 * log(1/3)
有几个种类就计算几次,求和即可。
当我们用决策树对数据进行分类的时候,因为他基于CART算法,所以是一个二叉树。
CART(分类树和回归树)与C4.5非常相似,但是区别在于它支持数字目标变量(回归)并且不计算规则集。CART使用在每个节点处产生最大信息增益的特征和阈值构造二叉树。
可以看出我们分类的时候就是找到这个能够有最大信息增益的阈值,最大信息增益就是上一次的信息熵减去分类后的信息熵,也就是找出分类后信息熵最小化的那个阈值。那么怎么找到这个值呢?当然要一个一个试。因为就算是人都不会一眼就看出来,更别说计算机了。
我们一鸢尾花的数据为例,因为这个我们很熟悉
import numpy as np
from sklearn.tree import DecisionTreeClassifier
import sklearn.datasets as datasets
iris = datasets.load_iris()
# 我们使用全部的数据进行计算。因为我们主要不是为了做预测
X = iris["data"]
y = iris["target"]
# 构造分类器,使用entropy,也就是信息熵计算分类
clf = DecisionTreeClassifier(criterion="entropy")
clf.fit(X,y)
这时候其实决策树已经分好了。因为决策树是可以被看见的。我们把他到处到PDF文件。
from sklearn import tree
# graphviz要pip 另外还得去官网下载一个安装文件配一下环境变量
import graphviz
g = tree.export_graphviz(clf,out_file=None,filled=True)
graph = graphviz.Source(g)
graph.render(filename='iris')
这个代码会生成一个PDF文件。里面就是我们绘制的二叉树的图形。
如下:

可以看出他根据哪一个类别(比如第一次划分X[3]就是第四个特征。取得阈值为0.8,信息熵为1.585是原来的信息熵)
我们先来计算一下原数据的信息熵:
这里我们把数据转换成Dataframe,方便后面分类查找。
import pandas as pd
df_iris = pd.DataFrame(iris['data'])
df_iris["目标"] = iris["target"]
# 更改一下列明,我们容易一目了然
df_iris.rename({0:"特征1",1:"特征2",2:"特征3",3:"特征4"},axis=1,inplace=True)
# 这个是一共有哪几个种类,我们先记下来
y_zl = df_iris['目标'].unique()
#查看下数据格式
df_iris.head()

# 定义一个函数,输入是一个dataframe,输出这个dataframe目标值的信息熵。
def entropy(df):
entropy_ = 0
# 这个dataframe中的总行数。
rownum = df.shape[0]
# 便利每一个种类,求出他们的概率再求出单个种类的信息熵。最后累加
for i in range(len(y_zl)):
cond = df['目标']==y_zl[i]
p = df[cond].shape[0]/rownum
entropy_ += (-1)*p*np.log2(p)
return entropy_
那么原数据:
entropy(df_iris)
1.584962500721156
四舍五入后,和上面PDF中1.585是一样的。
可以看出经过X[3]也就是第四个特征值取0.8的阈值二分后,有最大的信息增益。
那么怎么求出来他?
- 首先他肯定不会第一眼看出来以特征4划分,所以每一个特征都要计算。、
- 在每一个特征里,取特征值里的一个最大值和一个最小值,然后从最小的开始按照设定的step往上走,一个一个值计算。
- 直到遍历完,这时候就会有信息熵最小的那一个数被保存下来,也就是信息增益最大的数。这就是我们要找的阈值。
我把数据转成dataframe是因为我用query方法查找子视图很方便。
这时候我们上面 那一个方法就不够用了。我们在写一个方法:
# 我们要给他一个dataframe和一个特征(tz缩写)列。
def df_entropy(df,tz):
#去除数据中的两个最值
xmin = df[tz].min()
xmax = df[tz].max()
# 先给一个默认的最佳阈值
besti = 100
# 给一个默认的最小信息熵
bestentropy = 100
#这里因为数据都是小数点后一位数,所以我设定的step为0.05.肯定能便利到每一个值
for i in np.arange(xmin,xmax,0.05):
i = i.round(2)
#根据阈值划分两个条件,一个大于一个小于等于,把数据分成两边
cond1 = tz+">"+str(i)
cond2 = tz+"<="+str(i)
# 在用上面的函数分别计算划分后的两个子视图的信息熵。然后再按比例求和得到最终的信息熵
#注意这里是按比例求和。因为如果你分的两边,一个占90%,一个占10%,那么就是0.9*占比90的信息熵
#再加上0.1*占比10的信息熵,这就是这个的总信息熵
ent1 = entropy(df.query(cond1))
ent2 = entropy(df.query(cond2))
ent = (df.query(cond1).shape[0]/df.shape[0])*ent1 + (df.query(cond2).shape[0]/df.shape[0])*ent2
if bestentropy>=ent:
bestentropy = ent
besti = i
# 最终返回最合适的阈值,和最小的信息熵
return besti,bestentropy
#输入一个dataframe,然后调用上面的函数得出最终结果。
def cross_entropy(df):
cols = df.columns[0:-1]
best = {"bestcol":'',"besti":100,"bestentropy":100}
#遍历列,得出哪一个列中哪个阈值为最佳
for col in cols:
i,ent = df_entropy(df,col)
if best["bestentropy"]>=ent:
best["bestentropy"] = ent
best["besti"] = i
best["bestcol"] = col
return best
最后就是验证我们的函数。
cross_entropy(df_iris)
{‘bestcol’: ‘特征4’, ‘besti’: 0.95, ‘bestentropy’: 0.6666666666666666}
我们自己的算法得出的结论是第一个分类选特征4的阈值为0.95最佳。
可是PDF图中第一个是0.8为阈值。
其实这里选择特征4的阈值为0.8到0.95之间的任何一个值都是一样的,因为他把一个种类单独分来了,只剩下了另外两种。所以特征4很好的甄别了这个种类的画。
再计算一个。PDF第二行右边的是根据特征4分开的,我们令:
df1 = df_iris.query('特征4>0.8')
display(entropy(df1))
cross_entropy(df1)
1.0
{‘bestcol’: ‘特征4’, ‘besti’: 1.75, ‘bestentropy’: 0.30983962924532515}
本身的信息熵为1.0,并且选择X[3]也就是特征4的阈值我1.75。和PDF中正好吻合。
接着继续计算下去,都是吻合的。也是这种计算方法。直到最后的信息熵为0就是纯度最高,不用再分下去了。
所以如果我们没有写好的算法,我们自己也能够根据信息熵或者基尼系数把他分好类别。
这里只介绍公式计算方法,不针对他的准确性。他也是一种基础,为学习其他算法打基础。
因为树的种类有很多,最基础的决策二叉树了解了,后面的也会慢慢的就水到渠成。
最后:
以下优缺点摘自sklearn官网
决策树的一些优点是:
- 易于理解和解释。树木可以可视化。
- 需要很少的数据准备。其他技术通常需要数据规范化,需要创建伪变量并删除空白值。但是请注意,此模块不支持缺少的值。
- 使用树的成本(即预测数据)与用于训练树的数据点数量成对数。
- 能够处理数字和分类数据。其他技术通常专用于分析仅具有一种类型的变量的数据集。有关更多信息,请参见算法。
- 能够处理多输出问题。
- 使用白盒模型。如果模型中可以观察到给定的情况,则可以通过布尔逻辑轻松解释条件。相反,在黑匣子模型中(例如,在人工神经网络中),结果可能更难以解释。
- 可以使用统计测试来验证模型。这使得考虑模型的可靠性成为可能。
- 即使生成数据的真实模型在某种程度上违反了它的假设,也可以表现良好。
决策树的缺点包括:
- 决策树学习者可能会创建过于复杂的树,从而无法很好地概括数据。这称为过度拟合。为避免此问题,必须使用诸如修剪,设置叶节点处所需的最小样本数或设置树的最大深度之类的机制。
- 决策树可能不稳定,因为数据中的细微变化可能会导致生成完全不同的树。通过使用集成中的决策树可以缓解此问题。
- 在最优性的几个方面,甚至对于简单的概念,学习最优决策树的问题都被认为是NP完全的。因此,实用的决策树学习算法基于启发式算法(例如贪婪算法),其中在每个节点上做出局部最优决策。这样的算法不能保证返回全局最优决策树。可以通过在集成学习器中训练多棵树来缓解这种情况,在该学习器中,特征和样本将通过替换随机抽样。
- 有些概念很难学习,因为决策树无法轻松表达它们,例如XOR,奇偶校验或多路复用器问题。
- 如果某些类别占主导地位,决策树学习者会创建有偏见的树。因此,建议在与决策树拟合之前平衡数据集。
本文介绍了决策树算法中信息熵的计算方法及其在分类过程中的作用。通过鸢尾花数据集的例子,展示了如何寻找最大信息增益的阈值来构建决策树,解释了决策树的优点和缺点,如易于理解、处理不同类型数据以及易过拟合等问题。
5423

被折叠的 条评论
为什么被折叠?



