关于熵的一些概念及其计算

最近在看 verl 的源码学习强化学习的相关实现,看到了一个计算熵的函数,感觉挺有意思:

python 复制代码
def entropy_from_logits(logits: torch.Tensor):
    """Calculate entropy from logits."""
    pd = torch.nn.functional.softmax(logits, dim=-1)
    entropy = torch.logsumexp(logits, dim=-1) - torch.sum(pd * logits, dim=-1)
    return entropy

在人工智能深度学习领域,模型训练有很多数学的理论做支撑,但从数学公式转化为具体的代码实现,往往不能直接按原公式的计算逻辑编写代码进行计算,因为数学是比较理想的,而真正要把数据放到计算机中进行处理,则需要考虑很多问题,比如计算是否稳定、数值会不会溢出等等,因此通常需要对原公式做一些转换,熵的计算就是如此,当然还有很多其他的例子,比如 softmax 的计算等等。本文就借此机会聊聊与熵相关的一些内容。

熵(Entropy)是信息论中的一个核心概念,最早由克劳德·香农(Claude Shannon)在1948年提出。它用来量化一个概率分布的不确定性或"混乱程度"。下面从直观含义、数学定义和实际作用三个方面来解释。


一、熵的直观含义

想象你面对一个随机事件,比如:

  • 抛一枚公平硬币 :正面或反面各50%。结果很难预测 → 不确定性高熵大
  • 抛一枚作弊硬币 :99% 是正面。结果几乎可以猜到 → 不确定性低熵小
  • 如果某个事件必然发生 (概率为1),那完全没有不确定性 → 熵为0

所以:熵越大,表示结果越不可预测;熵越小,表示结果越确定。


二、数学定义

对于一个离散随机变量 X X X,其可能取值为 { x 1 , x 2 , . . . , x n } \{x_1, x_2, ..., x_n\} {x1,x2,...,xn},对应的概率为 p i = P ( X = x i ) p_i = P(X = x_i) pi=P(X=xi),则香农熵定义为:

H ( X ) = − ∑ i = 1 n p i log ⁡ p i H(X) = -\sum_{i=1}^n p_i \log p_i H(X)=−i=1∑npilogpi

  • 单位:若对数以 2 为底,单位是 比特(bit) ;以自然对数(e)为底,单位是 纳特(nat)
  • 约定:当 p i = 0 p_i = 0 pi=0 时,定义 0 log ⁡ 0 = 0 0 \log 0 = 0 0log0=0(因为极限为0)。

三、熵的作用与应用场景

1. 衡量模型的置信度(机器学习)

  • 在分类任务中,模型输出一个概率分布(如 softmax 后的结果)。
  • 如果熵很低(接近0):模型对某个类别非常确信(如 [0.99, 0.01])。
  • 如果熵很高:模型犹豫不决(如 [0.33, 0.33, 0.34])。
  • ✅ 应用:主动学习(Active Learning)中,选择熵高的样本让人工标注,因为模型最"困惑"。

2. 强化学习中的探索(Exploration)

  • 在策略梯度方法(如 PPO、A3C)中,常在损失函数中加入熵正则项

L = 原始损失 + β ⋅ H ( π ) \mathcal{L} = \text{原始损失} + \beta \cdot H(\pi) L=原始损失+β⋅H(π)

  • 目的:鼓励策略保持一定随机性,避免过早收敛到次优解(即"鼓励探索")。
  • 如果策略熵太低,说明 agent 总是选同一个动作,可能陷入局部最优。

3. 数据压缩(信息论)

  • 熵代表了编码该随机变量所需的最小平均比特数
  • 例如:公平硬币的熵是 1 bit,意味着每个结果至少需要 1 bit 来编码。
  • 这是 ZIP、JPEG 等压缩算法的理论基础。

4. 特征选择与决策树(如 ID3、C4.5)

  • 决策树使用信息增益(Information Gain)来选择分裂特征:

IG = H ( 父节点 ) − ∑ ∣ 子集 ∣ ∣ 总 ∣ H ( 子节点 ) \text{IG} = H(\text{父节点}) - \sum \frac{|子集|}{|总|} H(\text{子节点}) IG=H(父节点)−∑∣总∣∣子集∣H(子节点)

  • 信息增益越大,说明该特征能最大程度减少不确定性(降低熵)。

