决策树(Decision tree)算法详解(ID3、C4.5、CART)

XGBoosting参数简介 一、GBDT(Gradient Boosting Decision Tree 梯度增强决策树) 1、BDT:Boosting Decision Tree 提升决策树 1)Boosting:提升,涉及到机器学习中的集成学习,原理就是通过多个特征生成多个树,来决策一件事 2)BDT的核心在于,每一颗树学的是前面所有树结论和的残差 2、GB(Gradient Boosting 梯度提升) 二、CART(ClassificationAnd Regression Tree) 1、ID3-信息增益 2、. 阅读详情

一、决策树介绍

决策树是一种树形结构的监督学习算法,其核心思想是通过一系列条件判断对数据进行分类,就像人类在做决策时的逻辑判断过程。

1.1 决策树的结构特征

  • 内部节点:表示一个特征上的判断(如"年龄是否大于30")
  • 分支:表示判断结果的输出(如"是"或"否")
  • 叶子节点:表示最终的分类结果(如"同意贷款"或"拒绝贷款")

1.2 决策树的构建三步骤

  1. 特征选择:从众多特征中挑选分类能力最强的特征
  2. 树的生成:基于选择的特征递归构建决策树
  3. 剪枝优化:防止过拟合,提升模型泛化能力

1.3 决策树构建例子

你有一个朋友正在考虑是否要去参加一个社交活动,他/她/他们可能会这样思考:
朋友问你:这个活动值得去吗?
于是你开始了解情况:
问:这个活动是线上还是线下?
答:线下,在市中心的一个咖啡馆。
问:天气怎么样?
答:那天天气不错。
问:有没有感兴趣的人会去?
答:有,你喜欢的那位也会去。
问:交通方便吗?
答:地铁直达,很方便。
……
于是你的大脑里就构建了这样一棵“决策树”:
在这里插入图片描述
绘图代码:

import graphviz

# 创建有向图,并设置中文字体
# 1. 导入Graphviz库:
#    graphviz是Python与Graphviz软件交互的接口,负责生成可视化图形(需提前安装Graphviz软件)
import graphviz  

# 2. 创建有向图对象,并配置中文显示:
#    - comment:给图加注释(仅文档用途,不影响渲染)
#    - format:指定输出文件格式(如png、pdf等)
#    - node_attr/edge_attr/graph_attr:设置节点、边、全局的字体为"SimHei"(微软雅黑),解决中文乱码问题
dot = graphviz.Digraph(
    comment='社交活动决策树',       # 图的描述信息(可选)
    format='png',                  # 输出文件格式
    node_attr={'fontname': 'SimHei'},  # 节点文字用微软雅黑(支持中文)
    edge_attr={'fontname': 'SimHei'},  # 边的标签文字用微软雅黑
    graph_attr={'fontname': 'SimHei'}  # 全局文字(如标题)用微软雅黑
)

# 3. 添加节点(node):
#    格式:dot.node(节点唯一标识, 显示的文字)
#    节点ID(如'A')是内部标记,显示文字是图形中实际展示的内容
dot.node('A', '活动类型')         # 根节点:决策起点(活动类型)
dot.node('B', '线上')             # 分支1:活动类型为线上
dot.node('C', '线下')             # 分支2:活动类型为线下
dot.node('D', '天气是否好?')     # 线下活动的子判断:天气条件
dot.node('E', '否')               # 天气分支:不好
dot.node('F', '是')               # 天气分支:好
dot.node('G', '有没有感兴趣的人?') # 天气好时的子判断:兴趣条件
dot.node('H', '否')               # 兴趣分支:没有
dot.node('I', '有')               # 兴趣分支:有
dot.node('J', '去参加')           # 最终决策:参加
dot.node('K', '考虑其他安排')     # 最终决策:不参加

# 4. 添加边(edge):
#    格式:dot.edge(起点ID, 终点ID, label=边的说明文字)
#    label可选,用于解释分支条件
dot.edge('A', 'B')                # 活动类型 → 线上(无额外条件,直接分支)
dot.edge('A', 'C')                # 活动类型 → 线下(无额外条件,直接分支)
dot.edge('C', 'D')                # 线下活动 → 判断天气
dot.edge('D', 'E', label='否')    # 天气判断 → 否(边标注“否”)
dot.edge('D', 'F', label='是')    # 天气判断 → 是(边标注“是”)
dot.edge('F', 'G')                # 天气好 → 判断是否有感兴趣的人
dot.edge('G', 'H', label='否')    # 兴趣判断 → 否(边标注“否”)
dot.edge('G', 'I', label='是')    # 兴趣判断 → 是(边标注“是”)
dot.edge('I', 'J')                # 有感兴趣的人 → 去参加(最终决策)
dot.edge('H', 'K')                # 没有感兴趣的人 → 考虑其他安排(最终决策)

# 5. 渲染并查看图形:
#    - 第一个参数:输出文件名(生成的文件会是 decision_tree_social_event.png)
#    - view=True:生成后自动用系统默认程序打开图片
#    注意:运行前需确保:
#      ① 系统安装了Graphviz软件(https://graphviz.org/download/)
#      ② Graphviz的bin目录已加入系统环境变量(如 C:\Program Files\Graphviz\bin)
dot.render('decision_tree_social_event', view=True)

二、ID3决策树:基于信息增益的决策模型

2.1 信息增益的公式与符号解析

信息增益公式:
g ( D , A ) = H ( D ) − H ( D ∣ A ) g(D, A) = H(D) - H(D|A) g(D,A)=H(D)−H(D∣A)

  • g ( D , A ) g(D, A) g(D,A):特征 A A A对数据集 D D D的信息增益
  • H ( D ) H(D) H(D):数据集 D D D的经验熵,衡量数据的不确定性
    H ( D ) = − ∑ k = 1 K ∣ C k ∣ ∣ D ∣ log ⁡ 2 ∣ C k ∣ ∣ D ∣ H(D) = -\sum_{k=1}^{K}\frac{|C_k|}{|D|}\log_2\frac{|C_k|}{|D|} H(D)=−k=1∑K​∣D∣∣Ck​∣​log2​∣D∣∣Ck​∣​
    其中, K K K为类别数, ∣ C k ∣ |C_k| ∣Ck​∣为第 k k k类的样本数, ∣ D ∣ |D| ∣D∣为总样本数。
  • H ( D ∣ A ) H(D|A) H(D∣A):特征 A A A给定条件下 D D D的经验条件熵
    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 ∣ log ⁡ 2 ∣ D i k ∣ ∣ D i ∣ H(D|A) = \sum_{i=1}^{n}\frac{|D_i|}{|D|}H(D_i) = -\sum_{i=1}^{n}\frac{|D_i|}{|D|}\sum_{k=1}^{K}\frac{|D_{ik}|}{|D_i|}\log_2\frac{|D_{ik}|}{|D_i|} H(D∣A)=i=1∑n​∣D∣∣Di​∣​H(Di​)=−i=1∑n​∣D∣∣Di​∣​k=1∑K​∣Di​∣∣Dik​∣​log2​∣Di​∣∣Dik​∣​
    其中, n n n为特征 A A A的取值个数, ∣ D i ∣ |D_i| ∣Di​∣为特征 A A A取第 i i i个值的样本数, ∣ D i k ∣ |D_{ik}| ∣Dik​∣为 D i D_i Di​中属于第 k k k类的样本数。

2.2 信息增益的意义

信息增益衡量的是某个特征对数据分类不确定性的减少程度。直观来说,它反映了在已知某个特征的取值后,我们对样本分类结果的不确定性降低了多少。
例如,在判断一个人是否适合贷款时,如果“是否有房”这一特征能显著帮助我们确定贷款审批结果,那么这个特征的信息增益就较大。换句话说,信息增益越大,该特征在分类任务中的判别能力越强。

2.3 ID3决策树案例演示:贷款申请分类

以贷款申请数据为例,计算各特征的信息增益并构建ID3决策树。

数据集:

年龄有工作有房子信贷情况类别
青年否否一般拒绝
青年否否好拒绝
青年是否好同意
青年是是一般同意
青年否否一般拒绝
中年否否一般拒绝
中年否否好拒绝
中年是是好同意
中年否是非常好同意
中年否是非常好同意
老年否是非常好同意
老年否是好同意
老年是否好同意
老年是否非常好同意
老年否否一般拒绝

步骤1:计算数据集D的经验熵H(D)
数据集中共有15条样本,其中"同意"类5条,"拒绝"类10条:
H ( D ) = − 5 15 log ⁡ 2 5 15 − 10 15 log ⁡ 2 10 15 = 0.9183 H(D) = -\frac{5}{15}\log_2\frac{5}{15} - \frac{10}{15}\log_2\frac{10}{15} = 0.9183 H(D)=−155​log2​155​−1510​log2​1510​=0.9183

