1.决策树C4.5算法

article/2025/10/14 22:34:39

文章目录

  • 一、概述
  • 二、改进表现
  • 三、优缺点
  • 四、决策树
    • 1.特征选择
    • 2.决策树的生成
    • 3.决策树的剪枝

一、概述

    C4.5是一系列用在机器学习和数据挖掘的分类问题中的算法。它的目标是监督学习:给定一个数据集,其中的每一个元组都能用一组属性值来描述,每一个元组属于一个互斥的类别中的某一类。C4.5的目标是通过学习,找到一个从属性值到类别的映射关系,并且这个映射能用于对新的类别未知的实体进行分类。

    C4.5由J.Ross Quinlan在ID3的基础上提出的。ID3算法用来构造决策树。决策树是一种类似流程图的树结构,其中每个内部节点(非树叶节点)表示在一个属性上的测试,每个分枝代表一个测试输出,而每个树叶节点存放一个类标号。一旦建立好了决策树,对于一个未给定类标号的元组,跟踪一条有根节点到叶节点的路径,该叶节点就存放着该元组的预测。

    决策树的优势在于不需要任何领域知识或参数设置,适合于探测性的知识发现。从ID3算法中衍生出了C4.5CART两种算法。

二、改进表现

    (1)ID3算法在选择根节点和各内部节点中的分支属性时,采用信息增益作为评价标准。信息增益的缺点是倾向于选择取值较多的属性,而这类属性并不一定是最优的属性。在这里插入图片描述    (2)在决策树构造过程中进行剪枝,因为某些具有很少元素的结点可能会使构造的决策树过适应(Overfitting),如果不考虑这些结点可能会更好;

    (3)能够处理离散型连续型的属性类型,即将连续型的属性进行离散化处理;

    (4)能够处理具有缺失属性值的训练数据。

三、优缺点

    优点:产生的分类规则易于理解,准确率较高。

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

    过拟合的原因:在于学习时过多的考虑如何提高对训练数据的正确分类,从而构建出过于复杂的决策树。

四、决策树

    决策树是一种用于分类的树结构。如图所示,它由结点(node)和有向边(directed edge)组成,结点包括内部结点(internal node)和叶结点(leaf node),内部结点表示一个特征或属性,叶结点表示一个类。
在这里插入图片描述

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

    决策树如何进行分类呢?从根结点开始,根据待分类数据的某一特征值对其进行划分,分配到相应子结点,因此,每一个子结点都对应了该特征的一个取值。像这样递归进行,直到到达叶结点。

1.特征选择

    特征选择在于选取对训练数据具有良好分类能力的特征,这样可以提高决策树的学习效率。通常特征选择的准则是信息增益或信息增益比。

(1)熵

    在信息论和概率统计中,熵是表示随机变量不确定性的度量。设X是一个取有限个值得离散随机变量,其概率分布为:

P ( X = x i ) = p i , i = 1 , 2 , 3 , . . . , n P(X=x_i) =p_i,i=1,2,3,...,n P(X=xi)=pi,i=1,2,3,...,n

    则随机变量X的熵定义为:

H ( X ) = − ∑ i = 1 n p i l o g p i H(X)= -\displaystyle\sum_{i=1}^{n} p_ilogp_i H(X)=i=1npilogpi

    熵越大,随机变量的不确定性就越大。

(2)条件熵

    设有随机变量(X,Y)其联合概率分布为:

P ( X = x i , Y = y i ) = p i j , i = 1 , 2 , 3 , . . . , n , j = 1 , 2 , 3 , . . . , n P(X=x_i,Y=y_i) =p_{ij},i=1,2,3,...,n,j=1,2,3,...,n P(X=xi,Y=yi)=pij,i=1,2,3,...,n,j=1,2,3,...,n

     条件熵H(Y∣X) 表示在已知随机变量X的条件下随机变量Y 的不确定性,定义为X 给定条件下Y 的条件概率分布的熵对X 的数学期望:
H ( Y ∣ X ) = ∑ i = 1 n p i H ( Y ∣ X = x i ) H(Y|X)= \displaystyle\sum_{i=1}^{n} p_iH(Y|X=x_i) H(YX)=i=1npiH(YX=xi)
p i = P ( X = x i ) , i = 1 , 2 , 3 , . . . , n p_i=P(X=x_i),i=1,2,3,...,n pi=P(X=xi),i=1,2,3,...,n

(3)经验熵和经验条件熵

    当熵和条件熵中的概率由数据估计(特别是极大似然估计)得到时,对应的熵与条件熵分别称为经验熵和经验条件熵。

(4)信息增益

    信息增益表示得知特征X 的信息后特征Y 的信息不确定性减少的程度,反应了特征X对于其他特征不确定性的影响程度。

    信息增益:特征A对训练数据集D的信息增益 g ( D , A ) g(D,A) g(D,A),定义为集合D的经验熵H(D)与特征A给定条件下D的经验条件熵 H ( D ∣ A ) H(D|A) H(DA)之差,即:

