尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
信息熵、交叉熵与KL散度:机器学习损失函数的信息论本质
1. 从天气预报说起信息量凭什么用对数来度量先讲一件我去年做模型时遇到的怪事。当时在调一个多分类的模型验证集准确率卡在 87% 上不去。我同事看了一眼损失曲线说你把标签做平滑试试。我那时候只把交叉熵当个公式用哪里知道标签平滑跟信息熵有什么关系。后来把信息论这套概念从头啃了一遍才发现自己以前对损失函数的理解完全停留在求导方便这个层面。要讲清楚交叉熵和 KL 散度最好先回到最原始的问题一条消息的信息量到底怎么计算想象你早上打开天气 App看到今天太阳照常升起和今天有台风这两条通知。第一条你点都不会点第二条你会立刻转发给家人。为什么因为太阳升起这件事几乎必然发生它没有消除任何不确定性而台风概率很小一旦发生你的认知就被大幅刷新。这就是信息量的直觉定义信息量度量的是一个事件发生所带来的惊讶程度或不确定性消除量它与事件发生的概率成反比。概率越低的事件一旦发生信息量越大。那为什么偏偏要用对数函数而不是直接用 1/p这里有一个非常优雅的理由可加性。假设两个独立事件同时发生联合概率是 p(x,y)p(x)p(y)。我们对同时收到两条消息的信息量直觉是两条消息信息量之和而 log 函数恰好能把乘法变成加法log(1/(p(x)p(y))) log(1/p(x)) log(1/p(y))这个性质是线性度量下唯一的选择。所以信息量定义为I(x) -log p(x)底数取 2 时单位是比特bit取 e 时单位是纳特nat取 10 时单位是哈特莱hartley。机器学习里因为要和 softmax 里的 exp 搭配推导中常用自然对数但本质上换底只是乘一个常数不影响任何结论。我第一次真正理解这条公式不是通过推导而是通过一个极端例子设 p1.0信息量是 0设 p0.0001信息量大约是 9.21 纳特约 13.3 比特。这个对比非常直观——必然发生的事件不带信息极不可能发生的事件信息量爆炸。而信息熵就是把整个分布里所有可能事件的信息量按概率加权平均。2. 信息熵一个系统的平均惊喜程度2.1 熵的定义和它为什么是不确定性如果信息量是单个事件的性质那么一个随机变量 X 带着一个完整的概率分布 p(x)它的整体信息量该怎么描述把每个事件的信息量做概率加权平均H(X) -Σ p(x) log p(x)这就是信息熵也叫香农熵。我见过太多人把熵理解成混乱程度就结束了这个理解没有错但不够。更准确的说法是熵是在编码理论意义下表达一个分布内部不确定性的下界。如果你要设计一套最优编码来传输来自这个分布的符号平均每个符号最少需要 H(X) 个比特。这是香农第一定理的核心结论也正是熵在工程上最硬核的用途。举一个硬币的例子。一枚均匀硬币p(正)0.5p(反)0.5熵是H -(0.5·log0.5 0.5·log0.5) 1 比特它告诉你每抛一次硬币平均需要 1 个比特来记录结果。这很符合直觉一个二进制事件至少需要一位信息。再看一个极端分布一面硬币永远正面朝上p(正)1p(反)0。熵是 0。因为结果完全确定你不需要任何比特来传递信息。再看一个不均匀分布p(正)0.9p(反)0.1。熵是 -(0.9·log0.9 0.1·log0.1) ≈ 0.469 比特。有意思的地方来了这个分布的平均信息量比 1 比特小说明它内部可预测性高。如果你用霍夫曼编码可以为大概率事件分配 1 位、为小概率事件分配 2 位平均不到 1 位就能传完每个符号。所以熵也经常被解释为不可预测性或系统内部的自由度。均匀分布熵最大确定性分布熵最小。2.2 熵的最大值在哪均匀分布一个经典结论是在所有取值个数相同的离散分布中均匀分布的熵最大。对于取值 k 个的离散变量最大熵是 log k。这个结论在机器学习里有一个非常实际的应用它的反面就是标签平滑的动机。硬标签对应的分布是某个类概率为 1、其余为 0 的 one-hot 分布它的熵是 0。这是一个极端确定性的目标模型被要求输出一个同样极端的分布很容易出现过拟合和校准误差。标签平滑做的事情本质上是把目标分布从熵为 0 的 one-hot 拉向一个熵更大的软分布让模型不要那么自信得过头。我第一次意识到这个联系的场景是这样的当时把标签从 [1,0,0] 换成 [0.9,0.05,0.05] 之后验证集损失在同样的 epoch 数下从 0.82 降到了 0.71准确率也从 87% 涨到 88.6%。那时候我只知道平滑能缓解过拟合但不理解背后的概率意义。后来才明白在信息论视角下这是在调整目标分布本身的熵而不是在调模型参数。2.3 熵为零和熵最大的边界意义沿着熵的定义继续往边界推熵等于 0表示系统完全确定熵等于 log k表示系统完全均匀。真实世界的分布几乎都在这两个极端之间。一个常见误区是熵越小一定越好。在模型训练里验证集上的交叉熵越小越好但这个是相对你给定的目标分布而言的而一个均匀分布的熵是最大的模型如果输出均匀分布预测结果等于瞎猜。所以熵本身无所谓优劣关键看它相对于什么参考系——这就自然引出跨分布的比较工具KL 散度和交叉熵。3. 交叉熵和 KL 散度两套分布之间的距离感3.1 KL 散度用分布 Q 去近似分布 P 时损失了多少信息信息熵刻画的是单个分布的内部不确定性。但现实中我们经常要处理两个分布一个是数据的真实分布 P另一个是模型输出的预测分布 Q。怎么度量这两个分布差多少答案就是KL 散度Kullback-Leibler divergence也叫相对熵D_KL(P || Q) Σ p(x) · log(p(x) / q(x))把它展开能拆成两项D_KL(P || Q) Σ p(x) log p(x) - Σ p(x) log q(x) -H(P) H(P, Q)其中H(P, Q) -Σ p(x) log q(x)就是交叉熵。这个结构特别重要KL 散度 交叉熵 - 信息熵。第一个等式说明KL 散度的含义是用 Q 去描述 P 时额外需要的编码长度——换句话说如果真实分布是 P但你错误地以为它是 Q你的编码方案会比最优方案平均多花 D_KL(P||Q) 个比特。P 本身的最短平均编码长度是 H(P)你用 Q 对应的编码方案去编 P平均编码长度则是交叉熵 H(P,Q)两者的差就是 KL 散度。这也解释了一个重要的性质KL 散度非负而且只有 PQ 时等于 0。它不是凭空定义的距离而是有编码理论底座的额外代价。至于为什么非负可以从 Jensen 不等式的角度理解-log 是凸函数期望的凸函数大于等于凸函数的期望代入以后自然得到非负性。这里不展开证明但结论要记住额外代价只会大于等于 0不会为负。3.2 交叉熵为什么是垃圾的那半截如果你只看最小化交叉熵这个行为它等价于在 P 固定的情况下最小化 KL 散度。为什么因为 KL 散度 交叉熵 - 熵而训练中数据分布 P 是固定的它的熵 H(P) 是常数不随模型参数变化。于是argmin_θ D_KL(P || Q_θ) argmin_θ H(P, Q_θ)也就是说机器学习里的交叉熵损失函数其实是在固定真实分布的前提下最小化 KL 散度。这也是很多人第一次听到分类任务用交叉熵是因为它等价于 KL 散度时的疑惑来源。既然等价为什么不直接用 KL 散度做损失函数因为计算 KL 散度必须先算 H(P)也就是真实分布的信息熵这个量我们根本不知道——我们只知道 P 的样本。而交叉熵只涉及样本上 Q 的负对数似然可以直接通过采样估计不需要显式知道 P。3.3 KL 散度的不对称性一个被忽视的坑KL 散度不是对称的D_KL(P||Q) ≠ D_KL(Q||P)。这一点在实践里影响巨大。D_KL(P||Q) 是用 Q 逼近 P追求的是覆盖 P 的所有高概率区域导出的模型倾向于产生更宽的分布可能包含一些低概率的毛刺。D_KL(Q||P) 是用 P 来评估 Q模型会更倾向于集中在 P 的一个高概率峰值附近可能出现 mode collapse生成的样本种类单一。在生成模型里反向 KL 会导致模型只学到训练分布中的一部分模式这在对抗生成网络的早期版本里是个严重问题。而在蒸馏学习、变分推断中这个不对称性决定了目标函数应该选正向还是反向选错了效果天差地别。4. 机器学习的视线为什么损失函数非交叉熵不可4.1 从极大似然估计推导交叉熵很多人只知道交叉熵配 softmax 好用但不知道为什么好用。其实把它和**极大似然估计MLE**联系起来逻辑链条非常顺滑。假设我们有一个分类模型对每个样本 x输出一个概率分布 Q(y|x) softmax(z)z 是 logits。数据集中的样本来自真实分布 P(y|x)。我们用模型去拟合训练数据的联合概率L(θ) Π_i P(样本 i)取负对数之后-log L(θ) -Σ_i log Q(y_i | x_i)这恰好就是交叉熵损失。所以交叉熵损失就是负对数似然在期望意义上等于 KL 散度加上一个常数。这不是巧合而是信息论和统计估计在同一个框架下的自然汇合。对比一下回归任务回归常用均方误差MSE它对应的假设是误差服从高斯分布MLE 推导后自然得到 MSE。分类任务对应的是类别分布MLE 推导后得到交叉熵。每个损失函数背后都站着一个分布假设想明白这一点选损失函数就不会只靠手感。4.2 为什么不直接用 0-1 损失或 MSE分类任务最简单的损失是预测错多少个0-1 损失。但它的梯度几乎处处为零没法用梯度下降优化。MSE 当分类损失行不行试过的人都知道效果差到离谱。原因可以从熵的角度解释MSE 假设误差是高斯噪声但分类标签是离散的类别分布这个分布假设是错的。另一个原因更直接在梯度上softmax 加 MSE 的梯度在输出接近饱和时非常小模型训练会变得极其缓慢而 softmax 加交叉熵的梯度形式为 (Q - Y)即使输出已经很接近目标梯度幅度也不会消失它自然地把预测分布和真实分布的差异传给上游。这个差异表达式也是我在实践中感受最深的一点交叉熵的梯度不包含 softmax 的导数项这在反向传播的数值稳定性上省了无数麻烦。如果你自己用纯 Python 实现过两层神经网络对比一下两种损失在反向传播时的表达式复杂度就会明白为什么框架里默认组合是CrossEntropyLoss Softmax。4.3 多分类交叉熵的逐样本形式多分类交叉熵在单样本上的定义是L -Σ_k y_k · log p_k其中 y_k 是 one-hot 标签的第 k 位p_k 是模型预测的第 k 类概率。由于 one-hot 向量里只有一个位置是 1这个表达式可以化简成L -log p_c其中 c 是正确类别。这意味着一件事交叉熵损失只关心正确类别的预测概率其他类别的概率不直接参与单样本损失。但其他类别仍然通过 softmax 的分母影响 p_c所以它们间接参与了优化。这个化简常被忽略但它解释了一个实战现象当测试集出现一个模型从未见过的类时交叉熵不会给它任何惩罚渐量而 KL 散度视角下的分布整体相似度会更明显。换句话说交叉熵关注的是正确的那个类有没有高概率而不是整个预测分布像不像真实分布。这也是为什么有些论文会在评估阶段额外计算 KL 散度或 Jensen-Shannon 散度来观察整体的分布匹配度。5. 实操里绕不开的细节数值稳定性、标签平滑与散度方向5.1 log(0) 的雷区和处理手法交叉熵公式里有 log q(x)。如果模型输出的某个类概率是 0计算直接变成 log(0) -∞梯度也会变成 NaN。实践中 softmax 不会输出绝对 0但浮点精度下可能出现极端小的值比如 1e-300此时 log 值很大但还不是 -∞梯度会异常放大。最稳妥的做法是在实现交叉熵时用log-softmax 合并计算。数学上log softmax(z)_k z_k - logsumexp(z)理由很简单logsumexp 本身在数值上很稳定先减掉最大值再求和可以避免 exp(z) 溢出。PyTorch 和 TensorFlow 里的 CrossEntropyLoss 内部做的就是这个合并操作。如果你自己实现模型千万别写成先算 softmax 再算 log再传给损失函数那会平白引入精度损失和数值风险。5.2 标签平滑重新解读给目标分布加一点熵标签平滑的具体做法是把硬标签从 0/1 改成y_c 1 - ε ε/K y_k ε/K, k ≠ c其中 K 是类别数ε 是平滑系数一般取 0.1。从信息论角度平滑后的目标分布熵变大了模型不再被强制输出一个极端集中在单点的分布而是被允许保留一部分不确定性。在实践中标签平滑带来的直接变化是验证集上 top-1 准确率可能微降但测试集上通常能涨一点尤其是类别不平衡或数据集噪声较多的情况。它减少的其实是过拟合——模型对训练集上的极端样本不再做到 100% 自信这相当于给概率空间加了一个软约束。我个人用下来的经验是ε0.1 对 ImageNet 风格的大规模分类有效对小数据集要调得更小比如 0.05 甚至 0.01否则模型会欠拟合。平滑过头时训练损失会明显偏高这不一定是坏事但如果准确率也开始下降就该往回调。5.3 正向 KL 和反向 KL选错方向会踩大坑前面提到 KL 散度不对称。在实践里这直接体现在很多模型的目标函数选型上变分自编码器VAE的损失里有 D_KL(Q(z|x) || P(z))其中 Q 是编码器输出的近似后验P(z) 是先验标准正态分布。这里用的是Q 逼近 P属于反向 KL 的典型形式它会让 Q 尽量落在 P 的支持集内倾向于压缩潜在空间的表达范围。知识蒸馏里常用 D_KL(学生 || 教师) 还是 D_KL(教师 || 学生)效果截然不同。前者鼓励学生分布覆盖教师的分布后者则倾向于让学生专注在教师最确信的区域。如果只是套公式而不注意方向你很可能得到训练损失降了但生成样本多样性极差这类奇怪现象。我去年做某个模拟项目时曾经直接把 KL 项的反向改成正向结果损失数值大幅震荡折腾了一整天才定位到方向问题。KL 散度不是对称的它不是几何距离而是一种有方向的信息代价。5.4 常见直觉误区熵大等于不靠谱最后一个想纠正的误区很多人看到训练时模型输出的预测分布熵变大就觉得模型变笨了。其实要看上下文。在测试阶段预测分布熵大可能意味着模型不确定这是坏事但训练早期熵大往往意味着模型还在探索没有收敛到局部最小值——这时候熵值快速下降反而是正常信号。还有一个更微妙的场景对抗训练或正则化手段有时会主动提高模型预测分布的熵因为这能提升模型在边界样本上的泛化能力。所以看损失曲线时不要只盯交叉熵本身要把交叉熵拆成 熵 H(P) 和 KL 散度两部分来看一个固定的交叉熵下降可能来自真实分布熵的变化也可能来自分布匹配度的变化两者对应的语义完全不同。在我自己看训练日志的习惯里除了记录 loss 之外我还会记录模型输出的平均预测熵。当 loss 变化和熵变化出现背离时比如 loss 降了但熵反而升了这通常意味着模型在往更均匀但更接近目标的方向调整这时候去查数据分布和标签质量往往能找到隐藏的问题。这个习惯帮我发现过两次数据标注错误比盯着准确率曲线有用得多。最后再分享一个小技巧当你向别人解释交叉熵和 KL 散度的区别时可以借用快递包裹的比喻——信息熵是包裹本身的最小体积交叉熵是你实际用的盒子体积KL 散度是盒子里多余的填充泡沫的体积。你希望泡沫越少越好也就是让交叉熵逼近信息熵而信息熵的大小由真实分布决定模型能做的只是尽量别在盒子里浪费空间。想通这一层后面再看各种损失函数的变体大多都是在这盒泡沫上做文章。
RELATED