步骤2:计算各特征的条件熵和信息增益
以"年龄"特征为例,其取值为{青年, 中年, 老年}:

  • 青年样本:5条(ID1-5),其中拒绝4条,同意1条
    H ( 青年 ) = − 4 5 log ⁡ 2 4 5 − 1 5 log ⁡ 2 1 5 = 0.7219 H(青年) = -\frac{4}{5}\log_2\frac{4}{5} - \frac{1}{5}\log_2\frac{1}{5} = 0.7219 H(青年)=−54​log2​54​−51​log2​51​=0.7219
  • 中年样本:5条(ID6-10),其中拒绝2条,同意3条
    H ( 中年 ) = − 2 5 log ⁡ 2 2 5 − 3 5 log ⁡ 2 3 5 = 0.9709 H(中年) = -\frac{2}{5}\log_2\frac{2}{5} - \frac{3}{5}\log_2\frac{3}{5} = 0.9709 H(中年)=−52​log2​52​−53​log2​53​=0.9709
  • 老年样本:5条(ID11-15),其中拒绝1条,同意4条
    H ( 老年 ) = − 1 5 log ⁡ 2 1 5 − 4 5 log ⁡ 2 4 5 = 0.7219 H(老年) = -\frac{1}{5}\log_2\frac{1}{5} - \frac{4}{5}\log_2\frac{4}{5} = 0.7219 H(老年)=−51​log2​51​−54​log2​54​=0.7219
  • 条件熵:
    H ( D ∣ 年龄 ) = 5 15 × 0.7219 + 5 15 × 0.9709 + 5 15 × 0.7219 = 0.8049 H(D|年龄) = \frac{5}{15} \times 0.7219 + \frac{5}{15} \times 0.9709 + \frac{5}{15} \times 0.7219 = 0.8049 H(D∣年龄)=155​×0.7219+155​×0.9709+155​×0.7219=0.8049
  • 信息增益:
    g ( D , 年龄 ) = 0.9183 − 0.8049 = 0.1134 g(D, 年龄) = 0.9183 - 0.8049 = 0.1134 g(D,年龄)=0.9183−0.8049=0.1134

同理计算其他特征的信息增益:

  • g ( D , 有工作 ) = 0.3236 g(D, 有工作) = 0.3236 g(D,有工作)=0.3236
  • g ( D , 有房子 ) = 0.4208 g(D, 有房子) = 0.4208 g(D,有房子)=0.4208
  • g ( D , 信贷情况 ) = 0.3623 g(D, 信贷情况) = 0.3623 g(D,信贷情况)=0.3623

步骤3:选择信息增益最大的特征分裂
"有房子"的信息增益最大(0.4208),作为根节点分裂,得到左右子树:

  • 有房子:7条样本(ID4,8,9,10,11,12,14),其中6条同意,1条拒绝
  • 无房子:8条样本(ID1,2,3,5,6,7,13,15),其中2条同意,6条拒绝

步骤4:递归构建子树
对每个子树重复上述过程,最终生成完整的ID3决策树。

在这里插入图片描述

这是一棵用于 贷款申请分类 的决策树(基于ID3算法,通过信息熵选择分裂特征),核心判断逻辑如下:

根节点:判断“是否有房子”

  • 条件:按特征取值分裂(右分支为 有房子 > 0.5,左分支为 有房子 ≤ 0.5)。
  • 信息增益:0.42(衡量该特征对分类的贡献度)。
  • 样本数:15(全量样本)。
  • 类别分布:拒绝6人,同意9人(分布:拒绝=6,同意=9)。

分支逻辑

  • 右分支(有房子 > 0.5)

    • 样本:6人(所有“有房”申请人)。
    • 类别分布:同意6人,拒绝0人。
    • 决策:直接判定为 同意(叶子节点)。
  • 左分支(有房子 ≤ 0.5)

    • 进入下一层判断 “是否有工作”:

第二层节点:判断“是否有工作”

  • 条件:按特征取值分裂(右分支为 有工作 > 0.5,左分支为 有工作 ≤ 0.5)。
  • 信息增益:0.918(该特征对剩余样本的分类贡献度)。
  • 样本数:9人(所有“无房”申请人)。
  • 类别分布:拒绝6人,同意3人(分布:拒绝=6,同意=3)。

最终叶子节点

  • 左子节点(有工作 ≤ 0.5)

    • 样本:6人(无房且无工作的申请人)。
    • 类别分布:同意0人,拒绝6人。
    • 决策:拒绝(叶子节点)。
  • 右子节点(有工作 > 0.5)

    • 样本:3人(无房但有工作的申请人)。
    • 类别分布:同意3人,拒绝0人。
    • 决策:同意(叶子节点)。

决策树通过 “有房→有工作” 的两步判断,输出贷款决策:

  • 有房 → 直接同意;
  • 无房但有工作 → 同意;
  • 无房且无工作 → 拒绝。

(注:LabelEncoder 按字母序编码类别,此处“同意”为0,“拒绝”为1,节点分布以 拒绝=X,同意=Y 格式展示。)

绘图代码:

# 导入必要的库
import pandas as pd  # 用于数据处理和构建 DataFrame
from collections import Counter  # 用于统计样本数量
from math import log2  # 用于计算对数
from graphviz import Digraph  # 用于可视化决策树
from sklearn.preprocessing import LabelEncoder  # 用于将字符串特征编码为数字


# =============================================
# 1. 数据准备
# =============================================
# 构建训练数据集,包含 5 个特征和 1 个目标变量
data = {
    # 每个样本的唯一编号,容易造成过拟合
    # "ID": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],

    # 年龄:青年、中年、老年
    "年龄": ["青年", "青年", "青年", "青年", "青年", "中年", "中年", "中年", "中年", "中年",
             "老年", "老年", "老年", "老年", "老年"],

    # 是否有工作:是、否
    "有工作": ["否", "否", "是", "是", "否", "否", "否", "是", "否", "否",
               "否", "否", "是", "是", "否"],

    # 是否有房子:是、否
    "有房子": ["否", "否", "否", "是", "否", "否", "否", "是", "是", "是",
               "是", "是", "否", "否", "否"],

    # 信贷情况:一般、好、非常好
    "信贷情况": ["一般", "好", "好", "一般", "一般", "一般", "好", "好", "非常好", "非常好",
                 "非常好", "好", "好", "非常好", "一般"],

    # 类别:是否贷款成功(同意/拒绝)
    "类别": ["拒绝", "拒绝", "同意", "同意", "拒绝", "拒绝", "拒绝", "同意", "同意", "同意",
             "同意", "同意", "同意", "同意", "拒绝"]
}

# 将数据转换为 pandas 的 DataFrame 格式
df = pd.DataFrame(data)

# 提取特征列名列表(所有列除了最后一列)
features = list(df.columns[:-1])  # 特征:ID、年龄、有工作、有房子、信贷情况

# 目标变量列名(最后一列)
target = df.columns[-1]  # 类别列名


# =============================================
# 2. 信息熵与信息增益计算
# =============================================

def entropy(y):
    """
    计算信息熵 H(Y)
    y: 当前样本的目标变量值(如:['拒绝', '同意', ...])
    返回:当前样本的信息熵
    """
    counts = Counter(y)  # 统计每个类别的数量
    total = len(y)  # 总样本数
    if total == 0:
        return 0  # 防止除以 0
    # 计算 -Σ(p * log2(p))
    return -sum((count / total) * log2(count / total) for count in counts.values())


def conditional_entropy(X_col, y):
    """
    计算条件熵 H(Y|X)
    X_col: 某个特征列的值(如:['青年', '中年', ...])
    y: 对应的目标变量值
    返回:给定该特征下目标变量的条件熵
    """
    values = set(X_col)  # 获取该特征的所有唯一值
    total = len(y)  # 总样本数
    ent = 0
    for v in values:
        mask = (X_col == v)  # 找到该特征值对应的样本
        y_sub = y[mask]  # 取出这些样本的目标变量
        ent += len(y_sub) / total * entropy(y_sub)  # 加权求和
    return ent


def info_gain(dataset, feature):
    """
    计算某个特征的信息增益 IG(Y, X)
    dataset: 整个数据集
    feature: 当前特征名称(如:"年龄")
    返回:该特征的信息增益
    """
    X_col = dataset[feature]  # 取出该特征列
    y = dataset[target]  # 取出目标变量列
    return entropy(y) - conditional_entropy(X_col, y)  # 信息增益 = 总熵 - 条件熵


# =============================================
# 3. 手动实现 ID3 决策树
# =============================================

def id3_tree(dataset, features):
    """
    使用 ID3 算法递归构建决策树
    dataset: 当前数据集
    features: 当前可用特征列表
    返回:当前节点的决策树结构字典
    """
    target_values = dataset[target].unique()  # 获取当前目标变量的唯一值

    # 终止条件1:当前样本全部属于同一类
    if len(target_values) == 1:
        return {'label': target_values[0]}  # 返回叶子节点标签

    # 终止条件2:没有可用特征
    if not features:
        most_common = dataset[target].mode().iloc[0]  # 返回多数类作为预测结果
        return {'label': most_common}

    # 选择信息增益最大的特征
    gains = {f: info_gain(dataset, f) for f in features}  # 计算每个特征的信息增益
    best_feature = max(gains, key=gains.get)  # 选出最大增益的特征

    # 构建当前节点信息
    class_counts = dict(Counter(dataset[target]))  # 统计目标变量分布
    node_info = {
        'feature': best_feature,
        'gain': gains[best_feature],  # 信息增益
        'class_dist': class_counts,  # 类别分布
        'n_samples': len(dataset),  # 样本数量
        'children': {}  # 子节点
    }

    # 递归划分每个特征值
    remaining_features = [f for f in features if f != best_feature]  # 剩余可用特征
    for raw_value in dataset[best_feature].unique():  # 遍历当前特征的每个唯一值
        sub_data = dataset[dataset[best_feature] == raw_value]  # 划分子数据集
        node_info['children'][raw_value] = id3_tree(sub_data, remaining_features)  # 递归生成子树

    return node_info


# =============================================
# 4. 构建特征编码器(用于生成 CART 风格的分割条件)
# =============================================
# 保存每个特征的编码器,便于后续可视化时使用
feature_encoders = {}

for feat in features:
    le = LabelEncoder()  # 创建编码器
    le.fit(df[feat])  # 拟合该特征的编码规则
    feature_encoders[feat] = le  # 保存编码器