g ( D , A ) = H ( D ) − H ( D ∣ A ) g(D,A)= H(D)-H(D|A) g(D,A)=H(D)H(DA)

    根据信息增益准则的特征选择方法是:对训练数据集(或子集)D,计算其每个特征的信息增益,并比较它们的大小,选择信息增益最大的特征。

    设训练数据集为D,|D|表示其样本容量,即样本个数。设有K个类 C k C_k Ck k = 1 , 2 , … , K k=1,2,…,K k1,2,,K ∣ C k ∣ |C_k| Ck为属于类 C k C_k Ck的样本个数, ∑ i = 1 n ∣ C k ∣ = ∣ D ∣ \displaystyle\sum_{i=1}^{n} |C_k|=|D| i=1nCk=D。设特征A有n个不同的取值 a 1 , a 2 , … , a n {a_1,a_2, …,a_n} a1,a2,,an,根据特征A的取值将D划分为n个子集 D 1 , D 2 , … , D n D_1,D_2,…,D_n D1,D2,,Dn ∣ D i ∣ |D_i| Di为Di的样本个数, ∑ i = 1 n ∣ D i ∣ = ∣ D ∣ \displaystyle\sum_{i=1}^{n} |D_i|=|D| i=1nDi=D

ID3信息增益算法:

输入:训练数据集D和特征A;
输出:特征A对训练数据集D的信息增益 g ( D ∣ A ) g(D|A) g(DA);

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

H ( D ) = − ∑ k = 1 K ∣ C k ∣ ∣ D ∣ l o g 2 ∣ C k ∣ ∣ D ∣ H(D)= -\displaystyle\sum_{k=1}^{K} \frac{|C_k|}{|D|}log_2\frac{|C_k|}{|D|} H(D)=k=1KDCklog2DCk
    
(2)计算特征A对数据集D的经验条件熵H(D|A)

H ( D ∣ A ) = ∑ i = 1 n ∣ D i ∣ ∣ D ∣ H ( D i ) = − ∑ i = 1 n ∣ D i ∣ ∣ D ∣ ∑ k = 1 K ∣ D i k ∣ ∣ D i ∣ l o g 2 ∣ D i k ∣ ∣ D i ∣ H(D|A)=\displaystyle\sum_{i=1}^{n} \frac{|D_i|}{|D|}H(D_i)= -\displaystyle\sum_{i=1}^{n} \frac{|D_i|}{|D|}\displaystyle\sum_{k=1}^{K} \frac{|D_{ik}|}{|D_i|}log_2 \frac{|D_{ik}|}{|D_i|} H(DA)=i=1nDDiH(Di)=i=1nDDik=1KDiDiklog2DiDik

(3)计算信息增益

g ( D , A ) = H ( D ) − H ( D ∣ A ) g(D,A)= H(D)-H(D|A) g(D,A)=H(D)H(DA)

(5)信息增益比

    以信息增益作为选择特征的准则,存在偏向于选择取值较多的特征的问题。即当一个特征可能的取值较多时,其计算出来的信息增益可能会较高,但是并不一定就一定是一个更有效的分类特征。采用信息增益比可以对这一问题进行校正,这是特征选择的另一准则。

    特征A对训练数据集D的信息增益比 g R ( D , A ) g_R(D,A) gR(D,A)定义为其信息增益 g ( D , A ) g(D,A) g(D,A)与训练数据集D的经验熵 H ( D ) H(D) H(D)之比:

g R ( D , A ) = g ( D , A ) H ( D ) g_R(D,A)=\frac{g(D,A)}{H(D)} gR(D,A)=H(D)g(D,A)

C4.5信息增益算法:

输入:训练数据集D和特征A;
输出:特征A对训练数据集D的信息增益 g ( D ∣ A ) g(D|A) g(DA);

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

H ( D ) = − ∑ k = 1 K ∣ C k ∣ ∣ D ∣ l o g 2 ∣ C k ∣ ∣ D ∣ H(D)= -\displaystyle\sum_{k=1}^{K} \frac{|C_k|}{|D|}log_2\frac{|C_k|}{|D|} H(D)=k=1KDCklog2DCk
    
(2)计算特征A对数据集D的经验条件熵H(D|A)

H ( D ∣ A ) = ∑ i = 1 n ∣ D i ∣ ∣ D ∣ H ( D i ) = − ∑ i = 1 n ∣ D i ∣ ∣ D ∣ ∑ k = 1 K ∣ D i k ∣ ∣ D i ∣ l o g 2 ∣ D i k ∣ ∣ D i ∣ H(D|A)=\displaystyle\sum_{i=1}^{n} \frac{|D_i|}{|D|}H(D_i)= -\displaystyle\sum_{i=1}^{n} \frac{|D_i|}{|D|}\displaystyle\sum_{k=1}^{K} \frac{|D_{ik}|}{|D_i|}log_2 \frac{|D_{ik}|}{|D_i|} H(DA)=i=1nDDiH(Di)=i=1nDDik=1KDiDiklog2DiDik
    