5. 异常检测 / 不确定性估计

  • 高熵的预测可能意味着输入是异常样本分布外数据(OOD)
  • 可用于安全关键系统(如自动驾驶)中判断"模型是否知道自己不知道"。

四、举个例子 🌰

假设一个三分类问题,模型输出三种概率分布:

情况 概率分布 熵(近似) 含义
A [0.9, 0.05, 0.05] ≈ 0.37 非常确信,低不确定性
B [0.33, 0.33, 0.34] ≈ 1.10 完全犹豫,高不确定性
C [1.0, 0.0, 0.0] = 0.0 完全确定

→ 熵帮助我们量化这种"犹豫程度"


总结

角度 熵的意义
信息论 信息的平均"惊喜度";不确定性度量
机器学习 模型置信度、探索 vs 利用、正则化
工程应用 压缩、加密、异常检测、主动学习

💡 简单记住:熵 = 不确定性 = 混乱程度 = 信息量

越"乱",熵越大;越"确定",熵越小。

熵与信息量

熵(Entropy)和信息量(Information Content)是信息论中紧密相关但不同层次的概念。它们的关系可以用一句话概括:

熵是信息量的期望值(平均信息量)。

下面从定义、直观理解到数学关系一步步解释。


一、信息量(自信息,Self-Information)

定义

对于一个具体事件 ( x ) (x) (x),其发生概率为 p ( x ) p(x) p(x),它的信息量(也叫"自信息")定义为:

I ( x ) = − log ⁡ p ( x ) I(x) = -\log p(x) I(x)=−logp(x)

直观理解

  • 越不可能发生的事件,一旦发生,带来的信息量越大
    • 例如:"太阳从东边升起"(概率≈1)→ 信息量 ≈ 0(不惊讶)。
    • "明天下陨石雨"(概率≈0.0001)→ 信息量很大(非常惊讶!)。
  • 单位:比特(bit,以2为底)、纳特(nat,以e为底)。

信息量描述的是单个事件的"惊讶程度"或"信息价值"。


二、熵(Entropy)

定义

如前一节所述,熵是量化一个概率分布的不确定性或"混乱程度",而这种不确定性也衡量了整个概率分布的平均信息量,即信息量的数学期望:

H ( X ) = E x ∼ P [ I ( x ) ] = E [ − log ⁡ p ( x ) ] = − ∑ x p ( x ) log ⁡ p ( x ) H(X) = \mathbb{E}_{x \sim P}[I(x)] = \mathbb{E}[-\log p(x)] = -\sum_x p(x) \log p(x) H(X)=Ex∼P[I(x)]=E[−logp(x)]=−x∑p(x)logp(x)

直观理解

  • 熵衡量的是:在知道结果之前,你预期会获得多少信息
  • 它不是针对某一次结果,而是对整个随机变量 X 的不确定性的度量。
  • 比如抛硬币:
    • 公平硬币:每次结果都可能带来 1 bit 信息,平均就是 1 bit → 熵 = 1。
    • 作弊硬币(99% 正面):大多数时候结果无聊(信息少),偶尔反面很惊喜(信息多),但平均下来信息量较低 → 熵 < 1。

熵 = 平均信息量 = 预期惊喜程度 = 不确定性大小


三、类比帮助理解

概念 类比 特点
信息量 某一天的天气是否让你惊讶 针对单次事件
这个城市天气的"不可预测程度" 针对整个分布

就像:

  • "今天中了彩票" → 信息量极大(因为概率极低)。
  • 但"买彩票能中奖"这件事的熵其实很低(因为中奖概率太小,几乎不会发生,所以平均信息量不高)。

四、数学关系总结

符号 含义 公式
I ( x ) I(x) I(x) 事件 x x x 的信息量 I ( x ) = − log ⁡ p ( x ) I(x) = -\log p(x) I(x)=−logp(x)
H ( X ) H(X) H(X) 随机变量 X X X 的熵 H ( X ) = E [ I ( x ) ] = − ∑ p ( x ) log ⁡ p ( x ) H(X) = \mathbb{E}[I(x)] = -\sum p(x) \log p(x) H(X)=E[I(x)]=−∑p(x)logp(x)