# =============================================
# 5. 决策树可视化(CART 风格,支持中文)
# =============================================
def visualize_tree_cart_style(tree, feature_encoders, graph=None, parent_id=None, edge_label=""):
    """
    使用 Graphviz 可视化决策树(CART 风格)
    tree: 当前树节点结构
    feature_encoders: 编码器字典
    graph: 当前图对象
    parent_id: 父节点 ID
    edge_label: 边上的标签
    返回:Graphviz 图对象
    """
    from uuid import uuid4  # 用于生成唯一节点 ID

    if graph is None:
        # 初始化一个空图,设置字体支持中文
        graph = Digraph(
            'DecisionTree',
            format='png',
            node_attr={'fontname': 'SimHei'},  # 支持中文节点
            edge_attr={'fontname': 'SimHei'},  # 支持中文边标签
            graph_attr={'fontname': 'SimHei', 'rankdir': 'TB'}  # 树方向从上往下
        )

    node_id = str(uuid4())  # 生成当前节点的唯一标识符

    if 'label' in tree:
        # 如果是叶子节点,显示类别标签
        label = f"类别: {tree['label']}"
        shape = "box"  # 叶子节点用矩形
    else:
        # 如果是内部节点,显示特征、增益等信息
        feat_name = tree['feature']
        metric = round(tree.get('gain', 0), 3)  # 获取信息增益
        n = tree['n_samples']  # 样本数
        dist = ", ".join([f"{k}={v}" for k, v in tree['class_dist'].items()])  # 分布

        # 构造节点标签
        label = (
            f"{feat_name}\\n"
            f"信息增益={metric}\\n"
            f"样本数={n}\\n"
            f"分布:{dist}"
        )
        shape = "ellipse"  # 内部节点用椭圆

    graph.node(node_id, label=label, shape=shape)  # 添加当前节点到图中

    if parent_id:
        # 如果有父节点,则画边
        graph.edge(parent_id, node_id, label=edge_label)

    if 'children' in tree:
        # 如果有子节点,递归绘制
        feat_name = tree['feature']
        encoder = feature_encoders[feat_name]  # 获取该特征的编码器
        unique_values = df[feat_name].unique()  # 获取原始特征值
        sorted_values = sorted(encoder.transform(unique_values))  # 编码后的排序值

        for raw_value, child in tree['children'].items():
            encoded_value = encoder.transform([raw_value])[0]  # 把原始值转为编码值
            display_label = get_edge_label(feat_name, encoded_value, sorted_values)  # 生成边标签
            # 递归绘制子树
            visualize_tree_cart_style(child, feature_encoders, graph, node_id, display_label)

    return graph


def get_edge_label(feat_name, encoded_value, sorted_values):
    """
    生成边标签,例如:年龄 <= 0.5、年龄 > 0.5
    feat_name: 特征名
    encoded_value: 编码后的特征值
    sorted_values: 排序后的编码值列表
    返回:边标签字符串
    """
    index = sorted_values.index(encoded_value)
    if index == 0:
        threshold = (sorted_values[index] + sorted_values[index + 1]) / 2
        return f"{feat_name} <= {threshold:.1f}"
    elif index == len(sorted_values) - 1:
        threshold = (sorted_values[index - 1] + sorted_values[index]) / 2
        return f"{feat_name} > {threshold:.1f}"
    else:
        low = (sorted_values[index - 1] + sorted_values[index]) / 2
        high = (sorted_values[index] + sorted_values[index + 1]) / 2
        return f"{low:.1f} < {feat_name} <= {high:.1f}"


# =============================================
# 6. 主程序:构建并可视化 ID3 决策树
# =============================================

# 构建模型
tree_id3 = id3_tree(df, features)  # 构建 ID3 决策树

# 设置可视化图例格式
dot_id3 = visualize_tree_cart_style(tree_id3, feature_encoders)  # 可视化 ID3 树

# 保存为 PNG 文件,并自动打开查看
dot_id3.render("id3_decision_tree_with_id", view=True)

2.4 ID3决策树缺陷

ID3决策树的核心优势是计算简单、可解释性强,但存在明显缺陷:倾向于选择取值较多的特征(如"ID"特征可能有最大信息增益),导致过拟合风险。

ID3决策树的缺陷演示:被“ID”特征误导的过拟合

  1. 构造含干扰特征的数据集
    在原有贷款数据中加入 “ID” 特征(唯一标识,与贷款结果无实际关联),数据如下:
ID年龄有工作有房子信贷情况类别
1青年否否一般拒绝
2青年否否好拒绝
3青年是否好同意
………………

(共15条,ID=1~15,类别不变)

  1. 信息增益计算(核心对比)

    ① 总熵 ( H(D) )
    总样本15条,同意=9,拒绝=6:
    H ( D ) = − 9 15 log ⁡ 2 9 15 − 6 15 log ⁡ 2 6 15 ≈ 0.918 H(D) = -\frac{9}{15}\log_2\frac{9}{15} - \frac{6}{15}\log_2\frac{6}{15} \approx 0.918 H(D)=−159​log2​159​−156​log2​156​≈0.918

    ② “ID”特征的信息增益
    “ID”有15个唯一值(每个ID对应1条样本),每个子集 D i D_i Di​ 只有1条样本(纯类别,熵为0):
    H ( D ∣ ID ) = ∑ i = 1 15 1 15 × 0 = 0 ⇒ g ( D , ID ) = 0.918 − 0 = 0.918 H(D|\text{ID}) = \sum_{i=1}^{15} \frac{1}{15} \times 0 = 0 \quad \Rightarrow \quad g(D, \text{ID}) = 0.918 - 0 = 0.918 H(D∣ID)=i=1∑15​151​×0=0⇒g(D,ID)=0.918−0=0.918

    ③ 有效特征“有房子”的信息增益
    “有房子”分两类(无房=8条,有房=7条),条件熵计算得 H ( D ∣ 有房子 ) ≈ 0.497 H(D|\text{有房子}) \approx 0.497 H(D∣有房子)≈0.497,故:
    g ( D , 有房子 ) ≈ 0.918 − 0.497 = 0.421 g(D, \text{有房子}) \approx 0.918 - 0.497 = 0.421 g(D,有房子)≈0.918−0.497=0.421

  2. 缺陷暴露:被“ID”误导的过拟合

    • 增益排序:g(D, ID) > g(D, 有房子),ID3会优先选 “ID” 作为根节点。
    • 逻辑荒谬:“ID”是纯标识(与贷款结果无关),但因取值唯一,决策树会分裂出15个叶子节点(每个ID对应一个结果),导致 模型仅记忆样本,无法泛化新数据(如ID=16的新样本,树无法判断)。

这就是ID3的核心缺陷:盲目追求“信息增益最大”,倾向选择取值多的特征(如ID),最终导致过拟合。

三、C4.5决策树:信息增益率的优化

3.1 信息增益率的公式与符号解析

信息增益率公式:
Gain_Ratio ( D , A ) = g ( D , A ) IV ( A ) \text{Gain\_Ratio}(D, A) = \frac{g(D, A)}{\text{IV}(A)} Gain_Ratio(D,A)=IV(A)g(D,A)​

  • Gain_Ratio ( D , A ) \text{Gain\_Ratio}(D, A) Gain_Ratio(D,A):特征 A A A的信息增益率
  • g ( D , A ) g(D, A) g(D,A):特征 A A A的信息增益
  • IV ( A ) \text{IV}(A) IV(A):特征 A A A的内在信息(分裂信息)
    IV ( A ) = − ∑ i = 1 n ∣ D i ∣ ∣ D ∣ log ⁡ 2 ∣ D i ∣ ∣ D ∣ \text{IV}(A) = -\sum_{i=1}^{n}\frac{|D_i|}{|D|}\log_2\frac{|D_i|}{|D|} IV(A)=−i=1∑n​∣D∣∣Di​∣​log2​∣D∣∣Di​∣​
    其中, n n n为特征 A A A的取值个数, ∣ D i ∣ |D_i| ∣Di​∣为特征 A A A取第 i i i个值的样本数。

3.2 信息增益率的意义

信息增益率通过引入一个称为内在信息(Intrinsic Value,IV)的指标对信息增益进行归一化处理。其目的是解决ID3算法中偏向于选择取值较多特征的问题。

内在信息 IV ( A ) \text{IV}(A) IV(A) 反映了特征 A A A 取值分布的均匀程度。分布越均匀, IV ( A ) \text{IV}(A) IV(A) 的值就越大。通过将信息增益除以 IV ( A ) \text{IV}(A) IV(A),信息增益率有效降低了那些取值数量多、但划分意义不大的特征的优先级。

可以将其理解为:信息增益是一个“原始得分”,而信息增益率是根据题目难度调整后的“加权得分”。对于取值较少但具有明显分类效果的特征,它会得到更高的认可,从而避免模型错误地偏好那些取值繁多但实际判别能力一般的特征。

3.3 C4.5决策树:信息增益率修正ID3的过拟合缺陷

含ID特征的数据集构造 :
在原贷款数据中加入ID列(取值1~15,唯一标识,与贷款结果无关),数据集如下:

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

步骤1:计算数据集总熵 H ( D ) H(D) H(D)
总样本15条,同意=9,拒绝=6:
H ( D ) = − 9 15 log ⁡ 2 9 15 − 6 15 log ⁡ 2 6 15 ≈ 0.918 H(D) = -\frac{9}{15}\log_2\frac{9}{15} - \frac{6}{15}\log_2\frac{6}{15} \approx 0.918 H(D)=−159​log2​159​−156​log2​156​≈0.918

