ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

机器学习复习Day6——决策树

机器学习复习Day6——决策树 ---type: notetitle: 决策树编程作业date: 2026-08-27description: C2W4 从零造一棵决策树认蘑菇熵量有多乱、分裂掰两拨、信息增益切前熵−切后加权熵、选增益最大特征。坑0log₂(0) 要 else 兜底np.log2(0)→-inf→nanget_best_split 占位数不能撞真实下标。---# 2026-08-27 学习笔记## 笔记区学的时候随手记### 核心观点**造一棵决策树让它自己学会认蘑菇。** 数据10 朵蘑菇、3 个特征棕色菌盖 / 细长菌柄 / 独生标签是**可食(1) / 有毒(0)**。这棵树的活儿就是**每次问一个问题把蘑菇切得更干净切到分不动为止。**造树不靠背靠 4 块积木作业就是补这 4 个函数| 积木 | 干什么 | 人话 || ----------------------------------- | -------------------- | ---------------------- || 熵 compute_entropy | 量这一拨有多乱 | 一团糊 vs 分得清 || 分裂 split_dataset | 按某特征掰成左右两拨 | 一个问题把蘑菇分开 || 信息增益 compute_information_gain | 这一刀划不划算 | 切完比切前干净多少 || 选最佳 get_best_split | 挑增益最大的特征 | 试遍问题挑最能分开的 |### 关键方法/流程- **熵**全一种 0一半一半 1。公式 -p1·log₂(p1) - (1-p1)·log₂(1-p1)p1 可食比例。- **信息增益** 分裂前熵 − 分裂后两拨加权熵。**越大 混乱减少越多 越该往下分。**- **加权**两拨大小可能不同要按占比加权不能直接平均熵。### 实战记录**① 熵里 0·log₂(0)0 要 else 兜底** 0log₂(0)0 是人为约定。但计算机里 np.log2(0) 返回 -inf0 × -inf nan所以 p10 或 p11 时公式会算出 nan 而不是 0。因此必须写 else: entropy 0 手动定死否则过不了测试。**② best_feature-1 占位不撞真实下标** 在 get_best_split 中用 -1 做占位因为 -1 不是任何真实特征下标本数据集下标是 0、1、2能安全表示还没选到。若用 0 当初始值0 本身是合法特征下标一旦循环没找到更大增益会误返回特征 0。关键是占位数别撞上真实下标——-1、3、4、5 都可以**2 不行**2 是独生特征的下标。## 代码逐段展开### Ex1 compute_entropy(y) — 算一拨的熵pythondef compute_entropy(y):entropy 0.if len(y) ! 0: # 空节点返回 0p1 len(y[y 1]) / len(y) # 可食比例if p1 ! 0 and p1 ! 1:entropy -p1 * np.log2(p1) - (1-p1) * np.log2(1-p1)else: # p10/1 → 0log₂(0) 约定entropy 0.return entropy- p1 len(y[y 1]) / len(y)数可食的 ÷ 总数 比例。- p1 是 0 或 1 时 np.log2 会算出 -inf0×-inf nan必须 else 兜底给 0。- 根节点 5 可食 5 有毒 → p10.5 → 熵 1.0最乱测试预期就是 1.0。### Ex2 split_dataset(X, node_indices, feature) — 按特征掰两拨pythondef split_dataset(X, node_indices, feature):left_indices []right_indices []for i in node_indices: # 逐个样本if X[i][feature] 1: # 特征1 左left_indices.append(i)else: # 特征0 右right_indices.append(i)return left_indices, right_indices- 只记**下标**不搬数据。按棕色菌盖(feature0)分根节点左 [0,1,2,3,4,7,9]右 [5,6,8]。### Ex3 compute_information_gain(...) — 这刀划不划算pythondef compute_information_gain(X, y, node_indices, feature):left_indices, right_indices split_dataset(X, node_indices, feature)X_node, y_node X[node_indices], y[node_indices]X_left, y_left X[left_indices], y[left_indices]X_right, y_right X[right_indices], y[right_indices]information_gain 0node_entropy compute_entropy(y_node) # 分裂前多乱left_entropy compute_entropy(y_left) # 左拨right_entropy compute_entropy(y_right) # 右拨w_left len(X_left) / len(X_node) # 左占比w_right len(X_right) / len(X_node) # 右占比weighted_entropy w_left * left_entropy w_right * right_entropyinformation_gain node_entropy - weighted_entropyreturn information_gain- 分裂用的是**你自己写的 Ex2**熵用**你自己写的 Ex1**——积木互相拼。- 两拨大小不一样 → 按占比加权不能直接平均。- 预期棕色 0.0349、细长 0.1245、独生 0.2781 → **独生收益最大**。### Ex4 get_best_split(...) — 挑增益最大的特征pythondef get_best_split(X, y, node_indices):num_features X.shape[1]best_feature -1max_info_gain 0for feature in range(num_features): # 试遍每个特征info_gain compute_information_gain(X, y, node_indices, feature)if info_gain max_info_gain:max_info_gain info_gainbest_feature featurereturn best_feature- best_feature -1**占位**不撞真实下标安全表示还没选到。- 循环里 if info_gain max_info_gain找到更大的就换最后留最大的。- 根节点独生(2) 增益 0.2781 最大 → 第一次分裂就选独生。## 线索区学完后合上材料自问自答 先看问题 → 自己回答 → 对照。答不上来的就是没学透。**Q: 熵最大是啥时候为什么**A: p10.5一半一半时熵1 最大。最乱就是两种各占一半猜哪边都没把握全是一种则熵0一点悬念没有。**Q: 信息增益越大说明什么**A: 这一刀把混乱削减得越多越值得在这里往下分。本质 分裂前熵 − 分裂后加权熵。**Q: 占位数为什么不能用 0 或 2**A: 0、2 都是真实特征下标。占位数若撞真实下标循环里一直没找到更大增益时会把还没选到误当成选到了那个特征。用 -1或 3、4、5才安全。**Q: 信息增益里为什么按人数加权而不是两个熵直接平均**A: 左拨右拨大小可能不一样。直接平均把 10 人和 1 人当等重不公平。按占比加权才反映数据多的那边说了算。## 总结50 字以内C2W4 决策树 从零造树熵量多乱、分裂掰两拨、信息增益切前熵−切后加权熵、选增益最大特征。坑0log₂(0) 要 else 兜底、占位数不撞真实下标。---## 复习卡片| 概念 | 一句话 | 我的场景 || -------- | ---------------------------------- | --------------------------- || 熵 | 量这一拨多乱全一种0、一半一半1 | 判断该不该继续切 || 信息增益 | 切前熵 − 切后加权熵 | 越大越该往下分 || 加权熵 | 按占比加权不直接平均 | 两拨人数不一样时 || 占位数 | -1/3/4/5 行0、2 不行 | get_best_split 的还没选到 || 0log₂(0) | 数学约定0机器算 nan | np.log2(0) 要 else 兜底 |
返回列表