👉 所以:熵是信息量在概率分布下的加权平均


五、实际例子

假设一个四面骰子,有以下两种情况:

情况1:公平骰子

  • 每面概率 = 0.25
  • 每次掷出任意一面的信息量: I = − log ⁡ 2 ( 0.25 ) = 2 I = -\log_2(0.25) = 2 I=−log2(0.25)=2 bits
  • 熵: H = 0.25 × 2 + 0.25 × 2 + 0.25 × 2 + 0.25 × 2 = 2 bits H = 0.25 \times 2 + 0.25 \times 2 + 0.25 \times 2 + 0.25 \times 2 = 2\text{ bits} H=0.25×2+0.25×2+0.25×2+0.25×2=2 bits

✅ 每次结果都同样"惊喜",平均信息量 = 2 bits。

情况2:作弊骰子

  • P(1)=0.5, P(2)=0.3, P(3)=0.15, P(4)=0.05
  • 各事件信息量:
    • I(1) = -log₂(0.5) = 1 bit
    • I(2) = -log₂(0.3) ≈ 1.74 bits
    • I(3) ≈ 2.74 bits
    • I(4) ≈ 4.32 bits
  • 熵: H = 0.5 × 1 + 0.3 × 1.74 + 0.15 × 2.74 + 0.05 × 4.32 ≈ 1.65 bits H = 0.5×1 + 0.3×1.74 + 0.15×2.74 + 0.05×4.32 ≈ 1.65 \text{ bits} H=0.5×1+0.3×1.74+0.15×2.74+0.05×4.32≈1.65 bits

✅ 虽然"掷出4"信息量很大,但它很少发生,所以平均信息量(熵)反而比公平骰子低


六、延伸:为什么叫"信息量"?

香农认为:

信息是用来消除不确定性的。

  • 如果一件事本来就很确定(p≈1),告诉你结果并不会减少你的不确定性 → 信息量小。
  • 如果一件事非常不确定(p≈0.5 或均匀分布),告诉你结果会大幅减少不确定性 → 信息量大。

就是"在得知结果前,你预期能消除多少不确定性"------也就是平均能获得多少信息。


总结

概念 作用对象 含义 关系
信息量 单个事件 x x x 该事件发生带来的"惊讶程度" I ( x ) = − log ⁡ p ( x ) I(x) = -\log p(x) I(x)=−logp(x)
整个分布 X X X 平均能获得多少信息(不确定性) H ( X ) = E [ I ( x ) ] H(X) = \mathbb{E}[I(x)] H(X)=E[I(x)]

🔑 熵是信息量的期望;信息量是熵的基本构成单元。

熵的计算的代码实现

回到开头的 python 函数 entropy_from_logits,这个函数的作用是从 logits 计算对应的 概率分布的熵(entropy)。下面我们逐步解释其原理和实现细节。


1. 背景知识

  • Logits:在机器学习中,logits 通常指模型最后一层输出的原始值(尚未经过 softmax 归一化)。它们可以看作是未归一化的概率。
  • Softmax:将 logits 转换为概率分布:

p i = e z i ∑ j e z j p_i = \frac{e^{z_i}}{\sum_j e^{z_j}} pi=∑jezjezi

其中 z i z_i zi 是第 i i i 个 logit, p i p_i pi 是对应的概率。

  • 熵(Entropy) :衡量一个概率分布的不确定性。从前面的定义可以看到,对于离散分布 p = ( p 1 , . . . , p n ) p = (p_1, ..., p_n) p=(p1,...,pn),熵定义为:

H ( p ) = − ∑ i p i log ⁡ p i H(p) = -\sum_i p_i \log p_i H(p)=−i∑pilogpi


2. 函数逐行解释

python 复制代码
def entropy_from_logits(logits: torch.Tensor):
    """Calculate entropy from logits."""
  • 输入:logits 是一个 PyTorch 张量,形状通常是 (batch_size, num_classes) 或更高维,但最后一个维度是类别维度。
  • 目标:计算每个样本(沿最后一个维度)对应的概率分布的熵。

第一步:计算概率分布