步骤2:计算“ID”特征的信息增益率

  • 信息增益 g ( D , ID ) g(D, \text{ID}) g(D,ID):
    ID有15个唯一值,每个子集仅1条样本(纯类别,熵为0):
    H ( D ∣ ID ) = ∑ i = 1 15 1 15 × 0 = 0 ⇒ g ( D , ID ) = 0.918 − 0 = 0.918 H(D|\text{ID}) = \sum_{i=1}^{15}\frac{1}{15} \times 0 = 0 \quad \Rightarrow \quad g(D, \text{ID}) = 0.918 - 0 = 0.918 H(D∣ID)=i=1∑15​151​×0=0⇒g(D,ID)=0.918−0=0.918

  • 内在信息 IV(ID) \text{IV(ID)} IV(ID):
    IV(ID) = − ∑ i = 1 15 1 15 log ⁡ 2 1 15 ≈ 3.907 \text{IV(ID)} = -\sum_{i=1}^{15}\frac{1}{15}\log_2\frac{1}{15} \approx 3.907 IV(ID)=−i=1∑15​151​log2​151​≈3.907

  • 信息增益率:
    Gain_Ratio ( D , ID ) = 0.918 3.907 ≈ 0.235 \text{Gain\_Ratio}(D, \text{ID}) = \frac{0.918}{3.907} \approx 0.235 Gain_Ratio(D,ID)=3.9070.918​≈0.235

步骤3:计算“有房子”特征的信息增益率

  • 信息增益 g ( D , 有房子 ) g(D, \text{有房子}) g(D,有房子):
    有房=7条(同意6,拒绝1),无房=8条(同意2,拒绝6):
    H ( D ∣ 有房子 ) = 7 15 ( − 6 7 log ⁡ 2 6 7 − 1 7 log ⁡ 2 1 7 ) + 8 15 ( − 2 8 log ⁡ 2 2 8 − 6 8 log ⁡ 2 6 8 ) ≈ 0.497 H(D|\text{有房子}) = \frac{7}{15}\left(-\frac{6}{7}\log_2\frac{6}{7}-\frac{1}{7}\log_2\frac{1}{7}\right) + \frac{8}{15}\left(-\frac{2}{8}\log_2\frac{2}{8}-\frac{6}{8}\log_2\frac{6}{8}\right) \approx 0.497 H(D∣有房子)=157​(−76​log2​76​−71​log2​71​)+158​(−82​log2​82​−86​log2​86​)≈0.497

    g ( D , 有房子 ) = 0.918 − 0.497 = 0.421 g(D, \text{有房子}) = 0.918 - 0.497 = 0.421 g(D,有房子)=0.918−0.497=0.421

  • 内在信息 IV(有房子) \text{IV(有房子)} IV(有房子):

    IV(有房子) = − 7 15 log ⁡ 2 7 15 − 8 15 log ⁡ 2 8 15 ≈ 0.998 \text{IV(有房子)} = -\frac{7}{15}\log_2\frac{7}{15} - \frac{8}{15}\log_2\frac{8}{15} \approx 0.998 IV(有房子)=−157​log2​157​−158​log2​158​≈0.998

  • 信息增益率:
    Gain_Ratio ( D , 有房子 ) = 0.421 0.998 ≈ 0.422 \text{Gain\_Ratio}(D, \text{有房子}) = \frac{0.421}{0.998} \approx 0.422 Gain_Ratio(D,有房子)=0.9980.421​≈0.422

特征选择对比

特征信息增益 ( g )内在信息 IV \text{IV} IV信息增益率
ID0.9183.9070.235
有房子0.4210.9980.422

步骤4:递归构建子树

  • 分裂子节点:以信息增益率最高的特征( “有房子” )为根节点分裂后,得到两个子节点:左子节点:无房样本(8 条,同意 2,拒绝 6)右子节点:有房样本(7 条,同意 6,拒绝 1)递归应用
  • C4.5 逻辑:对每个子节点数据集,重复步骤 1-3:计算子节点数据集的总熵 H ( D i ) H(D_i) H(Di​);计算各特征(年龄、有工作、信贷情况、ID)的信息增益率;选择信息增益率最大的特征分裂(若存在)。
  • 终止条件(满足任一条件则停止分裂):子节点所有样本属于同一类别(如右子节点 “有房” 样本中 6 同意 1 拒绝,若继续分裂可能得到纯类别节点);信息增益率小于预设阈值(避免无意义分裂);特征已全部使用或样本数少于最小阈值。
    ID3决策树 I D 3 决策树 ID3决策树 ID3决策树

C4.5决策树
C 4.5 决策树 C4.5决策树 C4.5决策树

绘图代码:

# 导入必要的库
import pandas as pd  # 用于数据处理和构建 DataFrame
from collections import Counter  # 用于统计样本数量
from math import log2  # 用于计算对数
from graphviz import Digraph  # 用于可视化决策树
from sklearn.preprocessing import LabelEncoder  # 用于将字符串特征编码为数字


# =============================================
# 1. 数据准备(含 ID)
# =============================================
# 构建训练数据集,包含 5 个特征和 1 个目标变量
data = {
    # 每个样本的唯一编号,容易造成过拟合
    "ID": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],

    # 年龄:青年、中年、老年
    "年龄": ["青年", "青年", "青年", "青年", "青年", "中年", "中年", "中年", "中年", "中年",
             "老年", "老年", "老年", "老年", "老年"],

    # 是否有工作:是、否
    "有工作": ["否", "否", "是", "是", "否", "否", "否", "是", "否", "否",
               "否", "否", "是", "是", "否"],

    # 是否有房子:是、否
    "有房子": ["否", "否", "否", "是", "否", "否", "否", "是", "是", "是",
               "是", "是", "否", "否", "否"],

    # 信贷情况:一般、好、非常好
    "信贷情况": ["一般", "好", "好", "一般", "一般", "一般", "好", "好", "非常好", "非常好",
                 "非常好", "好", "好", "非常好", "一般"],

    # 类别:是否贷款成功(同意/拒绝)
    "类别": ["拒绝", "拒绝", "同意", "同意", "拒绝", "拒绝", "拒绝", "同意", "同意", "同意",
             "同意", "同意", "同意", "同意", "拒绝"]
}

# 将数据转换为 pandas 的 DataFrame 格式
df = pd.DataFrame(data)

# 提取特征列名列表(所有列除了最后一列)
features = list(df.columns[:-1])  # 特征:ID、年龄、有工作、有房子、信贷情况

# 目标变量列名(最后一列)
target = df.columns[-1]  # 类别列名


# =============================================
# 2. 信息熵与信息增益计算
# =============================================

def entropy(y):
    """
    计算信息熵 H(Y)
    y: 当前样本的目标变量值(如:['拒绝', '同意', ...])
    返回:当前样本的信息熵
    """
    counts = Counter(y)  # 统计每个类别的数量
    total = len(y)  # 总样本数
    if total == 0:
        return 0  # 防止除以 0
    # 计算 -Σ(p * log2(p))
    return -sum((count / total) * log2(count / total) for count in counts.values())


def conditional_entropy(X_col, y):
    """
    计算条件熵 H(Y|X)
    X_col: 某个特征列的值(如:['青年', '中年', ...])
    y: 对应的目标变量值
    返回:给定该特征下目标变量的条件熵
    """
    values = set(X_col)  # 获取该特征的所有唯一值
    total = len(y)  # 总样本数
    ent = 0
    for v in values:
        mask = (X_col == v)  # 找到该特征值对应的样本
        y_sub = y[mask]  # 取出这些样本的目标变量
        ent += len(y_sub) / total * entropy(y_sub)  # 加权求和
    return ent


def info_gain(dataset, feature):
    """
    计算某个特征的信息增益 IG(Y, X)
    dataset: 整个数据集
    feature: 当前特征名称(如:"年龄")
    返回:该特征的信息增益
    """
    X_col = dataset[feature]  # 取出该特征列
    y = dataset[target]  # 取出目标变量列
    return entropy(y) - conditional_entropy(X_col, y)  # 信息增益 = 总熵 - 条件熵


def split_info(X_col):
    """
    计算分裂信息(Split Information),用于 C4.5 增益率计算
    X_col: 某个特征列的值
    返回:该特征的分裂信息
    """
    counts = Counter(X_col)  # 统计每个特征值出现的次数
    total = len(X_col)  # 总样本数
    # 计算 -Σ(|D_v|/|D| * log2(|D_v|/|D|))
    return -sum((count / total) * log2(count / total) for count in counts.values())


def gain_ratio(dataset, feature):
    """
    计算增益率 GainRatio(Y, X)
    dataset: 整个数据集
    feature: 当前特征名称
    返回:该特征的增益率
    """
    ig = info_gain(dataset, feature)  # 先计算信息增益
    si = split_info(dataset[feature])  # 再计算分裂信息
    return ig / si if si != 0 else float('inf')  # 增益率 = IG / SI


# =============================================
# 3. 手动实现 ID3 和 C4.5 决策树
# =============================================

def id3_tree(dataset, features):
    """
    使用 ID3 算法递归构建决策树
    dataset: 当前数据集
    features: 当前可用特征列表
    返回:当前节点的决策树结构字典
    """
    target_values = dataset[target].unique()  # 获取当前目标变量的唯一值

    # 终止条件1:当前样本全部属于同一类
    if len(target_values) == 1:
        return {'label': target_values[0]}  # 返回叶子节点标签

    # 终止条件2:没有可用特征
    if not features:
        most_common = dataset[target].mode().iloc[0]  # 返回多数类作为预测结果
        return {'label': most_common}

    # 选择信息增益最大的特征
    gains = {f: info_gain(dataset, f) for f in features}  # 计算每个特征的信息增益
    best_feature = max(gains, key=gains.get)  # 选出最大增益的特征

    # 构建当前节点信息
    class_counts = dict(Counter(dataset[target]))  # 统计目标变量分布
    node_info = {
        'feature': best_feature,
        'gain': gains[best_feature],  # 信息增益
        'class_dist': class_counts,  # 类别分布
        'n_samples': len(dataset),  # 样本数量
        'children': {}  # 子节点
    }

    # 递归划分每个特征值
    remaining_features = [f for f in features if f != best_feature]  # 剩余可用特征
    for raw_value in dataset[best_feature].unique():  # 遍历当前特征的每个唯一值
        sub_data = dataset[dataset[best_feature] == raw_value]  # 划分子数据集
        node_info['children'][raw_value] = id3_tree(sub_data, remaining_features)  # 递归生成子树

    return node_info


