决策树的构建

一、决策树的定义

决策树又称为判定树,是数据挖掘技术中的一种重要的分类与回归方法,它是一种以树结构形式来表达的预测分析模型。其每个非叶节点表示一个特征属性上的测试,每个分支代表这个特征属性在某个值域上的输出,而每个叶节点存放一个类别。

一般,一棵决策树包含一个根节点,若干个内部结点和若干个叶结点。

叶结点对应于决策结果,其他每个结点对应于一个属性测试。每个结点包含的样本集合根据属性测试的结果划分到子结点中,根结点包含样本全集,从根结点到每个叶结点的路径对应了一个判定的测试序列。决策树学习的目的是产生一棵泛化能力强,即处理未见示例强的决策树。

使用决策树进行决策的过程就是从根节点开始,测试待分类项中相应的特征属性,并按照其值选择输出分支,直到到达叶子节点,将叶子节点存放的类别作为决策结果。

二、决策树的构造

算法核心思想

决策树通过递归地将数据集划分为更纯的子集来构建树结构。每次划分选择能够带来最大信息增益的特征,直到满足停止条件(如所有样本属于同一类别或没有更多特征可用)。

决策树的关键在于如何选择最优的划分属性,对于二分类而言,就是尽量使得划分的样本属于同一类别,即“纯度”最高的属性。对于度量特征的纯度,需要用信息熵。

信息熵

信息熵的定义:当前的样本集D中第k类样本所占的比例为,K为类别的总数。

则样本集的信息熵为

对于Ent(D)的值来说,Ent(D)的值越小,D的纯度越高

三、代码分析

1. 计算熵

def calculate_entropy(data):

    # 计算数据集的熵
    total_count = len(data)  # 计算数据集的总数
    class_counts = np.unique(data[:, -1], return_counts=True)[1]  # 计算数据集中每个类别的数量
    entropy = 0  # 初始化熵为0
    for count in class_counts:
        probability = count / total_count  # 计算每个类别的概率
        entropy -= probability * np.log2(probability)  # 计算熵
    return entropy  # 返回熵

2. 计算信息增益

def calculate_info_gain(data, feature_index):
    # 计算数据集的熵
    total_entropy = calculate_entropy(data)
    # 获取特征列的唯一值
    unique_values = np.unique(data[:, feature_index])
    # 初始化加权熵
    weighted_entropy = 0
    # 遍历特征列的唯一值
    for value in unique_values:
        # 获取特征列等于当前值的子数据集
        sub_data = data[data[:, feature_index] == value]
        # 计算子数据集的熵
        sub_entropy = calculate_entropy(sub_data)
        # 计算加权熵
        weighted_entropy += (len(sub_data) / len(data)) * sub_entropy
    # 计算信息增益
    info_gain = total_entropy - weighted_entropy
    # 返回信息增益
    return info_gain

3. 选择最佳特征

def choose_best_feature(data):
    # 获取特征数量
    num_features = data.shape[1] - 1
    # 初始化最佳特征为None
    best_feature = None
    # 初始化最大信息增益为0
    max_info_gain = 0
    # 遍历每个特征
    for i in range(num_features):
        # 计算当前特征的信息增益
        info_gain = calculate_info_gain(data, i)
        # 如果当前特征的信息增益大于最大信息增益
        if info_gain > max_info_gain:
            # 更新最大信息增益
            max_info_gain = info_gain
            # 更新最佳特征
            best_feature = i
    # 返回最佳特征
    return best_feature

4. 多数表决

# 定义一个函数,用于找出数据集中出现次数最多的类别
def majority_class(data):
    # 使用numpy的unique函数,找出数据集中最后一列的唯一值,并返回其出现次数
    class_counts = np.unique(data[:, -1], return_counts=True)[1]
    # 找出出现次数最多的类别的索引
    max_count_index = np.argmax(class_counts)
    # 返回出现次数最多的类别
    return np.unique(data[:, -1])[max_count_index]

 5. 构建决策树

def create_decision_tree(data):
    # 如果数据集中所有样本的标签都相同,则返回该标签
    if len(np.unique(data[:, -1])) == 1:
        return data[0, -1]
    # 如果数据集中只有一个特征,则返回该特征中出现次数最多的标签
    if data.shape[1] == 1:
        return majority_class(data)
    # 选择最佳特征
    best_feature = choose_best_feature(data)
    # 创建决策树
    tree = {best_feature: {}}
    # 获取最佳特征的所有取值
    unique_values = np.unique(data[:, best_feature])
    # 遍历最佳特征的所有取值
    for value in unique_values:
        # 获取最佳特征取值为value的子数据集
        sub_data = data[data[:, best_feature] == value]
        # 删除最佳特征
        sub_data = np.delete(sub_data, best_feature, axis=1)
        # 递归调用create_decision_tree函数,生成子树
        tree[best_feature][value] = create_decision_tree(sub_data)
    # 返回决策树
    return tree

 四、实验小结

理论与实践的印证 决策树的构造过程(如信息熵、信息增益的计算)在理论上清晰易懂,但实际编码时发现细节处理尤为重要。例如,递归终止条件的设定、特征划分时的数据拆分逻辑,都需要严谨的边界条件判断,否则容易陷入无限循环或得到错误结果。

信息增益的局限性 实验中通过信息增益选择最优特征,但实际应用中可能遇到高基数特征的干扰,这类特征的信息增益往往偏高但泛化能力差。这让我意识到,可能需要引入增益率或基尼系数等替代指标来优化特征选择。

过拟合问题的思考 实验中构建的决策树会一直分裂直到纯度达到100%,但这样生成的树容易过拟合。可以加入预剪枝或后剪枝策略,提升模型的泛化能力。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值