(3)计算信息增益

g ( D , A ) = H ( D ) − H ( D ∣ A ) g(D,A)= H(D)-H(D|A) g(D,A)=H(D)H(DA)

(4)计算信息增益比

g R ( D , A ) = g ( D , A ) H ( D ) g_R(D,A)=\frac{g(D,A)}{H(D)} gR(D,A)=H(D)g(D,A)

2.决策树的生成

ID3算法的核心是在决策树各个节点上应用信息增益准则选择特征,递归的构建决策树。

ID3算法决策树的生成

输入:训练数据集D,特征集A,阈值 ε \varepsilon ε
输出:决策树T。

(1)若D中所有实例属于同一类 C k C_k Ck,则T为单结点树,并将类 C k C_k Ck作为该结点的类标记, 返回T;
(2)若A=Ø,则T为单结点树,并将D中实例数最大的类 C k C_k Ck作为该结点的类标记,返回 T;
(3)否则,按ID3信息增益算法计算A中各特征对D的信息增益,选择信息增益最大的特征Ag;
(4)如果Ag的信息增益小于阈值 ε \varepsilon ε ,则置T为单结点树,并将D中实例数最大的类 C k C_k Ck作为该结点的类标记,返回T;
(5)否则,对Ag的每一可能值 a i a_i ai,依Ag= a i a_i ai将D分割为若干非空子集 D i D_i Di,将 D i D_i Di中实例数 最大的类作为标记,构建子结点,由结点及其子结点构成树T,返回T;
(6)对第i个子结点,以 D i D_i Di为训练集,以A-{Ag}为特征集,递归地调用步1~步5,得到子树 T i T_i Ti,返回 T i T_i Ti

ID年龄有工作有自己的房子信贷情况类别
1青年一般
2青年
3青年
4青年
5青年一般
6中年
7中年
8中年
9中年非常好
10中年非常好
11老年非常好
12老年
13老年
14老年非常好
15老年一般

统计学习方法例题ID3算法数学实现:

(1)计算经验熵:

H ( D ) = − 9 15 l o g 2 9 15 − 6 15 l o g 2 6 15 = 0.971 H(D) = -\frac{9}{15}log_2\frac{9}{15}-\frac{6}{15}log_2\frac{6}{15}=0.971 H(D)=159log2159156log2156=0.971

(2)计算条件经验熵:

分别以A1,A2,A3,A4表示年龄、有工作、 有自己的房子和信贷情况4个特征,则:

H ( D ∣ A 1 ) = ∑ i = 1 n ∣ D i ∣ ∣ D ∣ H ( D i ) = 5 15 H ( D 1 ) + 5 15 H ( D 2 ) + 5 15 H ( D 3 ) = 5 15 ( − 2 5 l o g 2 2 5 − 3 5 l o g 2 3 5 ) + 5 15 ( − 3 5 l o g 2 3 5 − 2 5 l o g 2 2 5 ) + 5 15 ( − 4 5 l o g 2 4 5 − 1 5 l o g 2 1 5 ) = 0.888 H(D|A_1)=\displaystyle\sum_{i=1}^{n} \frac{|D_i|}{|D|}H(D_i)= \frac{5}{15}H(D_1)+\frac{5}{15}H(D_2)+\frac{5}{15}H(D_3)=\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.888 H(DA1)=i=1nDDiH(Di)=155H(D1)+155H(D2)+155H(D3)=155(52log25253log253)+155(53log25352log252)+155(54log25451log251)=0.888

同理:

H ( D ∣ A 2 ) = 0.674 H(D|A_2)=0.674 H(DA2)=0.674
H ( D ∣ A 3 ) = 0.551 H(D|A_3)=0.551 H(DA3)=0.551
H ( D ∣ A 4 ) = 0.608 H(D|A_4)=0.608 H(DA4)=0.608

(3)计算信息增益:

g ( D , A 1 ) = H ( D ) − H ( D ∣ A 1 ) = 0.971 − 0.888 = 0.083 g(D,A_1)= H(D)-H(D|A_1)=0.971-0.888=0.083 g(D,A1)=H(D)H(DA1)=0.9710.888=0.083
g ( D , A 2 ) = H ( D ) − H ( D ∣ A 1 ) = 0.971 − 0.674 = 0.324 g(D,A_2)= H(D)-H(D|A_1)=0.971-0.674=0.324 g(D,A2)=H(D)H(DA1)=0.9710.674=0.324
g ( D , A 3 ) = H ( D ) − H ( D ∣ A 1 ) = 0.971 − 0551 = 0.420 g(D,A_3)= H(D)-H(D|A_1)=0.971-0551=0.420 g(D,A3)=H(D)H(DA1)=0.9710551=0.420
g ( D , A 4 ) = H ( D ) − H ( D ∣ A 1 ) = 0.971 − 0.608 = 0.363 g(D,A_4)= H(D)-H(D|A_1)=0.971-0.608=0.363 g(D,A4)=H(D)H(DA1)=0.9710.608=0.363