def c45_tree(dataset, features):
    """
    使用 C4.5 算法递归构建决策树(基于增益率)
    dataset: 当前数据集
    features: 当前可用特征列表
    返回:当前节点的决策树结构字典
    """
    target_values = dataset[target].unique()

    # 终止条件1:当前样本全部属于同一类
    if len(target_values) == 1:
        return {'label': target_values[0]}

    # 终止条件2:没有可用特征
    if not features:
        most_common = dataset[target].mode().iloc[0]
        return {'label': most_common}

    # 选择增益率最大的特征
    gains = {f: gain_ratio(dataset, f) for f in features}
    best_feature = max(gains, key=gains.get)

    # 构建当前节点信息
    class_counts = dict(Counter(dataset[target]))
    node_info = {
        'feature': best_feature,
        'gain_ratio': round(gains[best_feature], 3),
        'class_dist': class_counts,
        'n_samples': len(dataset),
        'children': {}
    }

    # 递归划分每个特征值
    remaining_features = [f for f in features if f != best_feature]
    for raw_value in dataset[best_feature].unique():
        sub_data = dataset[dataset[best_feature] == raw_value]
        node_info['children'][raw_value] = c45_tree(sub_data, remaining_features)

    return node_info


# =============================================
# 4. 构建特征编码器(用于生成 CART 风格的分割条件)
# =============================================
# 保存每个特征的编码器,便于后续可视化时使用
feature_encoders = {}

for feat in features:
    le = LabelEncoder()  # 创建编码器
    le.fit(df[feat])  # 拟合该特征的编码规则
    feature_encoders[feat] = le  # 保存编码器


# =============================================
# 5. 决策树可视化(CART 风格,支持中文)
# =============================================
def visualize_tree_cart_style(tree, feature_encoders, graph=None, parent_id=None, edge_label=""):
    """
    使用 Graphviz 可视化决策树(CART 风格)
    tree: 当前树节点结构
    feature_encoders: 编码器字典
    graph: 当前图对象
    parent_id: 父节点 ID
    edge_label: 边上的标签
    返回:Graphviz 图对象
    """
    from uuid import uuid4  # 用于生成唯一节点 ID

    if graph is None:
        # 初始化一个空图,设置字体支持中文
        graph = Digraph(
            'DecisionTree',
            format='png',
            node_attr={'fontname': 'SimHei'},  # 支持中文节点
            edge_attr={'fontname': 'SimHei'},  # 支持中文边标签
            graph_attr={'fontname': 'SimHei', 'rankdir': 'TB'}  # 树方向从上往下
        )

    node_id = str(uuid4())  # 生成当前节点的唯一标识符

    if 'label' in tree:
        # 如果是叶子节点,显示类别标签
        label = f"类别: {tree['label']}"
        shape = "box"  # 叶子节点用矩形
    else:
        # 如果是内部节点,显示特征、增益等信息
        feat_name = tree['feature']
        metric = round(tree.get('gain', tree.get('gain_ratio', 0)), 3)  # 获取指标值
        metric_label = "信息增益" if 'gain' in tree else "信息增益率"
        n = tree['n_samples']  # 样本数
        dist = ", ".join([f"{k}={v}" for k, v in tree['class_dist'].items()])  # 分布

        # 构造节点标签
        label = (
            f"{feat_name}\\n"
            f"{metric_label}={metric}\\n"
            f"样本数={n}\\n"
            f"分布:{dist}"
        )
        shape = "ellipse"  # 内部节点用椭圆

    graph.node(node_id, label=label, shape=shape)  # 添加当前节点到图中

    if parent_id:
        # 如果有父节点,则画边
        graph.edge(parent_id, node_id, label=edge_label)

    if 'children' in tree:
        # 如果有子节点,递归绘制
        feat_name = tree['feature']
        encoder = feature_encoders[feat_name]  # 获取该特征的编码器
        unique_values = df[feat_name].unique()  # 获取原始特征值
        sorted_values = sorted(encoder.transform(unique_values))  # 编码后的排序值

        for raw_value, child in tree['children'].items():
            encoded_value = encoder.transform([raw_value])[0]  # 把原始值转为编码值
            display_label = get_edge_label(feat_name, encoded_value, sorted_values)  # 生成边标签
            # 递归绘制子树
            visualize_tree_cart_style(child, feature_encoders, graph, node_id, display_label)

    return graph


def get_edge_label(feat_name, encoded_value, sorted_values):
    """
    生成边标签,例如:年龄 <= 0.5、年龄 > 0.5
    feat_name: 特征名
    encoded_value: 编码后的特征值
    sorted_values: 排序后的编码值列表
    返回:边标签字符串
    """
    index = sorted_values.index(encoded_value)
    if index == 0:
        threshold = (sorted_values[index] + sorted_values[index + 1]) / 2
        return f"{feat_name} <= {threshold:.1f}"
    elif index == len(sorted_values) - 1:
        threshold = (sorted_values[index - 1] + sorted_values[index]) / 2
        return f"{feat_name} > {threshold:.1f}"
    else:
        low = (sorted_values[index - 1] + sorted_values[index]) / 2
        high = (sorted_values[index] + sorted_values[index + 1]) / 2
        return f"{low:.1f} < {feat_name} <= {high:.1f}"


# =============================================
# 6. 主程序:构建并可视化两种树
# =============================================

# 构建模型
tree_id3 = id3_tree(df, features)  # 构建 ID3 决策树
tree_c45 = c45_tree(df, features)  # 构建 C4.5 决策树

# 设置可视化图例格式
dot_id3 = visualize_tree_cart_style(tree_id3, feature_encoders)  # 可视化 ID3 树
dot_c45 = visualize_tree_cart_style(tree_c45, feature_encoders)  # 可视化 C4.5 树

# 保存为 PNG 文件,并自动打开查看
dot_id3.render("id3_decision_tree_with_id", view=True)
dot_c45.render("c45_decision_tree_with_id", view=True)

3.4 结论:C4.5如何解决过拟合

  • ID3的缺陷:ID特征因信息增益最大(0.918)被优先选择,导致树分裂为15个叶子节点,完全记忆训练数据(过拟合)。
  • C4.5的修正:ID的信息增益虽高,但内在信息 V ( I D ) V(ID) V(ID)=3.907极大,导致信息增益率(0.235)低于“有房子”(0.422),因此C4.5选择 “有房子” 作为根节点,避免被ID特征误导。
  • 本质原因:信息增益率通过IV(A)惩罚了取值多但分类意义小的特征(如ID),使模型更关注真正有判别力的特征,降低过拟合风险。

3.5 C4.5的局限性

  • 对取值少的特征仍有偏向:若某特征取值少且IV(A)小,可能被过度优先选择(如两取值特征,IV=1时信息增益率=信息增益)。
  • 计算复杂度高:需额外计算IV(A),比ID3耗时更多。

通过信息增益率的归一化,C4.5在保留ID3可解释性的同时,有效缓解了“取值多特征偏好”问题,是决策树从理论到工程应用的重要改进。

四、CART决策树:基于基尼指数的二叉树模型

CART 决策树是一种基于基尼指数(或平方误差)的二叉树模型,广泛应用于分类和回归任务中。它通过最小化基尼指数来选择最优划分特征,确保每一步划分都能带来最大纯度提升。相较于 ID3 或 C4.5 等多叉树模型,CART 结构简单、计算效率高、鲁棒性强,是工业界常用的一种决策树实现方式。

4.1 基尼指数的公式与符号解析

基尼指数相关公式:

  • 数据集 D D D的基尼值:
    Gini ( D ) = 1 − ∑ k = 1 K ( ∣ C k ∣ ∣ D ∣ ) 2 \text{Gini}(D) = 1 - \sum_{k=1}^{K}\left(\frac{|C_k|}{|D|}\right)^2 Gini(D)=1−k=1∑K​(∣D∣∣Ck​∣​)2

  • 特征 A A A的基尼指数:
    Gini_index ( D , A ) = ∑ i = 1 n ∣ D i ∣ ∣ D ∣ Gini ( D i ) \text{Gini\_index}(D, A) = \sum_{i=1}^{n}\frac{|D_i|}{|D|}\text{Gini}(D_i) Gini_index(D,A)=i=1∑n​∣D∣∣Di​∣​Gini(Di​)

  • Gini ( D ) \text{Gini}(D) Gini(D):衡量数据集 D D D的不纯度,值越小纯度越高

  • Gini_index ( D , A ) \text{Gini\_index}(D, A) Gini_index(D,A):特征 A A A的基尼指数,用于选择最优分裂特征

  • K K K:类别数, ∣ C k ∣ |C_k| ∣Ck​∣:第 k k k类的样本数, ∣ D ∣ |D| ∣D∣:总样本数

  • n n n:特征 A A A的取值个数, ∣ D i ∣ |D_i| ∣Di​∣:特征 A A A取第 i i i个值的样本数

4.2 基尼指数的意义

  • 基尼指数衡量的是从数据集中随机抽取两个样本时,它们类别不一致的概率。这个指标越小,说明数据集的纯度越高;反之,则表示数据越混杂。

  • 在决策树构建过程中,当我们使用某个特征对数据集进行划分后,会分别计算每个子集的基尼指数,并通过加权求和得到整体的基尼指数(即 Gini_index ( D , A ) \text{Gini\_index}(D, A) Gini_index(D,A) )。该值越小,意味着划分后的各子集纯度越高,分类效果越好。

  • 可以形象地理解为:假设你有一袋球,颜色各异。如果你随手抓出两个球,颜色不一样的可能性越大,说明这袋球越“混乱”(基尼值高)。我们的目标是找到一种分法(特征),让每次分出来的每一小袋都尽可能接近“同色”,也就是让每袋的基尼指数尽可能小。

