西瓜书复习:决策树

一棵决策树包含一个根结点,若干个内部结点和若干个叶结点。叶结点对应于决策结果,其他每个结点则对应于一个属性测试。
每个结点包含的样本集合根据属性测试的节点被划分到子结点中。根结点包含样本全集,从根结点到每个叶结点的路径对应了一个判定测试序列。决策树学习的目的是为了产生一棵泛化能力强的决策树,其基本流程遵循简单的分治策略。
在这里插入图片描述
决策树的生成是一个递归的过程,三种情况会导致递归返回
1.当前结点包含的样本全属于同一类别,无需划分;
2.当前属性集为空,或者所有样本在所有属性上取值相同,无法划分;
3.当前结点包含的样本集合为空,不能划分

情况2我们把当前结点标记为叶节点,并将其设定为该结点所含样本最多的类别;情况3同样把当前结点标记为叶节点,但将其类别设定为其父节点所含样本最多的类别。
情况2是利用当前结点的后验分布,情况3则是把父节点的样本分布作为当前结点的先验分布。

决策树的关键是如何选择最优划分属性。随着划分过程不断进行,我们希望决策树的分支结点所包含的样本尽可能属于同一类别。
信息熵是度量样本集合纯度最常用的一种指标。假定当前样本集合D中第k类样本所占的比例为pk,D的信息熵定义为
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是用Python实现的西瓜id3决策树模型的代码: ```python import math import pandas as pd class Node: ''' 决策树节点类 ''' def __init__(self, col=-1, value=None, results=None, tb=None, fb=None): self.col = col # 待检验的判断条件所对应的列索引值 self.value = value # 为了使结果为True,当前列必须匹配的值 self.results = results # 存储叶节点上的结果,是一个字典形式,键为类别,值为次数 self.tb = tb # 左子树 self.fb = fb # 右子树 def load_data(): ''' 加载西瓜数据集,返回特征数据和标签 ''' data = pd.read_csv('watermelon.csv') return data.iloc[:, 1:-1], data.iloc[:, -1] def calc_entropy(labels): ''' 计算数据集的熵 ''' total = len(labels) counts = {} for label in labels: if label not in counts: counts[label] = 0 counts[label] += 1 entropy = 0.0 for key in counts: p = counts[key] / total entropy -= p * math.log2(p) return entropy def split_data(data, labels, col, value): ''' 根据给定特征划分数据集 ''' tb_rows, fb_rows = [], [] for i in range(len(data)): row = list(data.iloc[i]) if row[col] == value: tb_rows.append(row + [labels[i]]) else: fb_rows.append(row + [labels[i]]) return pd.DataFrame(tb_rows, columns=data.columns.tolist() + ['label']), pd.DataFrame(fb_rows, columns=data.columns.tolist() + ['label']) def build_tree(data, labels): ''' 构建决策树 ''' if len(labels) == 0: return Node() current_entropy = calc_entropy(labels) best_gain = 0.0 best_criteria = None best_sets = None feature_num = len(data.columns) for col in range(feature_num): column_values = set(data.iloc[:, col]) for value in column_values: tb_data, fb_data = split_data(data, labels, col, value) p = len(tb_data) / len(data) gain = current_entropy - p * calc_entropy(tb_data['label']) - (1 - p) * calc_entropy(fb_data['label']) if gain > best_gain and len(tb_data) > 0 and len(fb_data) > 0: best_gain = gain best_criteria = (col, value) best_sets = (tb_data, fb_data) if best_gain > 0: tb = build_tree(best_sets[0], best_sets[0]['label']) fb = build_tree(best_sets[1], best_sets[1]['label']) return Node(col=best_criteria[0], value=best_criteria[1], tb=tb, fb=fb) else: return Node(results={label: len([label for label in labels if label == '是']), '否': len([label for label in labels if label == '否'])}) def classify(sample, tree): ''' 使用决策树对单个样本进行分类 ''' if tree.results is not None: return tree.results else: v = sample[tree.col] branch = None if v == tree.value: branch = tree.tb else: branch = tree.fb return classify(sample, branch) def predict(data, tree): ''' 对数据集进行分类 ''' return [classify(list(data.iloc[i]), tree) for i in range(len(data))] data, labels = load_data() tree = build_tree(data, labels) print(predict(data, tree)) ``` 这里使用了pandas库来读取数据集,需要将数据集放在与代码文件相同的目录下,并命名为watermelon.csv。函数load_data返回的是特征数据和标签,分别是DataFrame类型和Series类型。函数build_tree实现了id3算法,返回构建好的决策树。函数classify用于对单个样本进行分类,函数predict用于对整个数据集进行分类。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值