相关推荐

VC++远程控制源码实战:Winsock通信与MFC功能解析

VC++远程控制源码实战:Winsock通信与MFC功能解析

简介:用Visual C开发远程控制软件的源码包,适合需要学习Windows网络编程和系统控制原理的初学者及中级开发者,能够帮助快速搭建基于TCP/IP的远程控制原型。压缩包内共30个文件,其中10个头文件与8个C源代码文件构成了程序主体&…

📅 2026/10/22 3:01:50
基于YOLOV8的道路裂缝检测:从数据治理到工程落地

基于YOLOV8的道路裂缝检测:从数据治理到工程落地

1. 为什么裂缝检测这件事值得用一个目标检测框架来做1.1 路面裂缝的形态差异与检测难点我做过一段时间道路病害巡检相关的方向,最开始其实没打算一上来就上目标检测,而是先认真考虑过传统的数字图像处理方案。说实话,如果只是处理那种“背景干…

📅 2026/10/22 3:01:50
ReAct模式从原理到实战:构建高效LLM Agent的完整指南

ReAct模式从原理到实战:构建高效LLM Agent的完整指南

做LLM应用开发的同行,最近应该都被Agent这个词刷屏了。翻开源代码,无论是成熟框架还是个人Demo,大部分都绕不开ReAct模式。我最初接触ReAct时,以为是什么高深莫测的新架构,真正啃完论文、动手写过几轮之后才发现&#…