最后,比较各特征的信息增益值。由于特征A3(有自己的房子)的信息增益值最大,所 以选择特征A3作为最优特征。

python代码实现:

from math import log
import operatordef loadDataSet():dataSet = [['青年', '否', '否', '一般', '否'],['青年', '否', '否', '好', '否'],['青年', '是', '否', '好', '是'],['青年', '是', '是', '一般', '是'],['青年', '否', '否', '一般', '否'],['中年', '否', '否', '一般', '否'],['中年', '否', '否', '好', '否'],['中年', '是', '是', '好', '是'],['中年', '否', '是', '非常好', '是'],['中年', '否', '是', '非常好', '是'],['老年', '否', '是', '非常好', '是'],['老年', '否', '是', '好', '是'],['老年', '是', '否', '好', '是'],['老年', '是', '否', '非常好', '是'],['老年', '否', '否', '一般', '否']]label = ['年龄', '有工作', '有自己的房子', '信贷情况']return dataSet, label#计算数据集的香农熵
def calcShannonEnt(dataSet):numEntries = len(dataSet)                            #求出数据有多少个对象,即有多少行,计算实例总数labelCount = {}for featVec in dataSet:                              #对数据集逐行求最后一类的数据,并将统计最后一列数据的数目classify = featVec[-1]if classify not in labelCount.keys():       #创建一个字典,键值是最后一列的数值labelCount[classify]=1#当前键值不存在,则扩展字典并将此键值加入字典else:labelCount[classify] += 1                  #每个键值都记录了当前类别出现的次数shannonEnt = 0.0for key in labelCount:prob = float(labelCount[key])/numEntries       #使用统计出的最后一列的数据来计算所有类标签出现的概率shannonEnt -= prob * log(prob,2)                #下面的公式return shannonEnt#按照获取最大信息增益的方法来划分数据集
def splitDataSet(dataSet, axis, value):retDataSet = []for featVec in dataSet:if featVec[axis] == value:                        #判断axis列的值是否为valuereducedFeatVec = featVec[:axis]               #[:axis]表示前axis行,即若axis为2,就是取featVec的前axis行reducedFeatVec.extend(featVec[axis+1:])       #[axis+1:]表示从跳过axis+1行,取接下来的数据retDataSet.append(reducedFeatVec)return retDataSet#遍历整个数据集,找到最好的特征划分方式
def chooseBestFeatureToSplitForID3(dataSet):numFeatures = len(dataSet[0]) - 1#特征个数baseEntropy = calcShannonEnt(dataSet)#数据集dataSet的熵bestInfoGain = 0.0#最优信息增益bestFeature = -1#最优特征for i in range(numFeatures):#对于每一个特征列featList = [example[i] for example in dataSet]#获取该特征列的uniqueVals = set(featList)#获得该特征的所有唯一特征值newEntropy = 0.0#i特征的信息熵for value in uniqueVals:subDataSet = splitDataSet(dataSet, i, value)#按照i特征的value唯一特征值--拆分数据集prob = len(subDataSet)/float(len(dataSet))#新数据集占总数据的比例newEntropy += prob * calcShannonEnt(subDataSet)#给定特征i的数据集dataSet的条件熵infoGain = baseEntropy - newEntropy#按照i特征划分的信息增益(数据集dataSet的熵-给定特征i的数据集dataSet的条件熵)if (infoGain > bestInfoGain):bestInfoGain = infoGainbestFeature = i    #判断出哪种划分方式得到最大的信息增益,且得出该划分方式所选择的特征# print('最优特征是:', label[bestFeature])return bestFeature#频率最高的类别函数 判断递归何时结束
def majorityCnt(classList):                 #参数classList在下面创建树的代码里,是每一行的最后一个特征classCount = {}for vote in classList:                   #将特征里的元素添加到新建的字典里作为键值,并统计该键值出现次数if vote not in classCount.keys(): classCount[vote] = 0classCount[vote] += 1sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)return sortedClassCount[0][0]           #返回出现次数最多的键值#创建决策树
def createTree(dataSet, labels):classList = [example[-1] for example in dataSet]if len(set(classList)) == 1:#if 数据集中的每个子项的类别完全相同:return 该类别return classList[0]if len(dataSet[0]) == 0: #if 遍历完所有的特征:return 频率最高的类别return majorityCnt(classList)# 寻找划分数据集的最好特征 #获取当前数据集合和标签列表的最优特征维度bestFeat = chooseBestFeatureToSplitForID3(dataSet)# 最优特征维度对应的标签值bestFeatLabel = labels[bestFeat]# 创建分支节点myTree = {bestFeatLabel: {}}del (labels[bestFeat])# 划分数据集featValues = [example[bestFeat] for example in dataSet]# print(set(featValues))# for 每个划分的子集for value in set(featValues):# 调用createTree()并且增加返回结果到分支节点中subLabels = labels[:]subDataSet = splitDataSet(dataSet, bestFeat, value)myTree[bestFeatLabel][value] = createTree(subDataSet, subLabels)# return 分支节点return myTreedataSet, label = loadDataSet()
print(createTree(dataSet, label))

