3、信息增益与决策树:信息增益的概念、ID3算法原理、基于信息增益的特征选择
3.1 信息增益到底是个啥?
说实话,我刚入行做数据分析那会儿,第一次看到「信息增益」这四个字,脑子里蹦出来的想法是——这玩意儿是不是跟信息论里的「熵」有关系?
没错,你猜对了。信息增益的核心,就是看一个特征能帮我们把数据「理得多清楚」。
我习惯用一个例子来理解:假设你有一堆水果,有苹果、香蕉、橘子。现在让你闭着眼睛摸一个,猜它是啥。你猜中的概率很低,因为三种水果混在一起,很「混乱」。这个混乱程度,在信息论里就叫「熵」。
但如果我告诉你「这个水果是红色的」,你的猜测范围一下子就缩小了。红色水果可能是苹果,也可能是某种红香蕉(虽然少见)。信息增益,就是衡量「红色」这个特征,到底帮我们减少了多少混乱。
核心公式(理解即可):
信息增益 = 原始熵 - 条件熵
说白了,就是「知道这个特征后,不确定性减少了多少」。
3.2 ID3算法原理——我当年手算过的算法
ID3算法,全称是Iterative Dichotomiser 3。名字挺唬人,其实逻辑很简单:每次选一个信息增益最大的特征来分裂数据。
我记得刚学这个算法时,导师让我们手算一个天气数据集。那会儿没有Python,没有sklearn,纯靠笔算。算完一遍,整个算法的直觉就刻在脑子里了。
ID3的核心步骤:
- 计算当前数据集的熵
- 对每个特征,计算按该特征分裂后的条件熵
- 用原始熵减去条件熵,得到每个特征的信息增益
- 选信息增益最大的特征作为当前节点
- 对每个分支递归执行上述步骤
- 直到所有样本属于同一类,或没有特征可用
我的经验:ID3有个明显的毛病——它偏爱取值多的特征。比如「用户ID」这个特征,每个用户一个值,信息增益肯定最大。但用它分裂,决策树就变成了一本花名册,毫无泛化能力。
我曾经在一个用户画像项目里踩过这个坑,后来改用C4.5(用信息增益比)才解决问题。
3.3 基于信息增益的特征选择——实战中的用法
在实际项目中,我很少直接用ID3建树。但信息增益这个指标,在特征选择阶段特别好用。
你想想看,几十个特征摆在你面前,哪些有用哪些没用?信息增益可以帮你快速排序。
我的操作流程:
- 先对每个特征计算信息增益
- 按信息增益从大到小排序
- 设定一个阈值(比如信息增益小于0.01的扔掉)
- 保留Top-K个特征
嗯,这里要注意:信息增益对连续型特征不友好。我一般会先做离散化,或者直接用信息增益比的变体。
避坑指南:我曾经在一个风控模型里,用信息增益选了Top10特征。结果模型上线后效果很差。后来发现,有两个特征的信息增益都很高,但它们之间相关性极强(几乎共线)。信息增益不考虑特征之间的冗余,所以最好配合相关性分析一起用。
3.4 知识体系框架图
下面这张图,是我自己梳理的信息增益与决策树的核心逻辑。你看一遍,基本就能串起来了。
3.5 代码示例:手算信息增益
下面这个Python代码,是我当年手算信息增益的「数字化版本」。你跑一遍,就能直观感受到每个特征的价值。
import numpy as np
import pandas as pd
from math import log2
def entropy(y):
"""计算熵"""
classes = np.unique(y)
ent = 0
for c in classes:
p = np.sum(y == c) / len(y)
if p > 0:
ent -= p * log2(p)
return ent
def information_gain(X, y, feature_idx):
"""计算某个特征的信息增益"""
# 原始熵
base_entropy = entropy(y)
# 按特征值分组
feature_values = np.unique(X[:, feature_idx])
cond_entropy = 0
for val in feature_values:
subset_y = y[X[:, feature_idx] == val]
weight = len(subset_y) / len(y)
cond_entropy += weight * entropy(subset_y)
return base_entropy - cond_entropy
# 示例数据:天气数据集
data = {
'天气': ['晴', '晴', '阴', '雨', '雨', '雨', '阴', '晴', '晴', '雨', '晴', '阴', '阴', '雨'],
'温度': ['高', '高', '高', '中', '低', '低', '低', '中', '低', '中', '中', '中', '高', '中'],
'湿度': ['高', '高', '高', '高', '正常', '正常', '正常', '高', '正常', '正常', '正常', '高', '正常', '高'],
'风': ['弱', '强', '弱', '弱', '弱', '强', '强', '弱', '弱', '弱', '强', '强', '弱', '强'],
'打球': ['否', '否', '是', '是', '是', '否', '是', '否', '是', '是', '是', '是', '是', '否']
}
df = pd.DataFrame(data)
X = df[['天气', '温度', '湿度', '风']].values
y = df['打球'].values
print("各特征的信息增益:")
for i, col in enumerate(['天气', '温度', '湿度', '风']):
ig = information_gain(X, y, i)
print(f"{col}: {ig:.4f}")
输出结果:
天气: 0.2467
温度: 0.0292
湿度: 0.1518
风: 0.0481
你看,天气的信息增益最大,所以ID3会先拿天气来分裂。这个结果跟我们的直觉一致——天气好不好,直接决定打不打球。
3.6 我的实战建议
信息增益这个指标,我到现在还在用。尤其是在做特征工程时,它是我快速筛选特征的「第一道筛子」。
但我建议你记住三点:
- 信息增益高 ≠ 特征一定好——还要看特征本身的业务含义
- 信息增益低 ≠ 特征一定没用——可能跟其他特征组合后效果很好
- 别只看信息增益——配合方差分析、卡方检验一起用,效果更稳
我个人习惯是:先用信息增益粗筛一遍,把明显没用的特征扔掉。然后用业务经验+模型验证做第二轮筛选。这样既快又稳,不容易漏掉重要特征。
好了,信息增益和ID3的核心内容就这些。你把这个逻辑吃透了,后面学C4.5、CART、随机森林都会轻松很多。
公众号:蓝海资料掘金营,微信deep3321