尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
香农熵、交叉熵与KL散度:机器学习损失函数的本质
1. 为什么要聊熵从一次实际调参说起做机器学习久了你会发现很多看似深奥的概念其实每天都在用只是我们未必意识到它的来路。我自己第一次真正被熵这个概念击中是在调试一个分类模型的时候。模型在训练集上表现很好但一到验证集就崩损失函数曲线还反复震荡。那时候我半懂不懂地调学习率、改网络结构折腾了好几天最后才意识到问题可能出在损失函数对分布差异的度量方式上。那会儿我不得不回头把香农熵、交叉熵、相对熵这三个概念重新啃了一遍。说实话刚开始觉得它们就是信息论里的三个数学定义跟我手头的代码没多大关系。但啃完之后再看手里的模型很多之前凭感觉的操作突然就有了理论依据。比如为什么分类问题几乎都用交叉熵而不用均方误差为什么模型蒸馏里要用KL散度为什么有些场景下必须处理log里面的零值这些问题的答案全都藏在这三个概念的关系里。这篇文章我就想把它们掰开揉碎讲清楚。不会堆一堆看不懂的推导而是从信息量的直觉出发用实际的例子和代码把香农熵、交叉熵、相对熵各自的含义、公式、用途以及它们之间的关联讲透。适合正在学机器学习、做算法落地或者准备面试的读者也适合那种用了很久交叉熵但说不清它到底是什么的实践者。看完你会对损失函数和数据分布有更本质的理解。2. 香农熵信息量到底怎么量化2.1 一个反直觉的事实小概率事件信息量更大先别急着看公式我们从一个问题出发什么样的消息信息量大我告诉你明天太阳会从东方升起你肯定觉得这是废话因为它几乎是必然事件不带来任何新信息。但如果我告诉你明天某个地方会下雪——尤其当这个地方此刻还是盛夏那这条消息的信息量就很大因为这件事发生的概率很低。这就是香农在1948年那篇开创性论文里的核心洞见一条消息携带的信息量取决于它对应事件发生概率的倒数。概率越低信息量越大。一个事件的信息量定义为I(x) -log p(x)这里的log一般取以2为底单位是比特bit也可以取自然底数e单位是奈特nat。负号保证信息量为正因为p(x)在0到1之间时对数本身就是负的。这个定义其实非常优雅。如果你抛一个公平硬币正反面概率各是0.5那么任意一面的信息量就是-log2(0.5) 1比特恰好是最基本的一单位信息。如果你抛一个不均匀的硬币正面概率0.9那正面的信息量只有约0.15比特而反面概率0.1信息量约3.32比特。这个差异直观反映了意料之中和意料之外的区别。2.2 从信息量到香农熵对不确定性取期望单一事件的信息量定义好之后一个自然的问题是一个随机变量整体携带的信息量是多少我们不能只看某一个事件的概率而要看所有可能结果的平均情况。于是香农熵的定义就顺理成章地出现了H(X) -Σ p(x) log p(x)它本质上是对所有可能结果的信息量按概率加权平均。如果随机变量X只有有限个取值这个公式就很好算。拿一个最简单的例子一个均匀分布的随机变量有4种等可能结果那么H(X) -4 × 0.25 × log2(0.25) 2比特。这意味着平均需要2个二进制位才能完整描述这个变量的取值跟实际编码所需位数刚好对上。如果随机变量的分布非常集中比如某个结果概率高达0.97其他结果分摊剩下的0.03那熵就会很小因为绝大多数情况下事情几乎确定了没什么不确定性。极端情况是确定性事件概率为1H(X) 0完全没有信息量。所以熵可以理解为不确定性的度量越随机、越难预测熵越大越确定、越规律熵越小。我在实际工作中常用的一个直觉是把熵理解为编码长度的下限。如果要用二进制编码表示一个随机变量的取值最优编码的平均长度不能低于H(X)比特。香农的编码理论在这个基础上建立了整个数据压缩的框架比如Huffman编码接近但不超过这个下限。这个编码视角在理解交叉熵的时候特别有用因为它能帮我们把两个分布的距离翻译成平均编码代价。2.3 联合熵与条件熵复杂系统的基础单变量的香农熵只是起点。现实中我们面对的往往是一组随机变量比如训练数据里的特征和标签。联合熵H(X, Y)度量的是两个变量共同的不确定性定义就是把联合概率p(x, y)代入公式求和。条件熵H(Y|X)度量的是已知X之后Y还剩多少不确定性定义是H(Y|X) -Σ p(x, y) log p(y|x)这里的直觉很直接已知一个信息另一个信息的不确定性通常会下降。如果X和Y完全独立那么H(Y|X) H(Y)知道X对Y没有任何帮助。如果X能完全决定Y那么H(Y|X) 0不确定性归零。两者之间的情况就是我们做特征工程、信息提取的空间所在。条件熵和信息增益在决策树里是核心工具。我之前在某风控项目里做特征筛选就反复用信息增益来衡量每个特征对目标变量的解释能力本质就是在算H(标签) - H(标签|特征)。这个链路能走通完全依赖于熵概念本身的严密定义。3. 交叉熵机器学习里最常用的损失函数3.1 用真实分布做编码却用预测分布来计费香农熵描述的是一个分布自身的不确定性。但现实中我们经常需要面对两个分布一个是我们认为的真实分布另一个是模型预测出来的分布。这时候就需要交叉熵来衡量如果用预测分布去编码真实分布下的数据平均编码长度是多少。交叉熵的定义如下H(p, q) -Σ p(x) log q(x)注意这里的p和q角色不同。p是真实分布q是预测分布或者估计分布。公式里面用的对数是q(x)也就是你用q作为编码依据来给数据编码但数据的实际分布是p所以概率加权用的是p(x)。打个比方真实分布是话费账单预测分布是你预估的话费。你按预估的q去准备钱但实际扣费按真实的p来加权重结果你准备的钱可能不够花也可能花不完。如果p和q完全一致那么H(p, q) H(p)交叉熵等于香农熵这是最理想的情况编码效率最高。如果q偏离p交叉熵就会变大多余的部分就是浪费掉的编码成本。3.2 为什么分类任务都在用交叉熵机器学习里的分类任务比如图像识别或者情感分析本质是在学一个概率分布。模型对每个类别输出一个概率真实标签通常用one-hot向量表示也就是真实分布p是确定性的正确类别的概率为1其余为0。这时候交叉熵的计算会大幅简化H(p, q) -log q(正确类别)也就是说交叉熵损失只关心模型给正确类别分配的概率。这个概率越大log q越接近0损失越小概率越小损失越大且增长非常快。很多教程会对比为什么分类用交叉熵而不用均方误差。我自己的感受是均方误差对概率输出不够敏感梯度容易在输出饱和区域变得极小训练会非常慢而交叉熵的梯度形式天然跟预测概率减真实标签这个差值挂钩即使输出层饱和梯度仍然有足够大的信号推动参数更新。这个差异在实际训练里非常明显我在某图像分类Demo上对比过同样一个简单的全连接网络用交叉熵几十个epoch就能明显收敛用均方误差则像蜗牛爬一样最后精度还差一截。3.3 一段可以直接用的实现交叉熵的实现本身不难但有几个细节值得注意。最常见的坑是log(0)问题如果q(x)恰好等于0直接算log就会得到负无穷。工程上极少让概率真的等于0因为模型输出经过softmax后理论上概率为正但浮点精度下仍然可能下溢到0。所以实际代码里要么对q做clip要么直接使用带log的softmax。用PyTorch的时候很多人直接调nn.CrossEntropyLoss()但没搞清楚它内部已经包含了softmax。我的代码习惯是import torch import torch.nn.functional as F # 模型原始输出 logits形状 [batch, num_classes] logits torch.tensor([[2.0, 0.5, 0.1], [1.0, 2.0, 0.2]]) # 真实标签 labels torch.tensor([0, 1]) # 方式一直接用封装好的损失函数内部自动做softmax loss1 F.cross_entropy(logits, labels) # 方式二手动做log_softmax再取负值效果一样但更直观 log_probs F.log_softmax(logits, dim1) loss2 F.nll_loss(log_probs, labels) print(loss1.item()) # 约 0.4170 print(loss2.item()) # 约 0.4170用log_softmax而不是先softmax再log除了数值稳定性更优之外计算上也更快因为log_softmax直接利用log-sum-exp技巧避免了中间过程的精度损失。如果模型最后一层没有接softmax直接用cross_entropy输入logits就好千万别在外面再套一层softmax再去算交叉熵等于把softmax算了两次数值偏差在类别多的时候会明显放大。3.4 加权交叉熵与类别不平衡真实业务里的分类问题几乎没有类别完全均匀的。比如某个异常检测场景正样本可能只占1%负样本占99%。如果直接用普通交叉熵模型很容易把所有样本都预测为负类因为准确率依然高达99%。这时候就需要给不同类别分配不同的权重。加权交叉熵的形式是在每个样本的损失上乘一个类别权重L -Σ w_c × log q(y_c)w_c可以用频率的倒数近似比如类别c的样本占比越低权重越高。这个方案简单但有效。我在某垃圾文本识别项目里试过负样本是正样本的30倍左右不加权重的时候模型对正样本的召回率惨不忍睹加了频率倒数加权之后召回率直接翻了一倍多。不过权重也不是越大越好权重过大容易导致模型对少数类过拟合实际操作里我会先在验证集上观察召回率和精确率的平衡慢慢调。4. 相对熵KL散度度量两个分布的差异4.1 KL散度的定义编码代价的差值相对熵又叫KL散度名字拗口但含义不难。它度量的是如果用预测分布q去编码真实分布p的数据比起用p自身编码平均多花了多少比特。换句话说它是交叉熵和香农熵的差值KL(p || q) H(p, q) - H(p) Σ p(x) log (p(x) / q(x))展开写法就是KL(p || q) Σ p(x) [log p(x) - log q(x)]这个定义特别清晰。它先天就是以p为基准、评估q的逼近程度。如果q和p完全一致每一项的比值是1log为0KL散度为0。q越偏离pKL散度越大。所以它看起来像一个距离但实际上它不是严格意义上的距离度量因为它不具备对称性。4.2 不对称性KL(p||q)和KL(q||p)是两回事这是KL散度最容易被误解的点我见过很多人在实际分析里把它当对称距离用结果得出完全不同的结论。KL(p || q)和KL(q || p)在绝大多数情况下不相等。用一个简单的例子说明设p是一个均匀分布三种结果各1/3q是一个非常尖锐的分布第一种结果0.98另外两种各0.01。计算KL(p || q)因为q对第二、三种结果的概率只有0.01而p认为这些结果概率是0.33log(p/q)会非常大KL值很高。反过来计算KL(q || p)q大概率取第一种结果p给它的概率是0.33虽然也有惩罚但总体的惩罚小得多。同样的两个分布前后顺序一换数值天差地别。在实际应用中这个不对称性是有讲究的。模型蒸馏、变分推断、贝叶斯推断里KL方向的选择直接决定了优化行为的差异。用KL(q || p)优化q会让q在p有概率的地方尽量都覆盖到因为它惩罚的是p很重视但q给的概率小的情况结果q倾向于比p更宽泛。用KL(p || q)优化q会让q集中到p概率最高的地方因为它惩罚的是q很重视但p给的概率小的情况结果q倾向于锁死主要模式。我自己调试生成模型的时候经常能看到这两种方向带来的行为差别。你要的是覆盖所有可能的模式还是锁定最可能的模式决定了KL方向的取舍。4.3 对称化的变体与JS散度因为KL散度不对称不少领域会用对称化的变体比如JS散度。JS散度的定义是JS(p, q) 0.5 × KL(p || m) 0.5 × KL(q || m)其中m (p q) / 2是两个分布的均值分布。JS散度的取值范围是0到log2之间有界且对称在生成对抗网络里经常作为分布匹配的度量。但即便JS散度有这些优点它在两个分布完全不重叠的时候会退化为常数log2梯度消失严重这也是后来WGAN等模型转而使用Wasserstein距离的原因。KL散度还有一个广泛应用的场景是多分类模型蒸馏。某个大模型的预测概率分布作为soft target小模型去拟合这个分布优化目标就是最小化KL(大模型分布 || 小模型分布)。大模型分布由真实标签和暗知识共同构成小模型通过学习这个分布不仅学到这张图是猫这个结论还学到它和狗有几分相似这种相对关系。这个思路在移动端模型部署里非常常见某公司在做端侧图像分类的时候就是用KL散度把大网络的知识迁移给轻量网络效果比直接训练轻量网络好了不少。5. 三个概念的内在关联与实战选择5.1 一个公式串起全部前面其实已经多次暗示了三者的关系现在把它明确写出来H(p, q) H(p) KL(p || q)翻译成大白话就是交叉熵 香农熵 KL散度。真实分布p自身的熵H(p)是固定的交叉熵H(p, q)的变化完全由KL散度驱动。换句话说最小化交叉熵和最小化KL散度在优化上是等价的因为H(p)那一项不依赖q。这个关系在模型训练里非常实用。比如分类任务里真实的one-hot分布熵恒为0交叉熵就直接等于KL散度。但我们在日志里看到的loss数值往往包含了一个基线如果真实标签不是one-hot而是带噪声的软标签H(p)不为0这时候只看loss绝对值是没法准确判断模型拟合质量的要看去掉H(p)之后的相对变化。5.2 按场景选择什么时候用什么把三者的适用场景理一下可以避免不少选型困惑概念核心作用典型场景香农熵度量单分布的不确定性决策树特征选择、评估数据随机性、计算信息增益交叉熵度量两个分布在编码视角下的契合度分类损失函数、神经网络训练、多标签学习KL散度度量两个分布的相对差异模型蒸馏、变分推断、分布匹配、生成模型评估我在项目里最常见的用法是训练阶段用交叉熵做损失评估阶段用KL散度做分布对比分析而香农熵多用在特征工程和数据探索阶段。三者不是互相替代的关系而是关注同一件事的不同层次。5.3 一个综合案例从数据探索到训练评估举一个具体的例子串联三个阶段。某文本分类项目训练前我先算训练集标签分布的香农熵发现类别熵偏低意味着数据集中某些类别明显占多数这提示我需要做加权或重采样。训练阶段用交叉熵作为损失函数配合类别权重。训练结束后我把模型预测结果在测试集上的平均概率分布提取出来算它和真实分布之间的KL散度用来判断模型是否产生了系统性偏差比如是否过度偏向某个类别。整个过程看起来复杂但本质就是三个熵概念在不同环节各司其职。6. 常见误区与排查经验6.1 高频问题速查表常见误区问题表现正确做法误以为KL散度是距离使用上忽略不对称性把KL(p直接对概率做log概率为0时出现负无穷或NaN使用log_softmax或对概率加极小epsilon进行clip混淆log底数不同地方混用log2和log e比较数值出现偏差统一用同一底数关注相对变化而非绝对数值softmax重复计算模型已接softmax再在loss里套交叉熵确认loss函数内部是否自带softmax避免重复交叉熵和KL在日志平台混读不同框架记录的loss物理意义不一致确认H(p)基线横向比较只看KL或相对变化6.2 数值稳定性的实操心得数值稳定性在我实际开发中踩过的坑比想的要多。最典型的是手动实现交叉熵时直接-np.sum(p * np.log(q))一旦q里有元素因为下溢变成0结果直接变NaN。我的标准做法是给log输入加一个极小值比如1e-12或者直接用现成框架里的log_softmax和cross_entropy。但要注意加到分母上和加到log输入里是有区别的log(x eps)在x接近0的时候改变的是对数值本身效果好在分母上加eps则会影响整个损失的量级需要小心。另一个经验是关于大批量训练时的loss观察。很多人发现loss在前期下降很快后期突然波动甚至上升就急着调学习率。但有时候是因为模型预测逐渐自信某些样本的log q非常接近0交叉熵的值本身就波动剧烈。这时候我习惯看滑动平均的loss同时配合验证集指标一起判断而不是被单个batch的loss波动吓到。6.3 关于熵为何有效的深度体会我自己在啃完这几个概念之后最大的收获不是记住了公式而是建立了一种编码视角的思维方式。任何一次分布拟合本质上都是在找一套尽可能短的编码方案来描述数据。交叉熵告诉你要支付多少代价KL散度告诉你有多少浪费香农熵则决定了你到底能压到多短。这种视角让我在调模型时少了很多盲目试错出了问题也能更快定位到根因而不是在超参数里瞎转。如果只让我留一个建议那就是在面对任何一个听起来很高深的数学概念时别急着背公式先找到它对应的直觉场景。香农熵对应的是明天太阳从东方升起和明天这里下雪的信息量差异交叉熵对应的是你按预估话费准备的资金和实际账单的差距KL散度对应的是两套账单制度之间的浪费成本。抓住这些直觉公式再复杂也跑不掉。
RELATED

