3、信息增益与决策树:信息增益的概念、ID3算法原理、基于信息增益的特征选择

3.1 信息增益到底是个啥?

说实话,我刚入行做数据分析那会儿,第一次看到「信息增益」这四个字,脑子里蹦出来的想法是——这玩意儿是不是跟信息论里的「熵」有关系?

没错,你猜对了。信息增益的核心,就是看一个特征能帮我们把数据「理得多清楚」。

我习惯用一个例子来理解:假设你有一堆水果,有苹果、香蕉、橘子。现在让你闭着眼睛摸一个,猜它是啥。你猜中的概率很低,因为三种水果混在一起,很「混乱」。这个混乱程度,在信息论里就叫「熵」。

但如果我告诉你「这个水果是红色的」,你的猜测范围一下子就缩小了。红色水果可能是苹果,也可能是某种红香蕉(虽然少见)。信息增益,就是衡量「红色」这个特征,到底帮我们减少了多少混乱。

核心公式(理解即可):

信息增益 = 原始熵 - 条件熵

说白了,就是「知道这个特征后,不确定性减少了多少」。

3.2 ID3算法原理——我当年手算过的算法

ID3算法,全称是Iterative Dichotomiser 3。名字挺唬人,其实逻辑很简单:每次选一个信息增益最大的特征来分裂数据。

我记得刚学这个算法时,导师让我们手算一个天气数据集。那会儿没有Python,没有sklearn,纯靠笔算。算完一遍,整个算法的直觉就刻在脑子里了。

ID3的核心步骤:

  1. 计算当前数据集的熵
  2. 对每个特征,计算按该特征分裂后的条件熵
  3. 用原始熵减去条件熵,得到每个特征的信息增益
  4. 选信息增益最大的特征作为当前节点
  5. 对每个分支递归执行上述步骤
  6. 直到所有样本属于同一类,或没有特征可用

我的经验:ID3有个明显的毛病——它偏爱取值多的特征。比如「用户ID」这个特征,每个用户一个值,信息增益肯定最大。但用它分裂,决策树就变成了一本花名册,毫无泛化能力。

我曾经在一个用户画像项目里踩过这个坑,后来改用C4.5(用信息增益比)才解决问题。

3.3 基于信息增益的特征选择——实战中的用法

在实际项目中,我很少直接用ID3建树。但信息增益这个指标,在特征选择阶段特别好用。

你想想看,几十个特征摆在你面前,哪些有用哪些没用?信息增益可以帮你快速排序。

我的操作流程:

  • 先对每个特征计算信息增益
  • 按信息增益从大到小排序
  • 设定一个阈值(比如信息增益小于0.01的扔掉)
  • 保留Top-K个特征

嗯,这里要注意:信息增益对连续型特征不友好。我一般会先做离散化,或者直接用信息增益比的变体。

避坑指南:我曾经在一个风控模型里,用信息增益选了Top10特征。结果模型上线后效果很差。后来发现,有两个特征的信息增益都很高,但它们之间相关性极强(几乎共线)。信息增益不考虑特征之间的冗余,所以最好配合相关性分析一起用。

3.4 知识体系框架图

下面这张图,是我自己梳理的信息增益与决策树的核心逻辑。你看一遍,基本就能串起来了。

信息增益与决策树知识体系 信息熵(不确定性) 信息增益 = 熵 - 条件熵 ID3算法:每次选信息增益最大的特征分裂 优点 易于理解、可解释性强 缺点 偏爱取值多的特征 应用 特征选择、分类建模 改进:C4.5(信息增益比)

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