运行结果:
在这里插入图片描述

C4.5算法:与ID3算法相似,不同是用信息增益比来选择特征。

C4.5算法决策树生成:

输入:训练数据集D,特征集A,阈值 ε \varepsilon ε
输出:决策树T。
(1)如果D中所有实例属于同一类 C k C_k Ck,则置T为单结点树,并将 C k C_k Ck作为该结点的类,返 回T;
(2)如果A=Ø,则置T为单结点树,并将D中实例数最大的类 C k C_k Ck作为该结点的类,返回 T;
(3)否则,计算A中各特征对D的信息增益比,选择信息增益比最大的特征Ag;
(4)如果Ag的信息增益比小于阈值 ε \varepsilon ε ,则置T为单结点树,并将D中实例数最大的类 C k C_k Ck作为该结点的类,返回T;
(5)否则,对Ag的每一可能值 a i a_i ai,依Ag= a i a_i ai将D分割为子集若干非空 D i D_i Di,将 D i D_i Di中实例数 最大的类作为标记,构建子结点,由结点及其子结点构成树T,返回T;
(6)对结点i,以 D i D_i Di为训练集,以A-{Ag}为特征集,递归地调用步(1)~步(5),得到子树Ti,返回 T i T_i Ti

统计学习方法例题c4.5算法python代码实现:

from math import log
import numpy as np
import pandas as pd
import operatordef loadDataSet():dataSet = [['青年', '否', '否', '一般', '否'],['青年', '否', '否', '好', '否'],['青年', '是', '否', '好', '是'],['青年', '是', '是', '一般', '是'],['青年', '否', '否', '一般', '否'],['中年', '否', '否', '一般', '否'],['中年', '否', '否', '好', '否'],['中年', '是', '是', '好', '是'],['中年', '否', '是', '非常好', '是'],['中年', '否', '是', '非常好', '是'],['老年', '否', '是', '非常好', '是'],['老年', '否', '是', '好', '是'],['老年', '是', '否', '好', '是'],['老年', '是', '否', '非常好', '是'],['老年', '否', '否', '一般', '否']]label = ['年龄', '有工作', '有自己的房子', '信贷情况']return dataSet, label#计算数据集的香农熵
def calcShannonEnt(dataSet):numEntries = len(dataSet)                            #求出数据有多少个对象,即有多少行,计算实例总数labelCount = {}for featVec in dataSet:                              #对数据集逐行求最后一类的数据,并将统计最后一列数据的数目classify = featVec[-1]if classify not in labelCount.keys():       #创建一个字典,键值是最后一列的数值labelCount[classify]=1#当前键值不存在,则扩展字典并将此键值加入字典else:labelCount[classify] += 1                  #每个键值都记录了当前类别出现的次数shannonEnt = 0.0for key in labelCount:prob = float(labelCount[key])/numEntries       #使用统计出的最后一列的数据来计算所有类标签出现的概率shannonEnt -= prob * log(prob,2)                #下面的公式return shannonEnt#按照获取最大信息增益的方法来划分数据集
def splitDataSet(dataSet, axis, value):retDataSet = []for featVec in dataSet:if featVec[axis] == value:                        #判断axis列的值是否为valuereducedFeatVec = featVec[:axis]               #[:axis]表示前axis行,即若axis为2,就是取featVec的前axis行reducedFeatVec.extend(featVec[axis+1:])       #[axis+1:]表示从跳过axis+1行,取接下来的数据retDataSet.append(reducedFeatVec)return retDataSet#遍历整个数据集,找到最好的特征划分方式
def chooseBestFeatureToSplitForC45(dataSet):numFeatures = len(dataSet[0]) - 1  # 特征个数baseEntropy = calcShannonEnt(dataSet)  # 数据集dataSet的熵bestInfoGainRatio = 0.0# 最优信息增益bestFeature = -1  #最优特征for i in range(numFeatures):  # 对于每一个特征列featList = [example[i] for example in dataSet]  # 获取该特征列的值uniqueVals = set(featList)  # 获得该特征的所有唯一特征值newEntroy = 0.0 # 给定特征i的数据集dataSet的条件熵ibaseEntroy=0.0#数据集dataSet关于特征i的值的熵(数据集dataSet按照特征i的值划分的各子集的熵*子集占dataSet的比例之和)for value in uniqueVals:subDataSet = splitDataSet(dataSet, i, value)  # 按照i特征的value唯一特征值--拆分数据集prob = len(subDataSet) / float(len(dataSet))  # 新数据集占总数据的比例newEntroy += prob * calcShannonEnt(subDataSet)ibaseEntroy-=prob*log(prob,2)infoGainRatio = (baseEntropy - newEntroy)/ibaseEntroy  # 按照i特征划分的信息增益比if (infoGainRatio > bestInfoGainRatio):bestInfoGainRatio = infoGainRatiobestFeature = ireturn bestFeature#频率最高的类别函数 判断递归何时结束
def majorityCnt(classList):                 #参数classList在下面创建树的代码里,是每一行的最后一个特征classCount = {}for vote in classList:                   #将特征里的元素添加到新建的字典里作为键值,并统计该键值出现次数if vote not in classCount.keys(): classCount[vote] = 0classCount[vote] += 1sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)return sortedClassCount[0][0]           #返回出现次数最多的键值#创建决策树
def createTree(dataSet, labels):classList = [example[-1] for example in dataSet]if len(set(classList)) == 1:#if 数据集中的每个子项的类别完全相同:return 该类别return classList[0]if len(dataSet[0]) == 0: #if 遍历完所有的特征:return 频率最高的类别return majorityCnt(classList)# 寻找划分数据集的最好特征 #获取当前数据集合和标签列表的最优特征维度bestFeat = chooseBestFeatureToSplitForC45(dataSet)# 最优特征维度对应的标签值bestFeatLabel = labels[bestFeat]# 创建分支节点myTree = {bestFeatLabel: {}}del (labels[bestFeat])# 划分数据集featValues = [example[bestFeat] for example in dataSet]# print(set(featValues))# for 每个划分的子集for value in set(featValues):# 调用createTree()并且增加返回结果到分支节点中subLabels = labels[:]subDataSet = splitDataSet(dataSet, bestFeat, value)myTree[bestFeatLabel][value] = createTree(subDataSet, subLabels)# return 分支节点return myTreedataSet, label = loadDataSet()
print(createTree(dataSet, label))