相关推荐

FOC电流环PI参数自整定:Simulink仿真模型与实现

FOC电流环PI参数自整定:Simulink仿真模型与实现

做电机控制的同行应该都有过这种经历:调电流环PI调得头皮发麻,Kp拧大一点电流波形开始抖,Ki给猛了系统直接振荡,试了上百组参数才勉强能用。更难受的是,好不容易调好的参数,换一台电机、换一块控制板、甚至…

📅 2026/10/21 17:46:40
动态反演+ESO+自适应:无人机姿态控制全家桶复现指南

动态反演+ESO+自适应:无人机姿态控制全家桶复现指南

最近我在复现一套无人机姿态控制方案,课题名称里串了四个关键词——动态反演、扩展状态观测器ESO、反馈线性化、自适应——翻译成大白话就是:用逆模型把非线性抵消掉,再用观测器把内外扰动估出来,最后用自适应律把参数不确定性也兜…

📅 2026/10/21 17:46:40
汽修营销人的毕业论文怎么选 AI 工具?从一份新能源 4S 店客户满意度调研说起 [特殊字符]

汽修营销人的毕业论文怎么选 AI 工具?从一份新能源 4S 店客户满意度调研说起 [特殊字符]

如果你读的是汽车技术服务与营销专业,大概率会遇到一类很“混搭”的毕业任务:既要懂汽车售后服务流程,又要会做客户调研和营销分析。比如论文题目可能是:《新能源汽车 4S 店售后服务客户满意度提升策略研究——以某市某品牌门店为…

📅 2026/10/21 17:46:40
MORE NEWS

更多资讯

📰

嵌入式C与标准C的差异:内存、运行时与编译器行为解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

UWB定位锚点三合一实测:中继、定位、信标如何兼顾部署效率

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

PLC工程师实战错题本:90条现场踩坑经验与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

从零理解电机旋转电压矢量:Clarke/Park变换与SVPWM仿真实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

从零搭建步兵机器人:硬件选型、供电与通信全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

读懂HCU控制模块说明书:状态机、标定与故障码排查

简介:《HCU控制模块使用说明书》是一份中文PDF版技术手册,面向MD880和HE系列变频器的调试与维护人员,系统讲解HCU控制模块的选型、安装、接线及扩展方法。文档按基本整流(HCU-20)、回馈整流(HCU-30&#xf…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

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

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

📞 💬