4.3 CART决策树案例演示:贷款申请的基尼指数计算

沿用前例,计算特征"有房子"的基尼指数(CART为二叉树,需将多取值特征转化为二叉分裂)。

步骤1:计算数据集D的基尼值
Gini ( D ) = 1 − ( 5 15 ) 2 − ( 10 15 ) 2 = 0.4444 \text{Gini}(D) = 1 - \left(\frac{5}{15}\right)^2 - \left(\frac{10}{15}\right)^2 = 0.4444 Gini(D)=1−(155​)2−(1510​)2=0.4444

步骤2:计算"有房子"特征的基尼指数

  • 有房子:7条样本,6同意,1拒绝
    Gini ( 有房子 ) = 1 − ( 6 7 ) 2 − ( 1 7 ) 2 = 0.2449 \text{Gini}(有房子) = 1 - \left(\frac{6}{7}\right)^2 - \left(\frac{1}{7}\right)^2 = 0.2449 Gini(有房子)=1−(76​)2−(71​)2=0.2449
  • 无房子:8条样本,2同意,6拒绝
    Gini ( 无房子 ) = 1 − ( 2 8 ) 2 − ( 6 8 ) 2 = 0.375 \text{Gini}(无房子) = 1 - \left(\frac{2}{8}\right)^2 - \left(\frac{6}{8}\right)^2 = 0.375 Gini(无房子)=1−(82​)2−(86​)2=0.375
  • 基尼指数:
    Gini_index ( D , 有房子 ) = 7 15 × 0.2449 + 8 15 × 0.375 = 0.3176 \text{Gini\_index}(D, 有房子) = \frac{7}{15} \times 0.2449 + \frac{8}{15} \times 0.375 = 0.3176 Gini_index(D,有房子)=157​×0.2449+158​×0.375=0.3176

步骤3:计算其他特征的基尼指数
以"年龄"特征为例,需转化为二叉分裂(如"青年"vs"非青年"):

  • 青年:5样本,4拒绝,1同意
    Gini ( 青年 ) = 1 − ( 4 5 ) 2 − ( 1 5 ) 2 = 0.32 \text{Gini}(青年) = 1 - \left(\frac{4}{5}\right)^2 - \left(\frac{1}{5}\right)^2 = 0.32 Gini(青年)=1−(54​)2−(51​)2=0.32
  • 非青年:10样本,6拒绝,4同意
    Gini ( 非青年 ) = 1 − ( 6 10 ) 2 − ( 4 10 ) 2 = 0.48 \text{Gini}(非青年) = 1 - \left(\frac{6}{10}\right)^2 - \left(\frac{4}{10}\right)^2 = 0.48 Gini(非青年)=1−(106​)2−(104​)2=0.48
  • 基尼指数:
    Gini_index ( D , 年龄 ) = 5 15 × 0.32 + 10 15 × 0.48 = 0.4267 \text{Gini\_index}(D, 年龄) = \frac{5}{15} \times 0.32 + \frac{10}{15} \times 0.48 = 0.4267 Gini_index(D,年龄)=155​×0.32+1510​×0.48=0.4267

步骤4:选择基尼指数最小的特征
"有房子"的基尼指数0.3176最小,作为分裂特征,生成二叉树:

  • 左子树:有房子,基尼值0.2449(更纯)
  • 右子树:无房子,基尼值0.375(较不纯)

步骤5:递归构建子树
在完成当前节点的最佳划分特征选择后(如“有房子”),CART 决策树会基于该特征的不同取值,将数据集划分为两个子集,并对每个子集递归地重复以下过程:

  • 判断是否满足终止条件:
    • 若当前子集中所有样本属于同一类别(基尼值为 0),则将其设为叶子节点,直接返回类别结果。
    • 若达到预设的最大深度(如 max_depth=3)或样本数过少(如小于 min_samples_split),也停止继续分裂。
  • 否则,继续进行最优划分特征的选择:
    • 对当前子集重新计算各个特征的基尼指数。
    • 选择基尼指数最小的特征作为新的划分依据。
    • 再次划分数据集并生成新的左右子节点:
    • 每个子节点代表一个划分后的子集。
    • 对每个子节点递归执行上述步骤,直到满足终止条件为止。
  • 最终形成一棵完整的二叉决策树:

在这里插入图片描述

绘图代码:

# 导入必要的库
import pandas as pd  # 用于构建 DataFrame 数据结构
from sklearn.tree import DecisionTreeClassifier, plot_tree  # 构建和可视化决策树
from sklearn.preprocessing import LabelEncoder  # 对字符串特征进行编码
import matplotlib.pyplot as plt  # 可视化工具

# 设置中文字体显示(解决中文乱码问题)
plt.rcParams['font.sans-serif'] = ['SimHei']  # 将默认字体设置为"SimHei(黑体)",确保中文标签正常显示
plt.rcParams['axes.unicode_minus'] = False  # 修复负号显示为方块的问题(确保特殊符号渲染正常)

# =============================================
# 1. 数据准备(含 ID)
# =============================================
# 构建训练数据集,包含 5 个特征和 1 个目标变量
data = {
    # 每个样本的唯一编号,容易造成过拟合
    "ID": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],

    # 年龄:青年、中年、老年
    "年龄": ["青年", "青年", "青年", "青年", "青年", "中年", "中年", "中年", "中年", "中年",
             "老年", "老年", "老年", "老年", "老年"],

    # 是否有工作:是、否
    "有工作": ["否", "否", "是", "是", "否", "否", "否", "是", "否", "否",
               "否", "否", "是", "是", "否"],

    # 是否有房子:是、否
    "有房子": ["否", "否", "否", "是", "否", "否", "否", "是", "是", "是",
               "是", "是", "否", "否", "否"],

    # 信贷情况:一般、好、非常好
    "信贷情况": ["一般", "好", "好", "一般", "一般", "一般", "好", "好", "非常好", "非常好",
                 "非常好", "好", "好", "非常好", "一般"],

    # 类别:是否贷款成功(同意/拒绝)
    "类别": ["拒绝", "拒绝", "同意", "同意", "拒绝", "拒绝", "拒绝", "同意", "同意", "同意",
             "同意", "同意", "同意", "同意", "拒绝"]
}

# 将数据转换为 pandas 的 DataFrame 格式
df = pd.DataFrame(data)

# 提取特征和目标变量
X = df.drop("类别", axis=1)  # 特征:年龄、有工作、有房子、信贷情况
y = df["类别"]  # 目标变量:类别(是否贷款成功)

# =============================================
# 2. 特征编码(将字符串特征转为数字)
# =============================================
# 创建 LabelEncoder 并对每个特征列进行编码
encoders = {}  # 存储每个特征的编码器
for col in X.columns:
    le = LabelEncoder()
    X[col] = le.fit_transform(X[col])  # 转换为数字
    encoders[col] = le  # 保存编码器供后续反编码用

# 对目标变量进行编码:'拒绝' -> 0, '同意' -> 1
y = LabelEncoder().fit_transform(y)

# =============================================
# 3. 构建 CART 决策树模型
# =============================================
# 创建 CART 分类器,使用默认的 gini 指数作为划分标准
clf = DecisionTreeClassifier(criterion='gini', max_depth=3)

# 训练模型
clf.fit(X, y)

# =============================================
# 4. 使用 matplotlib 可视化决策树结构
# =============================================
# 设置绘图风格
plt.figure(figsize=(10, 6))  # 设置画布大小

# 绘制决策树结构图
plot_tree(
    clf,  # 决策树模型
    feature_names=X.columns,  # 特征名称
    class_names=["拒绝", "同意"],  # 类别名称(中文支持)
    filled=True,  # 使用颜色填充节点
    fontsize=10,  # 字体大小
    proportion=False,  # 显示样本数量而非比例
    rounded=True  # 圆角矩形显示节点
)

# 设置图像标题并调整布局
plt.title("CART 决策树结构(基于基尼指数)")
plt.tight_layout()  # 自动调整子图参数,防止重叠

# 显示图像
plt.show()

4.4 Scikit-learn 中 CART 决策树的 API

  1. 分类树:DecisionTreeClassifier
    用于离散标签分类(如是否贷款),基于基尼指数或信息熵生成二叉树。
  • 核心参数:
    criterion 控制分裂标准(gini为默认基尼指数,entropy为信息熵);
    max_depth 限制树深度(避免过拟合,如设为3-10);
    min_samples_split 规定节点分裂的最小样本数(默认2);
    min_samples_leaf 设定叶子节点最小样本数(默认1)。
  • 关键方法:
    fit(X, y) 训练模型(X为特征矩阵,y为离散标签);
    predict(X) 预测类别;
    predict_proba(X) 输出类别概率;
    score(X, y) 计算准确率。
  1. 回归树:DecisionTreeRegressor
    用于连续值预测(如房价),基于均方误差或平均绝对误差分裂。
  • 核心参数:
    criterion 可选mse(均方误差,默认)或mae(平均绝对误差);
    其他参数(如max_depth、min_samples_split)与分类树逻辑一致。
  • 关键方法:
    fit(X, y) 训练模型(y为连续值);
    predict(X) 输出回归值;
    score(X, y) 计算R²系数(越接近1拟合越好)。
  1. 核心共通点
  • 分裂策略:splitter='best'(全局最优)或'random'(随机分裂防过拟合);
  • 特征重要性:训练后通过feature_importances_属性获取;
  • 可视化:用sklearn.tree.export_graphviz或plot_tree展示树结构。
  1. 分类与回归差异
    分类树用基尼/熵衡量纯度,输出类别概率;回归树用MSE/MAE衡量误差,输出连续值预测,评估指标为R²而非准确率。