运行结果: ​
在这里插入图片描述

3.决策树的剪枝

    决策树生成算法递归地产生决策树,直到不能继续下去为止。这样产生的树往往对训练数据的分类很准确,但对未知的测试数据的分类却没有那么准确,即出现过拟合现象。过拟合的原因在于学习时过多地考虑如何提高对训练数据的正确分类,从而构建出过于复杂的决策树。解决这个问题的办法是考虑决策树的复杂度,对已生成的决策树进行简化。

    在决策树学习中将已生成的树进行简化的过程称为剪枝(pruning)。具体地,剪枝从已生成的树上裁掉一些子树或叶结点,并将其根结点或父结点作为新的叶结点,从而简化分类树模型。

     决策树的剪枝往往通过极小化决策树整体的损失函数(loss function)或代价函数(cost function)来实现。设树T的叶结点个数为T,t是树T的叶结点,该叶结点有 N t N_t Nt个样本点,其中k类的样本点有 N t k N_{tk} Ntk个,k=1,2,…,K。

     叶结点t上的经验熵 H t ( T ) H_t(T) Ht(T)

H t ( T ) = − ∑ k = 1 K N t k N t l o g N t k N t H_t(T) = -\displaystyle\sum_{k=1}^{K} \frac{N_{tk}}{N_t}log\frac{N_{tk}}{N_t} Ht(T)=k=1KNtNtklogNtNtk

     损失函数计算的是每个叶节点的样本数和每个叶节点的经验熵的乘积的累加和,再加上以叶节点个数为基础的惩罚项,α⩾0 为正则化系数。则决策树的损失函数可以定义为:
C α ( T ) = ∑ t = 1 ∣ T ∣ N t H t ( T ) + α ∣ T ∣ C_α(T)=\displaystyle\sum_{t=1}^{|T|} N_tH_t(T)+α|T| Cα(T)=t=1TNtHt(T)+αT

     将损失函数右端的第1项记作:
C ( T ) = ∑ t = 1 ∣ T ∣ N t H t ( T ) = − ∑ t = 1 ∣ T ∣ ∑ k = 1 K N t k l o g N t k N t C(T)=\displaystyle\sum_{t=1}^{|T|} N_tH_t(T)=-\displaystyle\sum_{t=1}^{|T|}\displaystyle\sum_{k=1}^{K} N_{tk}log\frac{N_{tk}}{N_t} C(T)=t=1TNtHt(T)=t=1Tk=1KNtklogNtNtk
     ​则:
