本文來自「大千AI助手」技術實戰系列,專注用真話講技術,拒絕過度包裝。
ID3(Iterative Dichotomiser 3) 是機器學習史上的里程碑算法,由Ross Quinlan于1986年提出。它首次將信息論引入決策樹構建,奠定了現代決策樹的理論基礎。本文將深入剖析其數學本質與實現細節。
往期文章推薦:
- 20.用Mermaid代碼畫ER圖:AI時代的數據建模利器
- 19.ER圖:數據庫設計的可視化語言 - 搞懂數據關系的基石
- 18.決策樹:被低估的規則引擎,80%可解釋性需求的首選方案
- 17.實戰指南:用DataHub管理Hive元數據
- 16.一鍵規范代碼:pre-commit自動化檢查工具實戰指南
- 15.如何數據的永久保存?將信息以加密電磁波形式發射至太空實現永久保存的可行性說明
- 14.NLP已死?大模型時代誰在悄悄重建「語言巴別塔」
- 13.撕掉時序圖復雜度:Mermaid可視化極簡實戰指南
- 12.動手實踐:LangChain流圖可視化全解析
- 11.LangChain LCEL:三行代碼構建AI工作流的秘密
- 10.LangChain執行引擎揭秘:RunnableConfig配置全解析
- 9.避坑指南:Windows下pygraphviz安裝全攻略
- 8.Python3安裝MySQL-python踩坑實錄:從報錯到完美解決的實戰指南
- 7.Git可視化革命:3分鐘學會用Mermaid+AI畫專業分支圖
- 6.vscode常用快捷命令和插件
- 5.AI制圖新紀元:3分鐘用Mermaid畫出專業類圖
- 4.3分鐘搞定數據可視化:Mermaid餅圖終極指南
- 3.5分鐘玩轉Swagger UI:Docker部署+靜態化實戰
- 2.記錄下blog的成長過程
- 1.再說一說LangChain Runnable接口
一、核心思想:用信息增益量化特征價值
核心問題:如何選擇最優劃分特征?
ID3的答案:選擇能使信息增益最大化的特征
信息熵(Entropy):混亂度的度量
定義系統 S S S中樣本類別的混亂程度:
E n t r o p y ( S ) = ? ∑ i = 1 c p i log ? 2 p i Entropy(S) = -\sum_{i=1}^{c} p_i \log_2 p_i Entropy(S)=?i=1∑c?pi?log2?pi?
- c c c:類別總數(如二分類時c=2)
- p i p_i pi?:類別 i i i在 S S S中的比例
熵值解讀:
- 熵=0:所有樣本屬于同一類(完全純凈)
- 熵=1(二分類時):兩類樣本各占50%(最混亂)
示例:硬幣正反面概率均為0.5時, E n t r o p y = ? ( 0.5 log ? 2 0.5 + 0.5 log ? 2 0.5 ) = 1 Entropy = - (0.5\log_20.5 + 0.5\log_20.5) = 1 Entropy=?(0.5log2?0.5+0.5log2?0.5)=1
信息增益(Information Gain)
定義特征 A A A對數據集 S S S的劃分效果:
G a i n ( S , A ) = E n t r o p y ( S ) ? ∑ v ∈ V a l u e s ( A ) ∣ S v ∣ ∣ S ∣ E n t r o p y ( S v ) Gain(S, A) = Entropy(S) - \sum_{v \in Values(A)} \frac{|S_v|}{|S|} Entropy(S_v) Gain(S,A)=Entropy(S)?v∈Values(A)∑?∣S∣∣Sv?∣?Entropy(Sv?)
- V a l u e s ( A ) Values(A) Values(A):特征 A A A的取值集合(如“天氣”的特征值={晴,雨,陰})
- S v S_v Sv?: A A A取值為 v v v的子集
決策規則:選擇使 G a i n ( S , A ) Gain(S, A) Gain(S,A)最大的特征作為當前節點
二、算法運作機制:步步拆解
輸入與輸出
- 輸入:離散型特征數據集(ID3不支持連續特征)
- 輸出:一棵多叉決策樹(每個分支對應特征的一個取值)
遞歸構建流程
def ID3(S, features):if 所有樣本屬于同一類別C:return 葉節點(類別C)if 特征集為空:return 葉節點(S中最多的類別)# 核心步驟:計算每個特征的信息增益best_feature = argmax_{A ∈ features} [Gain(S, A)]創建節點Node(標注best_feature)# 遍歷最佳特征的每個取值for value in values(best_feature):Sv = S中best_feature=value的子集if Sv為空:添加葉節點(標注S中最多的類別)else:子節點 = ID3(Sv, features - {best_feature}) # 遞歸調用Node添加分支(value → 子節點)return Node
三、實例推演:天氣預報數據集
天氣 | 溫度 | 濕度 | 風力 | 是否打球 |
---|---|---|---|---|
晴 | 高 | 高 | 弱 | 否 |
晴 | 高 | 高 | 強 | 否 |
陰 | 高 | 高 | 弱 | 是 |
雨 | 中 | 高 | 弱 | 是 |
雨 | 低 | 正常 | 弱 | 是 |
步驟1:計算根節點熵值
- 總樣本數:5
- 打球(是):3,不打球(否):2
- E n t r o p y ( S ) = ? ( 3 5 log ? 2 3 5 + 2 5 log ? 2 2 5 ) ≈ 0.971 Entropy(S) = -(\frac{3}{5}\log_2\frac{3}{5} + \frac{2}{5}\log_2\frac{2}{5}) ≈ 0.971 Entropy(S)=?(53?log2?53?+52?log2?52?)≈0.971
步驟2:計算各特征信息增益
以“天氣”為例:
- 晴:2個樣本 → 全部“否” → E n t r o p y ( S 晴 ) = 0 Entropy(S_{晴}) = 0 Entropy(S晴?)=0
- 陰:1個樣本 → 全部“是” → E n t r o p y ( S 陰 ) = 0 Entropy(S_{陰}) = 0 Entropy(S陰?)=0
- 雨:2個樣本 → 全部“是” → E n t r o p y ( S 雨 ) = 0 Entropy(S_{雨}) = 0 Entropy(S雨?)=0
- G a i n ( S , 天氣 ) = 0.971 ? [ 2 5 × 0 + 1 5 × 0 + 2 5 × 0 ] = 0.971 Gain(S, 天氣) = 0.971 - [\frac{2}{5}×0 + \frac{1}{5}×0 + \frac{2}{5}×0] = 0.971 Gain(S,天氣)=0.971?[52?×0+51?×0+52?×0]=0.971
同理計算其他特征:
- G a i n ( S , 溫度 ) ≈ 0.571 Gain(S, 溫度) ≈ 0.571 Gain(S,溫度)≈0.571
- G a i n ( S , 濕度 ) ≈ 0.971 Gain(S, 濕度) ≈ 0.971 Gain(S,濕度)≈0.971
- G a i n ( S , 風力 ) ≈ 0.020 Gain(S, 風力) ≈ 0.020 Gain(S,風力)≈0.020
選擇“天氣”或“濕度”作為根節點(增益均為0.971)
四、ID3的局限性:算法缺陷深度分析
-
多值特征偏好問題
- 極端案例:若用“ID編號”作為特征
- 每個樣本獨占一個分支 → E n t r o p y ( S v ) = 0 Entropy(S_v)=0 Entropy(Sv?)=0
- G a i n ( S , I D ) = E n t r o p y ( S ) Gain(S, ID)=Entropy(S) Gain(S,ID)=Entropy(S)(增益最大)
→ 導致毫無泛化能力的過擬合樹
-
連續特征處理缺失
無法直接處理如“溫度=25°C”的連續值,需先離散化 -
缺失值敏感
未定義特征缺失時的處理機制 -
剪枝功能缺失
原始ID3不提供防止過擬合的剪枝策略
重要結論:這些缺陷直接催生了改進算法C4.5(引入信息增益率和剪枝)
五、Python實現核心代碼
import numpy as np
from collections import Counterdef entropy(y):"""計算信息熵"""hist = np.bincount(y)ps = hist / len(y)return -np.sum([p * np.log2(p) for p in ps if p > 0])def information_gain(X, y, feature_idx):"""計算指定特征的信息增益"""parent_entropy = entropy(y)# 按特征取值劃分數據集unique_vals = np.unique(X[:, feature_idx])child_entropy = 0for val in unique_vals:mask = X[:, feature_idx] == valchild_y = y[mask]weight = len(child_y) / len(y)child_entropy += weight * entropy(child_y)return parent_entropy - child_entropyclass ID3Node:def __init__(self, feature=None, children=None, label=None):self.feature = feature # 劃分特征索引self.children = children # 字典:{特征值: 子節點}self.label = label # 葉節點的類別標簽def id3(X, y, features):# 終止條件1:所有樣本同類別if len(np.unique(y)) == 1:return ID3Node(label=y[0])# 終止條件2:無可用特征if len(features) == 0:majority_label = Counter(y).most_common(1)[0][0]return ID3Node(label=majority_label)# 選擇最佳劃分特征gains = [information_gain(X, y, feat) for feat in features]best_idx = np.argmax(gains)best_feat = features[best_idx]# 創建新節點node = ID3Node(feature=best_feat, children={})# 遞歸構建子樹remaining_feats = [f for f in features if f != best_feat]for val in np.unique(X[:, best_feat]):mask = X[:, best_feat] == valX_sub, y_sub = X[mask], y[mask]if len(X_sub) == 0: # 子集為空majority_label = Counter(y).most_common(1)[0][0]node.children[val] = ID3Node(label=majority_label)else:node.children[val] = id3(X_sub, y_sub, remaining_feats)return node
六、歷史意義與現代應用
劃時代貢獻:
- 首次將信息論引入機器學習特征選擇
- 奠定決策樹遞歸分割的框架范式
- 啟發后續C4.5/CART等里程碑算法
現代應用場景:
- 醫學診斷系統(癥狀→疾病路徑清晰可解釋)
- 金融反欺詐規則提取(符合監管透明度要求)
- 工業故障樹分析(物理意義明確的決策邏輯)
本文由「大千AI助手」原創發布,專注用真話講AI,回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我,一起撕掉過度包裝,學習真實的AI技術!