python 复制代码
    pd = torch.nn.functional.softmax(logits, dim=-1)
  • 使用 softmax 将 logits 转换为概率分布 pd(probability distribution)。
  • dim=-1 表示在最后一个维度上做 softmax,即对每个样本的类别 logits 做归一化。

第二步:计算熵

python 复制代码
    entropy = torch.logsumexp(logits, dim=-1) - torch.sum(pd * logits, dim=-1)

这里用了一个数值稳定避免显式计算 log§ 的技巧。

我们从熵的定义出发:

H ( p ) = − ∑ i p i log ⁡ p i H(p) = -\sum_i p_i \log p_i H(p)=−i∑pilogpi

而由于 p i = e z i ∑ j e z j p_i = \frac{e^{z_i}}{\sum_j e^{z_j}} pi=∑jezjezi,所以:

log ⁡ p i = z i − log ⁡ ( ∑ j e z j ) \log p_i = z_i - \log\left(\sum_j e^{z_j}\right) logpi=zi−log(j∑ezj)

代入熵公式:

H ( p ) = − ∑ i p i ( z i − log ⁡ ∑ j e z j ) = − ∑ i p i z i + log ⁡ ∑ j e z j ⋅ ∑ i p i H(p) = -\sum_i p_i (z_i - \log\sum_j e^{z_j}) = -\sum_i p_i z_i + \log\sum_j e^{z_j} \cdot \sum_i p_i H(p)=−i∑pi(zi−logj∑ezj)=−i∑pizi+logj∑ezj⋅i∑pi

因为 ∑ i p i = 1 \sum_i p_i = 1 ∑ipi=1,所以:

H ( p ) = log ⁡ ( ∑ j e z j ) − ∑ i p i z i H(p) = \log\left(\sum_j e^{z_j}\right) - \sum_i p_i z_i H(p)=log(j∑ezj)−i∑pizi

这正是代码中的表达式!

  • torch.logsumexp(logits, dim=-1) 计算的是 $\log\left(\sum_j e^{z_j}\right)$,数值稳定。
  • torch.sum(pd * logits, dim=-1) 计算的是 $\sum_i p_i z_i$
  • 两者相减即为熵。

注意:这里没有显式计算 log(p),避免了在概率接近 0 时 log(0) 的数值问题。


3. 示例

python 复制代码
import torch

logits = torch.tensor([[1.0, 2.0, 3.0]])
entropy = entropy_from_logits(logits)
print(entropy)  # 输出一个标量(张量)

等价于:

python 复制代码
p = torch.softmax(logits, dim=-1)
H = -torch.sum(p * torch.log(p), dim=-1)

但原函数更数值稳定,尤其当 logits 数值较大或较小时。


4. 总结

  • 该函数高效、稳定地从 logits 计算熵。
  • 利用了恒等式:

H = log ⁡ ∑ e z i − ∑ p i z i H = \log\sum e^{z_i} - \sum p_i z_i H=log∑ezi−∑pizi

  • 避免了直接计算 log(softmax(logits)),从而提升数值稳定性。
相关推荐
qzhqbb2 小时前
问题归约知识表示及其搜索技术
人工智能·剪枝
杰瑞不懂代码2 小时前
OFDM 系统端到端仿真详解:信道估计、均衡与性能评估
人工智能·深度学习·matlab·ofdm
Wang201220132 小时前
AI各个领域适用的大模型介绍和适配的算法
人工智能·算法
冰西瓜6002 小时前
隐马尔可夫模型的三大问题(HMM)
人工智能·机器学习
工藤学编程2 小时前
AI Ping 赋能:基于 GLM-4.7(免费!)+ LangChain + Redis 打造智能AI聊天助手
人工智能·redis·langchain
程序员哈基耄2 小时前
AI背景移除器:一键释放图像创造力
人工智能
fie88892 小时前
基于 Matlab 实现的 语音分帧、端点检测、音高提取与DTW算法 结合的歌曲识别系统
人工智能·matlab
fruge2 小时前
解锁AI开发新效率:AI Ping平台与免费明星模型MiniMax-M2.1、GLM-4.7深度解析
人工智能
natide2 小时前
词汇/表达差异-7-Alias覆盖率
人工智能·pytorch·python·深度学习·自然语言处理