C α ( T ) = C ( T ) + α ∣ T ∣ C_α(T)=C(T)+α|T| Cα(T)=C(T)+αT

    C(T)表示模型对训练数据的预测误差,即模型与训练数据的拟合程度,|T|表示模型复杂度,参数α≥0控制两者之间的影响。较大的α促使选择较简单的模型(树),较小 的a促使选择较复杂的模型(树)。α=0意味着只考虑模型与训练数据的拟合程度,不考虑模型的复杂度。

    剪枝就是当α确定时,选择损失函数最小的模型,即损失函数最小的子树。当α值确定时,子树越大,往往与训练数据的拟合越好,但是模型的复杂度就越高;相反,子树越小, 模型的复杂度就越低,但是往往与训练数据的拟合不好。损失函数正好表示了对两者的平衡。

    可以看出,决策树生成只考虑了通过提高信息增益(或信息增益比)对训练数据进行更好的拟合。而决策树剪枝通过优化损失函数还考虑了减小模型复杂度。决策树生成学习局部的模型,而决策树剪枝学习整体的模型。

    定义的损失函数的极小化等价于正则化的极大似然估计。所以,利用损失函数最小原则进行剪枝就是用正则化的极大似然估计进行模型选择。

决策树的剪枝算法:

输入:生成算法产生的整个树T,参数α;
输出:修剪后的子树Ta。

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

(2)递归地从树的叶结点向上回缩。 设一组叶结点回缩到其父结点之前与之后的整体树分别为 T B T_B TB T A T_A TA,其对应的损失函数值分别是 C α ( T B ) C_α(T_B) Cα(TB) C α ( T A ) C_α(T_A) Cα(TA),如果

C α ( T A ) ≤ C α ( T B ) C_α(T_A)≤C_α(T_B) Cα(TA)Cα(TB)

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

(3)返回(2),直至不能继续为止,得到损失函数最小的子树 T a T_a Ta。 注意,上式只需考虑两个树的损失函数的差,其计算可以在局部进行。所以,决策树的剪枝算法可以由一种动态规划的算法实现。

决策树剪枝方法:

    首先剪枝(pruning)的目的是为了避免决策树模型的过拟合。因为决策树算法在学习的过程中为了尽可能的正确的分类训练样本,不停地对结点进行划分,因此这会导致整棵树的分支过多,也就导致了过拟合。决策树的剪枝策略最基本的有两种:预剪枝(pre-pruning)和后剪枝(post-pruning):

    预剪枝(pre-pruning):预剪枝就是在构造决策树的过程中,先对每个结点在划分前进行估计,若果当前结点的划分不能带来决策树模型泛华性能的提升,则不对当前结点进行划分并且将当前结点标记为叶结点。

    对比未剪枝的决策树和经过预剪枝的决策树可以看出:预剪枝使得决策树的很多分支都没有“展开”,这不仅降低了过拟合的风险,还显著减少了决策树的训练时间开销和测试时间开销。但是,另一方面,因为预剪枝是基于“贪心”的,所以,虽然当前划分不能提升泛华性能,但是基于该划分的后续划分却有可能导致性能提升,因此预剪枝决策树有可能带来欠拟合的风险。

    后剪枝(post-pruning):后剪枝就是先把整颗决策树构造完毕,然后自底向上的对非叶结点进行考察,若将该结点对应的子树换为叶结点能够带来泛华性能的提升,则把该子树替换为叶结点。

    对比预剪枝和后剪枝,能够发现,后剪枝决策树通常比预剪枝决策树保留了更多的分支,一般情形下,后剪枝决策树的欠拟合风险小,泛华性能往往也要优于预剪枝决策树。但后剪枝过程是在构建完全决策树之后进行的,并且要自底向上的对树中的所有非叶结点进行逐一考察,因此其训练时间开销要比未剪枝决策树和预剪枝决策树都大得多。


http://chatgpt.dhexx.cn/article/fPuncnU6.shtml

相关文章

python实现三种经典决策树算法