4.5 小结

CART决策树的核心优势在于:

  1. 始终生成二叉树,结构更简单
  2. 基尼指数计算效率高于熵运算
  3. 同时支持分类和回归任务(回归时使用平方误差最小化)
  4. 对噪声数据和缺失值的处理更鲁棒

五、三大决策树模型对比总结

模型核心指标节点分裂方式特征处理树结构优缺点
ID3信息增益多叉分裂仅支持离散特征多叉树优点:计算简单;缺点:偏向取值多的特征,易过拟合
C4.5信息增益率多叉分裂支持离散/连续特征多叉树优点:修正ID3的偏向问题;缺点:计算复杂,对取值少的特征仍有偏向
CART基尼指数二叉分裂支持离散/连续特征二叉树优点:计算高效,泛化能力强,支持分类/回归;缺点:对高维数据表现不佳

决策树的发展历程体现了机器学习算法的优化思路——从简单有效到复杂精准,再到平衡效率与性能。实际应用中,可根据数据特点和任务需求选择合适的决策树模型,或采用集成学习(如随机森林)进一步提升模型效果。

六、其他重要决策树算法

6.1 CHAID:基于统计检验的决策树

核心思想:使用卡方检验(分类目标)或F检验(连续目标)评估特征与目标的相关性

公式示例:
χ 2 = ∑ ( O i − E i ) 2 E i \chi^2 = \sum \frac{(O_i - E_i)^2}{E_i} χ2=∑Ei​(Oi​−Ei​)2​
其中 O i O_i Oi​为观察频数, E i E_i Ei​为期望频数

优势:

  • 支持多叉分裂,直观展示特征交互作用
  • 自动处理缺失值
  • 可生成非二叉树结构

应用场景:市场细分、客户画像分析

6.2 QUEST:快速无偏决策树

核心思想:通过统计检验选择分裂特征,避免CART对连续特征的偏向

算法流程:

  1. 使用ANOVA F-test选择最佳分裂特征
  2. 应用二次判别分析确定最优分裂点
  3. 递归构建二叉树

优势:

  • 无偏特征选择
  • 计算效率高
  • 处理高维数据能力强

应用场景:基因表达数据分析、高维生物信息学

6.3 条件推断树:统计驱动的决策树

核心思想:基于置换检验(Permutation Test)选择分裂变量和分裂点

算法特点:

  1. 计算特征与目标的统计相关性
  2. 评估分裂显著性的p值
  3. 仅当p值小于阈值时才进行分裂

公式核心:
p -value = P ( ∣ T ∣ ≥ ∣ t ∣ ∣ H 0 ) p\text{-value} = P(|T| \geq |t| | H_0) p-value=P(∣T∣≥∣t∣∣H0​)
其中 T T T为检验统计量, t t t为观察值, H 0 H_0 H0​为无关联假设

优势:

  • 有效控制变量选择偏差
  • 适用于混合类型特征(离散+连续)
  • 提供统计显著性评估

应用场景:临床试验数据分析、社会科学研究

6.4 斜决策树(Oblique Decision Tree)

核心思想:允许使用特征的线性组合进行分裂(如 0.5 × 年龄 + 0.8 × 收入 > 50 0.5 \times \text{年龄} + 0.8 \times \text{收入} > 50 0.5×年龄+0.8×收入>50)

数学表示:
∑ j = 1 p w j x j > θ \sum_{j=1}^{p} w_j x_j > \theta j=1∑p​wj​xj​>θ
其中 w j w_j wj​为特征权重, θ \theta θ为阈值

优势:

  • 构建更紧凑的树结构
  • 提升模型泛化能力
  • 更好处理相关特征

挑战:

  • 分裂点优化复杂度高
  • 需结合线性规划求解
  • 训练时间显著增加

应用场景:图像识别、金融风险评估

6.5 流数据决策树(Hoeffding Tree)

核心思想:基于Hoeffding不等式,在有限内存下处理无限数据流

核心公式:
n > R 2 ln ⁡ ( 1 / δ ) 2 ϵ 2 n > \frac{R^2 \ln(1/\delta)}{2\epsilon^2} n>2ϵ2R2ln(1/δ)​
其中 n n n为所需样本数, R R R为随机变量范围, δ \delta δ为置信度, ϵ \epsilon ϵ为误差界

优势:

  • 单次遍历数据
  • 实时更新模型
  • 有限内存需求

应用场景:实时交易监控、物联网设备数据分析

决策树(Decision Tree,DT)(ID3、C4.5、剪枝、CART) 决策树模型是树形结构,既可以用于分类,也可以用于回归。它是if-then规则的集合,也是定义在特征空间与类空间上的条件概率分布。一颗决策树由结点和有向边组成,结点分为内部结点(包括根结点,表示特征)和叶结点(表示类),有向边的权值表示特征的一个取值。 决策树模型是根据损失函数最小化的原则建立的。通常包括3个步骤:一、特征选择二、生成决策树三、修剪决策树 为了方便描述,设训练数据集D = {(x1,y1),(x2,y2),…,(xN,yN)},其中N为样本个数,|D|表示数据集D的样本容量,|D|=N。 xi 阅读详情

相关推荐

Decision Tree 决策树 - ID3, C45, C50, CART...

是什么 决策树是最简单的也是最具解释性和表达性的一种机器学习算法,既可以处理分类问题(ID3,C45,C50),也可以处理回归问题(CART)。 它是根据特征(feature)的值逐步把数据分类,直到所有的叶子节点属于同一个类型结束。注意决策树都是贪婪的。 关键概念 1. 如何确定哪个特征被优先选择用来分类。 根据某一个特征划分数据集,其划分前后信息熵会有变化。优先选择的特征是让给让

Hisense的专栏 1万+

【AI深究】决策树(Decision Tree)全网最详细全流程详解与案例(附Python代码演示)|数学原理、案例流程、代码演示及结果解读|ID3、C4.5、CART算法|工程启示、分类、回归决策树

大家好,我是爱酱。本篇将会系统讲解决策树(Decision Tree)的定义、原理、数学推导、常见算法、代码实现与工程应用。内容适合初学者和进阶读者,配合公式和可视化示例。这期的文章会较简单,如果大家有兴趣可以到爱酱主页搜寻更多分类、回归等的算法! 注:本文章含大量数学算式、详细例子说明及大量代码演示,大量干货,建议先收藏再慢慢观看理解。新频道发展不易,你们的每个赞、收藏跟转发都是我继续分享的动力!

AI人工智能爱酱~你的AI学习好帮手~ 7763

java结合Ai

Spring AI 是 AI 工程的应用框架。其目标是将Spring生态系统的设计原则(如可移植性和模块化设计)应用于AI领域,并促进使用POJO作为应用程序的构建块到AI领域。特征跨 AI 提供商的可移植 API 支持,适用于聊天、文本到图像和嵌入模型。支持同步 API 和流 API 选项。还支持下拉以访问特定于模型的功能。聊天模型亚马逊基岩人类学Cohere的命令AI21 Labs的侏罗纪-2Meta 的 LLama亚马逊的泰坦人类学克劳德Azure 开放式 AI。

qq_67832732的博客 2848

支持向量机(SVM)和决策树(Decision Tree)简介

选取特征,只是决策树中的 ID3 算法,这种算法倾向于选择取值较多的特征,后续提出的 C4.5 算法,以信息增益率作为特征选择指标,在一定程度上克服了这个缺点. 其他的决策树算法还有 CART,既能做分类也能做回归,感兴趣的读者可以了解一下.好的分类特征意味着对结果更精确的预测. 而预测得越准确,预测结果发生的概率也就越大. 大的概率意味着小的信息量,小的信息量会带来小的信息熵,进而使。终止条件可以这样设置:当前节点的信息熵小于给定的阈值时,就停止递归,取占比最大的类作为当前叶子节点的类别.

Blogs of zcy1221 8613

C#实战:如何用Bartender 10.1实现动态打印与批量打印(附完整源码)

本文深入探讨了如何在C#项目中高效集成Bartender 10.1,实现企业级的动态打印与批量打印功能。文章提供了从环境配置、COM接口精讲、高可用打印服务类封装,到批量打印性能优化及生产环境部署的全套实战方案与源码,帮助开发者构建健壮、可维护的打印解决方案。

weixin_29290963的博客 435

MATLAB实战:从零推导合成孔径雷达(SAR)后向投影(BP)算法核心公式与代码实现

本文详细介绍了如何使用MATLAB从零推导合成孔径雷达(SAR)后向投影(BP)算法的核心公式与代码实现。通过基础概念讲解、数学原理推导、距离维脉冲压缩实现及完整MATLAB代码展示,帮助读者掌握SAR成像的关键技术。特别针对BP算法的优化技巧和常见问题提供了实用解决方案,适合雷达信号处理领域的开发者和研究者参考。

weixin_28683689的博客 251

CART(二叉树)

自带的决策树只能实现。

ttest11的博客 485

QCC308x/3095收发一体:TX/RX双模一拖二与多编码广播实战解析

本文深度解析高通QCC308x/3095蓝牙音频芯片的TX/RX双模功能与广播应用。芯片支持发射和接收模式下的“一拖二”连接,并能实现LE Audio多设备广播,显著提升多设备音频切换体验与商业广播能力,适用于健身、导览等丰富场景。

g9h0i1的博客 1003

决策树