📅 2026/10/22 3:01:50
MORE NEWS

更多资讯

📰

VB与三菱Q系列PLC通讯源码解析:从MC协议到稳定收发

简介:一份面向工业自动化上位机开发者的VB与三菱Q系列PLC通讯数据传输源码包,聚焦串口与网络通信场景,适合具备VB基础并希望掌握PLC数据交换的开发新手,也适合需要实际工程参考的进阶人员。整个压缩包仅277KB,包含51个…

📰

AI辅助教材写作:从初稿到低查重的完整实操指南

1. 先搞明白:AI写教材和查重之间的真实关系1.1 教材写作的难点到底在哪里教材这个品类很特别,它不像自媒体文章,写错了改一改就行,也不像论文,只需要把论点论证清楚。教材要面对的是“教”和“学”两个场景&#xff0c…

📰

AI编程智能体分级选型与全行业落地实践指南

1. 智能体分级体系到底在分什么1.1 从"能聊天"到"能干活"的五个台阶很多人第一次接触AI编程智能体,脑子里浮现的还是那个"你问我答"的聊天框。但真正在工程一线用过智能体的人都知道,聊天只是最表层的能力。行业里目前比较…

📰

无需训练即可评估神经网络架构:NASWOT原理与实践

1. 这篇论文到底想解决什么问题第一次看到"Neural Architecture Search without Training"这个标题,我的反应是:不训练怎么搜索?这不是悖论吗?毕竟NAS(神经网络架构搜索)这个领域从诞生之初就带着…

📰

Linux swap 启停操作与 swappiness 调优实战指南

1. 从一次线上告警说起:swap 到底在什么情况下会咬人凌晨两点,监控面板上一条内存使用率的曲线突然拉满,紧接着几台业务节点的响应时间从几十毫秒飙到两秒以上。登录机器一看,free -h显示物理内存还剩一点,但 swap 已经…

📰

HBase建表源码深度解析:从客户端到Master的完整链路与Procedure状态机

1. 从一次建表超时说起:为什么要啃 HBase 建表源码如果你在生产环境维护过 HBase 集群,大概率遇到过这样的场景:客户端调用createTable()之后卡住不动,或者返回超时异常,但表实际上已经建好了;又或者建表请…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