决策树实现ID3、C4.5、CART算法 Author: 浅若清风cyfDate: 2020/12/15 一、创建数据集 手动 def createDataSet():"""创建测试的数据集:return:"""dataSet [# 1[青绿, 蜷缩, 浊响, 清晰, 凹陷, 硬滑, 好瓜],# 2[乌黑, 蜷缩, 沉闷, 清晰, 凹…

数据挖掘--决策树C4.5算法(例题)

C4.5算法与ID3算法的不同点: (1)分支指标采用增益比例 (2)数值属性的处理 (3)处理缺少属性值的训练样本 (4)使用K次迭代交叉验证,评估模型的优劣程度&#xf…

决策树算法总结(上:ID3,C4.5决策树)

文章目录 一、决策树原理1.1 决策树简介1.2 基本概念 二、数学知识2.1 信息熵2.2 条件熵:2.3 信息增益 三、ID3决策树3.1 特征选择3.2 算法思路3.3 算法不足 四、C4.5决策树算法4.1 处理连续特征4.2 C4.5决策树特征选取4.3 处理缺失值4.4 过拟合问题 五、决策树C4.5算法的不足 …

决策树分类算法的案例(代码实现及运行测试)

1 案例需求 我们的任务就是训练一个决策树分类器,输入身高和体重,分类器能给出这个人是胖子还是瘦子。 所用的训练数据如下,这个数据一共有10个样本,每个样本有2个属性,分别为身高和体重,第三列为类别标签…

决策树cart算法实战

1、使用决策树预测隐形眼镜类型,隐形眼镜数据集(lenses.csv)是非常著名的数据集,它包含很多患者眼部状况的观察 条件以及医生推荐的隐形眼镜类型。隐形眼镜类型包括硬材质、软材质以及不适合佩戴隐形眼镜。 要求:读取lenses.csv中的隐形眼镜数…

人工智能决策树大作业

人工智能技术: 机器学习之决策树大作业 以西瓜集 2.0 为建模数据,采用交叉验证方法进行数据训练集和验证集的划分,实现决策树 “预剪枝”算法,要求:尽可能充分利用有限的西瓜集 2.0 数据所提供信息,建立泛化能力强的 决策树模型。…

决策树算法:原理与python实现案例

文章目录 决策树算法浅析决策树的介绍决策树最佳划分的度量问题决策树python案例 决策树算法浅析 决策树的介绍 决策树的定义: 决策树是一种逼近离散值目标函数的方法,学习到的函数使用树结构进行表示,完成决策任务。这里决策树可以是分类树…

决策树实例-ID3

决策树-ID3实例 参考书籍: 《机器学习》周志华,第1版 《统计学习方法》李航,第2版 用来记录自己对书中知识的理解,加强自己的理解和记忆,同时提出自己迷惑不解的地方,提高自己编辑的表达能力。 代码参考博…

决策树算法及Python 代码示例

决策树是一种基于树形结构的算法,用于在一系列决策和结果之间建立模型。它通过对特征和目标变量之间的关系进行划分,来预测目标变量的值。 决策树算法示例: 假设我们有一组数据,其中包含天气,温度,湿度和是否出门的特…

决策树一CART算法(第四部分)

决策树一CART算法(第四部分) CART树的剪枝:算法步骤 输入:CART算法生成的决策树。 输出:最优决策树T 设 K 0 , T T 0 K0,TT_0 K0,TT0​ ,从完整的决策树出发 ​ k代表迭代次数,先…

决策树算法

决策树 决策树(Decision Tree)首先对数据进行处理,利用归纳算法生成可读的规则和决策树,然后使用决策对新数据进行分析,本质上是通过一系列规则对数据进行分类的过程 决策树是一种典型的分类方法。其中: 每个内部结点表示一个属性上的判断每个分支代表一个判断结果的输出每…

决策树ID3、C4.5和CART算法例子详解

决策树 决策树是附加概率结果的一个树状的决策图,是直观的运用统计概率分析的图法。机器学习中决策树是一个预测模型,它表示对象属性和对象值之间的一种映射,树中的每一个节点表示对象属性的判断条件,其分支表示符合节点条件的对…

决策树算法原理及案例

机器学习在各个领域都有广泛的应用,特别在数据分析领域有着深远的影响。决策树是机器学习中最基础且应用最广泛的算法模型。本文介绍了机器学习的相关概念、常见的算法分类和决策树模型及应用。通过一个决策树案例,着重从特征选择、剪枝等方面描述决策树…

通过实例理解决策树算法(ID3,C4.5,Cart算法)

(一)实例:使用ID3算法给出“好苹果”的决策树 (二)决策树的工作原理 我们在做决策树的时候,会经历两个阶段:构造和剪枝。 构造原理——构造的过程就是选择什么属性作为节点的过程,…

数据挖掘之C4.5决策树算法

1.决策树算法实现的三个过程: 特征选择:选择哪些特征作为分类的标准是决策树算法的关键,因此需要一种衡量标准来进行特征的确定,不同的决策树衡量标准不同。例如C4.5决策树就是以信息增益率来作为衡量标准。决策树的生成&#xf…

决策树ID3例题

表格里统计了14天的气象数据,特征属性包括outlook,temperature,humidity,windy,类别属性为是否打球(play),用ID3算法生成决策树。 解答过程:

决策树算法与案例

决策树算法介绍 树模型 决策树:从根节点开始一步步走到叶子节点(决策)。所有的数据最终都会落到叶子节点,既可以做分类也可以做回归 树的组成 根节点:第一个选择点;非叶子节点与分支:中间过程…

数据挖掘--决策树ID3算法(例题)

决策树分类算法 决策树分类算法通常分为两个步骤:决策树生成和决策树修剪。 决策树生成算法的输入参数是一组带有类别标记的样本,输出是构造一颗决策树,该树可以是一棵二叉树或多叉树。二叉树的内部结点(非叶子结点)…

决策树算法原理+例题练习

一、决策树的优缺点 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失值不敏感,可以处理不相关特征数据。缺点:可能会产生过度匹配的问题。使用数据类型:数值型和标称型。 二、一个实例 一天&#…

高级管理学:计算题

题1:决策树和期望值 某企业拟开发新产品,现在有两个可行性方案需要决策。 方案一:开发新产品 A,需要追加投资 180 万元,经营期限为 5 年。此间,产品销路好每年可获利 170 万元;销路一般每年可获…