决策树(decision tree)是一种基本的分类与回归方法,此处主要讨论分类的决策树。 决策树学习的算法通常是一个递归地选择最优特征(选择方法的不同,对应着不同的算法),并根据该特征对训练数据进行分割,使得各个子数据集有一个最好的分类的过程。这一过程对应着对特征空间的划分,也对应着决策树的构建。下面为一个实例图: 构造流程: 1) 开始:构建根节点,将所有训练数据都放在根节点,选择一个最优特征,按着这一特征将训练数据集分割成子集,使得各个子集有一个在当前条件下最好的分类。 2) 如果这些子集已经能够被

莫一丞元 4028

AI 与新媒体

AI重构新媒体生态:从生产到分发的全链路变革 AI正成为新媒体领域的核心基础设施,通过五大能力重塑内容产业:自动化生产(AIGC写作/制图/剪辑效率提升5-10倍)、智能分发(算法精准匹配用户)、数据洞察(实时舆情分析)、风险管控(审核效率提升12倍)和运营优化(A/B测试自动化)。这推动行业从"人找内容"转向"内容找人",制作成本下降90%的同时,也带来同质化加剧、版权争议和职业重构等挑战。当前阶段,人机协同成为主流——AI处理标准化生产,人类专注创意与价值观把控。

eastyuxiao的专栏 380

第二章 零差云控关节模组内部构造

对零差云控的eRob70I进行了拆解

SFY__优快云的博客 5964

机器学习 (二) 分类决策树

1 引言 在这一篇文章中,将讨论一种被广泛使用的分类算法—决策树(decision tree)。相比贝叶斯算法,决策树的优势在于构造过程不需要任何领域知识或参数设置,因此在实际应用中,对于探测式的知识发现,决策树更加适用。 2 决策树介绍 决策树是一种机器学习的方法,决策树的生成算法有ID3, C4.5 和 C5.0 等。决策树是一种树形结构,其中每个内部节点表示一个属性上的判断,每个分支代表一个...

AI黑板报的专栏 2632

ADS2023实战:2.4GHz超外差接收机从设计到链路预算全流程解析

本文以ADS 2023软件为平台,详细解析了2.4GHz超外差接收机从核心指标定义、架构原理到完整链路搭建与仿真的全流程。通过实战演练,重点阐述了如何利用ADS进行谐波平衡仿真和链路预算分析,以量化评估系统增益、噪声系数等关键性能,为射频工程师提供了一套从理论到仿真的系统级设计方法。

herb5的博客 817

GBDT学习总结(Boosting、决策树)

1 GBDT简介 GBDT (Gradient Boosting Decision Tree) 梯度提升决策树。DT-Decision Tree决策树,GB是Gradient Boosting,是一种学习策略,GBDT的含义就是用Gradient Boosting的策略训练出来的DT模型 在前几年深度学习还没有大行其道之前,GBDT在各种竞赛是大放异彩。一是效果确实挺不错。二是即可以用于分类也可以用于回归。三是可以筛选特征 2 集成学习 集成学习就是将多个弱的学习器结合起来组成一个强的学习器。 这就涉及到,

zephyr_wang的博客 2834

增益调度控制 —— 理论、案例与交互式 GUI 实现

本文详细介绍了增益调度控制的基本原理、数学模型及公式推导,探讨了该方法在适应非线性系统和大范围工作条件下的优势与局限。通过航空飞行控制、发动机推力控制以及化工过程控制三个典型案例,我们展示了如何利用调度变量动态调整控制增益,从而使得控制系统在各个工作点均能达到优良性能。为帮助工程师和研究者更直观地理解并验证增益调度控制的实际效果,本文提供了一套基于 Python 与 PyQt6 的交互式 GUI 控制系统代码。用户不仅可以实时查看仿真数据,还能通过在线调节参数直观体验调度控制的优势。

闲人编程的博客 1480

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

机器学习系列 06:决策树 01

本内容将介绍用于分类的决策树(decision tree),以及 ID3、C4.5 和 CART 算法。

步入人工智能 607

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

决策树:ID3、C4.5、CART决策树生成算法

示例训练数据 以如下数据集为例分别介绍决策树ID3、C4.5、CART的生成算法: ID3生成算法 例题:利用训练数据集,用ID3算法建立决策树。 ID3算法只有树的生成,所以该算法生成的树容易产生过拟合。 C4.5生成算法 C4.5与ID3类似,但有一点不同,C4.5在生成的过程中使用了信息增益比来选择特征。 CART生成算法 CART假设决策树是二叉树,内部结点特征的取值为“是”和“...

我的AI笔记 2741

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

【机器学习 | 决策树】万字长文详解决策树前世今生各种算法变体,以ID3、CRAT、C4.5、C5.0为例,确定不来看看?

本系列旨在普及那些深度学习路上必经的核心概念,文章内容都是博主用心学习收集所写,欢迎大家三联支持!本系列会一直更新,核心概念系列会一直更新!欢迎大家订阅。

计算机魔术师的blog 571

机器学习算法之决策树(decision tree)

决策树(Decision Tree,又称为判定树)算法是机器学习中常见的一类算法,是一种以树结构形式表达的预测分析模型。决策树属于监督学习(Supervised learning),根据处理数据类型的不同,决策树又为分类决策树与回归决策树。最早的的决策树算法是由Hunt等人于1966年提出,Hunt算法是许多决策树算法的基础,包括ID3、C4.5和CART等。

十年以上架构设计经验,专注于软件架构和人工智能领域,对机器视觉、NLP、音视频等领域都有涉猎 1万+

决策树(Decision Tree)

决策树,顾名思义,就是帮我们做出决策的树。现实生活中我们往往会遇到各种各样的抉择,把我们的决策过程整理一下,就可以发现,该过程实际上就是一个树的模型。more决策树分为分类树和回归树两种,分类树对离散变量做决策树,回归树对连续变量做决策树,这里我们只讨论分类树。比如选择好瓜的时候:我们可以认为色泽、根蒂、敲声是一个西瓜的三个特征,每次我们做出抉择都是基于这三个特征来把一个节点分成好几个新的节点。

crossoverpptx的博客 1万+

Decision Tree决策树 ID3,C4.5,CART方法原理及伪代码

1.算法原理 决策树:决策树是一个通过训练的数据来搭建起的树结构模型,根节点中存储着所有数据集和特征集,当前节点的每个分支是该节点在相应的特征值上的表现,而叶子节点存放的结果则是决策结果。通过这个模型,我们可以高效的对于未知的数据进行归纳分类。每次使用决策树时,是将测试样本从根节点开始,选择特征分支一直向下直至到达叶子节点,然后得到叶子节点的决策结果。 其中决策树算法的关键在于如何选出一个特...

zhongzhh8的博客 8909

机器学习:决策树(Decision Tree)--ID3算法

决策树的主要算法 构建决策树的关键:按照什么样的次序来选择变量(属性/特征)作为分类依据。 根据不同的目标函数,建立决策树主要有以下三种算法 ID3(J.Ross Quinlan-1975) 核心:信息熵,信息增益 C4.5——ID3的改进,核心:信息增益比/增益率 CART(Breiman-1984),核心:基尼系数 ID3算法 由Ross Quinlan在1986年提出,ID3决策树可以有多个分支,但是不能处理特征值为连续的情况,根据“最大信息熵增益”选取当前最佳的特征来分割数据。

qq_45882032的博客 7541

10.【机器学习】十大算法之一决策树(Decision tree)算法原理讲解

决策树是一种广泛应用于机器学习和数据分析领域的算法,它特别适用于分类和回归问题。作为一种监督学习算法,决策树通过模仿人类决策过程来构建预测模型。它的核心思想是从数据特征中选择最优的属性作为决策节点,然后根据这个属性的值将数据分成几个子集,这个过程递归地在每个子集上重复,直到满足某个停止条件。决策树的结构可以形象地看作是一棵树,其中根节点代表整个数据集,内部节点代表数据的一个特征属性,叶节点则代表最终的决策结果。从根节点到叶节点的每条路径都代表一个规则,这些规则合在一起就形成了一个完整的决策过程。

weixin_50804299的博客 6666

决策树Decision Tree+ID3+C4.5算法实战

决策树Decision Tree 决策树的三种算法: 举个栗子: 熵entropy的概念: 信息熵越大,不确定性越大。信息熵越小,不确定性越小。 骰子计算结果: ID3算法(根据信息熵来决定): 选择根节点ID3算法: 首先以结果buys_computer来计算总的信息熵D。 然后计算年龄的信息熵,只看年龄的部分,年轻的5/14,然后查看年龄中的buys_computer,2/5是yes...

那个Sharon 2668

决策树(decision tree):ID3、C4.5、CART

文章目录决策树(decision tree)决策树模型特征选择信息增益信息增益比ID3决策树生成决策树修建C4.5决策树生成决策树修建CART决策树生成决策树修建 决策树(decision tree)   决策树模型是一个分类与回归方法,属于监督学习模型,是一个概率模型和判别模型。 决策树模型   决策树模型包括特征选择,决策树生成和决策树剪枝。 特征选择   特征选择在于选取对分类有帮助的特征...

Leon_winter的博客 2487

分类算法之决策树(Decision Tree)

决策树,顾名思义,就是帮我们做出决策的树,生活中我们遇到各种各样的抉择,我们的决策过程就是一个树的模型,通过对一系列问题进行if/else的推导,最终实现相关决策例如:在选择瓜的时候我们认为色泽、根蒂、敲声是一个西瓜的三个特征,每次我们做出抉择都是基于这三个特征来把一个节点分成好几个新的节点,在我们的问题中,决策的内容是将结果分成两类, 即是(1)否(0)好瓜,这一智类决策问题被称为分类问题,决策树是一种简单的处理分类问题的算法。

clriszjgson的博客 3484
上一篇: RNN(Recurrent Neural Network,循环神经网络)家族详解(RNN,LSTM,GRU)
下一篇: 人工智能概念之七:集成学习思想(Bagging、Boosting、Stacking)
.30-06Springfield
博客等级 码龄7年 321粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值