从信息熵到交叉熵

理清香农熵、交叉熵与 KL 散度——它们如何度量「不确定」与「错配」。

香农在 1948 年《通信的数学理论》里提出的信息熵,是信息论的地基。今天每个人都在用 log_loss 训练分类器,但很少有人意识到:损失函数背后的「交叉熵」,不过是从「度量不确定」到「度量错配」的一小步。这篇文章用一页纸把它们串起来。

不确定:香农熵

先问一个朴素的问题:一个随机事件有多「意外」?概率 p(x)p(x) 越小,它发生时带来的信息量越大。我们定义某个结果 xx自信息(self-information)为 log2p(x)-\log_2 p(x),借鉴物理学的熵,把它的期望称为香农熵(Shannon entropy):

H(X)=xp(x)logp(x)H(X) = -\sum_{x} p(x) \log p(x)

这里藏着 log-\log 的物理直觉:概率越小,信息越大。越是几乎必然发生的事,它带来的信息越少;越罕见的结果,一旦出现越「值钱」。对数还让「信息可加」与「概率相乘」天然对齐——两个独立事件(概率 p1p_1p2p_2)同时发生的信息量等于各自信息量之和,即 log(p1p2)=logp1logp2-\log(p_1 p_2) = -\log p_1 - \log p_2,这正是信息论想要的可加性。

熵衡量的是不确定性:一个分布越平坦,结果越难预测,熵就越高。扔一枚均匀硬币,H=1H=1 bit;而一枚几乎总是掷出正面的硬币,H0H\approx 0

log2\log_2 时熵的单位是 bit,取 ln\ln 时是 nat——底数在正文里常写作 log2 与 loge;这个基的取舍不影响数学结构,只影响刻度。后面我们统一用自然对数。

错配:交叉熵

现在换一个视角。假设真实分布是 PP,我们却用 QQ 来预测。用 QQ 的编码去描述 PP 的样本,平均需要多少比特?这就是交叉熵(cross-entropy):

H(P,Q)=xp(x)logq(x)H(P,Q) = -\sum_{x} p(x) \log q(x)

注意两个分布的角色不对称:加权的是 PP(真实概率),取对数的是 QQ(预测概率)。当且仅当 P=QP=Q 时,它在所有 QQ 中取到最小值。

代价:KL 散度

交叉熵和我们熟悉的香农熵差多少?把上式的 logq(x)-\log q(x) 拆成两层:

DKL(PQ)=xp(x)logp(x)q(x)D_{\mathrm{KL}}(P\|Q) = \sum_{x} p(x)\log\frac{p(x)}{q(x)}

它度量的是 QQ 近似 PP 所付出的额外代价,故称KL 散度(Kullback–Leibler divergence)。三者的关系一目了然:

H(P,Q)=H(P)+DKL(PQ)H(P,Q) = H(P) + D_{\mathrm{KL}}(P\|Q)

跟随直觉核对:Q=PQ=PDKL=0D_{\mathrm{KL}}=0;对概率论稍熟的人也能验证,KL 恒非负。但正因为不对称,DKL(PQ)DKL(QP)D_{\mathrm{KL}}(P\|Q)\neq D_{\mathrm{KL}}(Q\|P)——它不是距离,而是散度,这也是它名字的由来。

这种不对称有直觉上的道理。当 pp 很小而 qq 很大时,plogpqp\log\frac{p}{q} 是个绝对值很小的负数,而且 pp 作为权重本就把它压得很低;反过来当 pp 很大而 qq 很小——即模型把高概率的真实事件估成几乎不可能——plogpqp\log\frac{p}{q} 会趋向无穷大。也就是说,「低估真实分布」的惩罚远重于「高估」——前者(pp 大、qq 小)让 plogpqp\log\frac{p}{q}\to\infty,后者(pp 小、qq 大)则被小权重压成接近 00。这正是 KL 不对称、也因此不是距离的原因。

把三者串成一条演化链,自信息是起点,熵是它的期望,交叉熵是「用错分布」的熵,而 KL 散度是两者的差:

flowchart LR
    A["自信息 -log p"] --> B["香农熵 H(X) = E[-log p]"]
    B --> C["交叉熵 H(P,Q)"]
    C --> D["KL 散度 D_KL(P‖Q)"]
    D -. "H(P,Q) = H(P) + D_KL" .-> C

一张图串起整个信息论

把信息论的几个核心量放在同一张图里,彼此的关系就一目了然:

mindmap
  root((信息论 Information Theory))
    自信息
      -log p
    熵
      H(X)
    交叉熵
      H(P,Q)
    KL 散度
      D_KL
    互信息
      I(X;Y)
    与最大似然
      MLE

其中 互信息(mutual information, I(X;Y)I(X;Y))度量「知道了 YY 之后,XX 的不确定减少多少」,它由熵与条件熵之差给出:

I(X;Y)=H(X)H(XY)=x,yp(x,y)logp(x,y)p(x)p(y)I(X;Y) = H(X) - H(X\mid Y) = \sum_{x,y} p(x,y)\log\frac{p(x,y)}{p(x)p(y)}

那棵树的每一根枝都是一条可验证的等式,而机器学习恰好站在互信息的一张特殊切片上:我们无法观测到真实的 PP,只能退而求其次,用交叉熵去逼近它。

多分类损失是怎么算出来的

flowchart TD
    A["输入 batch x"] --> B["模型前向 forward"]
    B --> C["softmax 输出 ŷ"]
    C --> D{"取真实类别 y"}
    D --> E["one-hot 标签 y"]
    E --> F["-Σ y_i log ŷ_i"]
    F --> G["交叉熵损失 L"]
    G --> H["反向传播 backprop"]
    H --> I["梯度下降 gradient descent"]

注意 softmaxone-hot 是一对:前者把模型对 CC 类的打分压成概率分布 y^\hat y,后者把真实标签展开成只有一处为 11 的向量。二者相乘后,损失只剩下「正确类别的负对数概率」这一项——这正是前文强调的「只惩罚打错的程度」。

训练一轮的序列

把上面的静态图展开成时间线,一轮训练就是数据、模型、损失、优化器四方的接力:

sequenceDiagram
    participant D as 数据 Data
    participant M as 模型 Model
    participant L as 损失 Loss
    participant O as 优化器 Optimizer
    D->>M: batch x
    M->>M: softmax → ŷ
    M->>L: ŷ, y
    L->>L: 交叉熵 -Σ y log ŷ
    L->>O: 梯度 ∇θ
    O->>M: 更新 θ

要把这次接力落到代码里,通常按下面的顺序动手:

  1. 准备数据:把 batch 归一化、打乱,并划分训练/验证集
    1. 先做均值-方差归一化,再 shuffle
    2. 留出约 10% 当验证集,避免过拟合被训练指标掩盖
  2. 前向:输入过一遍网络,得到 softmax 概率 y^\hat y
  3. 反向:沿交叉熵的梯度回传,更新参数 θ\theta

“Information is the resolution of uncertainty.” — Claude Shannon, 1948

后世的教科书几乎都沿用这套视角:把「消除不确定」当作度量的目标,正文可见 https://en.wikipedia.org/wiki/Information_theory

香农本人坦言,他特意从统计力学借来「熵」这个词,只因它与热力学熵「形式相同而含义更广」——这层借用的历史,本身也是信息论一步步独立成科的一段注脚。

这正是交叉熵的深层身份:它把「分辨不确定」落实成一个可微的损失,让梯度能沿着 softmax 一路回传。全篇可以用一句英文收束——“Minimizing cross-entropy is maximum likelihood.” 最小化交叉熵,就是最大似然。

顺带把散落在各处的术语收进一张对照表,方便查阅:

中文英文
互信息mutual information, I(X;Y)I(X;Y)
交叉熵cross-entropy, H(P,Q)H(P,Q)
softmaxsoftmax
one-hot 编码one-hot encoding
梯度下降gradient descent
反向传播backpropagation
似然likelihood

为什么分类损失用交叉熵

训练分类器时,我们有样本与其标签,却不知道真实分布 PP 本身(Cover & Thomas, 2006)。我们只能让模型输出 QQ,目标是让 QQ 尽量接近近似 PP经验分布(empirical distribution,即 label 的 one-hot)。

若用「误差平方」做主,参数更新慢、且损失平面存在大量鞍点;而交叉熵对 QQ 的梯度写得干净。看关系式:H(P,Q)=H(P)+DKLH(P,Q)=H(P)+D_{\mathrm{KL}},其中 H(P)H(P) 是常数,最小化交叉熵 ≡ 最小化 KL 散度

更本质地,这与最大似然估计(maximum likelihood estimation, MLE)是同一件事:在经验分布 P^\hat P 下,样本似然的对数期望正是 H^(P^,Q)-\hat H(\hat P,Q)。最大化似然等价于最小化交叉熵——这就是分类用交叉熵的深层原因:它不是拍脑袋选的损失,而是从「让模型尽量像真实分布」的统计原则里自然长出来的。这条等价链可以画成:

flowchart LR
    A["最大化似然 log P(D|θ)"] --> B["最大化 Σ log q_i"]
    B --> C["最小化 -Σ log q_i"]
    C --> D["最小化交叉熵 H(P,Q)"]
    D --> E["最小化 KL 散度 D_KL"]

多分类时,QQsoftmax 输出,PP 是 one-hot 标签。记 yiy_i 为标签、y^i\hat y_i 为模型对第 ii 类的预测概率,交叉熵写为:

L=i=1Cyilogy^i\mathcal{L} = -\sum_{i=1}^{C} y_i \log \hat y_i

由于 one-hot 只在真实类别处为 11,上式实际上只惩罚「模型给正确类别打的概率」,其余项全部归零。

代码上它往往配合 softmax 一起用。NumPy 版本的交叉熵损失如下:

import numpy as np

def cross_entropy(p, q, eps=1e-12):
    # p: one-hot 标签; q: softmax 输出, 剪裁避免 log(0)
    q = np.clip(q, eps, 1.0)
    return -np.sum(p * np.log(q))

这个 eps 的量级通常取 10<sup>-12</sup>:太小会触发浮点下溢,太大又会扭曲梯度。在 Jupyter 里复现这一小段,写完按 Ctrl+Enter 运行,就能看到单个样本的交叉熵。

更直观的对照

度量公式直觉
H(P)H(P)p(x)logp(x)-\sum p(x)\log p(x)一个分布本身有多不确定
交叉熵 H(P,Q)H(P,Q)p(x)logq(x)-\sum p(x)\log q(x)QQPP平均成本
KL 散度 DKL(PQ)D_{\mathrm{KL}}(P\Vert Q)p(x)logp(x)q(x)\sum p(x)\log\frac{p(x)}{q(x)}猜错的额外代价(非对称)

信息熵与交叉熵的关系示意

小记

顺一遍主线:度量「不确定」,交叉熵度量「错配」,KL 散度度量的正是这两者之差。二者不对称,是理解散度的钥匙。而在机器学习里,我们用一个恒定的 H(P)H(P),把难算的 DKLD_{\mathrm{KL}} 悄悄换成了好算的 H(P,Q)H(P,Q)。更完整的推导可参考 维基百科:Cross entropy

术语速查

核心概念用一句话收拢,方便对照正文:

熵 H(X)
度量一个分布本身的不确定性——自信息 -log p 的期望。
交叉熵 H(P,Q)
用预测分布 Q 的编码去描述真实分布 P 的样本,所需的平均比特数。
KL 散度 D_KL(P‖Q)
用 Q 近似 P 相比用 P 描述 P 多花的那部分代价,非对称、恒非负。
互信息 I(X;Y)
知道 Y 后 X 的不确定减少量,即 H(X) − H(X|Y)。

理解信息论 checklist

对照正文逐项核对,能勾掉的越多,说明整条脉络越清楚:

  • 理解自信息 logp-\log p 的由来:概率越小,信息越大
  • 分清 H(X)H(X)H(P,Q)H(P,Q)DKLD_{\mathrm{KL}} 三者:熵是「自信息的期望」,交叉熵是「用错分布」,KL 是「两者之差」
  • 推导 H(P,Q)=H(P)+DKLH(P,Q) = H(P) + D_{\mathrm{KL}}
  • 证明最小化交叉熵 ≡ 最大似然

顺带一提,写这类笔记时 Markdown 会吞掉一些记号,想让它们原样显示就得转义:星号 * 在信息论里不表示乘法(概率相乘的乘号往往直接省略),列表项的连字符 - 若不转义会被当成列表符号,表格单元格里的竖线 | 也得转义才不会破坏列结构。

由此,交叉熵从一个纯数学对象,变成了所有分类任务的默认准绳。偏离真实越远,交叉熵惩罚越重——这就是逻辑回归与深度网络共享的同一块地基。


附 · 本页的 Markdown 写法

上面是正文,这一篇是它的写作笔记:把这篇用到的 Markdown 语法逐项拆开,每项都给「写法」与「效果」,示例仍取自信息论。

标题

正文从 ## 起笔,小节用 ###;页面大标题由 frontmatter 的 title 字段给出。

写法:

## 二级标题
### 三级标题

frontmatter(页面元数据)

文件最顶部的 --- 包裹区是 frontmatter,用 YAML 写页面级信息。写作时对照下表,别漏字段:

字段必填用途默认值
title✅ 必填页面大标题、浏览器标签页标题
description✅ 必填列表卡片与搜索引擎摘要
pubDate✅ 必填发布日期,决定文章排序
updatedDate可选大改后填,页面显示「更新于」
heroImage可选文章头图
encrypted可选设为 true 正文需密码解锁false
published可选设为 false 发布构建隐藏true

必填三字段的写法:

---
title: '从信息熵到交叉熵'
description: '理清香农熵、交叉熵与 KL 散度。'
pubDate: 'Aug 02 2026'
---

可选字段示例(用到才写):

---
title: '从信息熵到交叉熵'
description: '理清香农熵、交叉熵与 KL 散度。'
pubDate: 'Aug 02 2026'
updatedDate: 'Aug 05 2026'      # 大改后填,页面显示「更新于」
heroImage: '../../assets/cover.jpg'  # 文章头图
encrypted: true                  # 正文需密码解锁(配合 CF Worker)
published: false                 # 设为 false 在发布构建中隐藏(dev 仍可见)
---

强调:粗体、斜体、行内代码

写法:

**** 度量不确定性,*交叉熵* 度量错配,`log_loss` 是常见损失。

效果:

度量不确定性,交叉熵 度量错配,log_loss 是常见损失。

公式(KaTeX)

行内公式夹单个 $,块级公式夹双 $

写法:

自信息是 $-\log p(x)$,熵是它的期望:
$$
H(X) = -\sum_x p(x)\log p(x)
$$

效果:

自信息是 logp(x)-\log p(x),熵是它的期望:

H(X)=xp(x)logp(x)H(X) = -\sum_x p(x)\log p(x)

引用块

行首 > 起引用。

写法:

> 熵衡量的是不确定性:分布越平坦,结果越难预测。

效果:

熵衡量的是不确定性:分布越平坦,结果越难预测。

列表与嵌套

无序用 -,有序用 1.,缩进两层即嵌套。

写法:

- 自信息:$-\log p(x)$
- 熵:$H(X)$
  - 交叉熵:$H(P,Q)$
  - KL 散度:$D_{KL}$

效果:

  • 自信息:logp(x)-\log p(x)
  • 熵:H(X)H(X)
    • 交叉熵:H(P,Q)H(P,Q)
    • KL 散度:DKLD_{KL}

任务列表

- [ ] 未勾选,- [x] 已勾选。

写法:

- [x] 理解自信息 $-\log p$ 的由来
- [ ] 推导 $H(P,Q) = H(P) + D_{KL}$

效果:

  • 理解自信息 logp-\log p 的由来
  • 推导 H(P,Q)=H(P)+DKLH(P,Q) = H(P) + D_{KL}

表格

表头、分隔行、表体三行构成,单元格用 | 分隔。

写法:

| 度量 | 一句话 |
| --- | --- |
| 熵 $H(P)$ | 一个分布本身有多不确定 |
| 交叉熵 $H(P,Q)$ | 用 $Q$ 猜 $P$ 的平均成本 |

效果:

度量一句话
H(P)H(P)一个分布本身有多不确定
交叉熵 H(P,Q)H(P,Q)QQPP 的平均成本

代码块

三个反引号 + 语言名开启语法高亮。

写法:

```python
import numpy as np

def cross_entropy(p, q, eps=1e-12):
    q = np.clip(q, eps, 1.0)
    return -np.sum(p * np.log(q))
```

效果:

import numpy as np

def cross_entropy(p, q, eps=1e-12):
    q = np.clip(q, eps, 1.0)
    return -np.sum(p * np.log(q))

mermaid 图

写法:

```mermaid
flowchart LR
    A["自信息 -log p"] --> B["香农熵 H(X)"]
    B --> C["交叉熵 H(P,Q)"]
```

渲染后即正文里那些可放大拖拽的流程图。

脚注

正文用 [^标记] 引用,文末(通常文件末尾)写定义。这里只展示写法,不再另加脚注:

信息论的地基是香农 1948 年的论文[^shannon]

[^shannon]: C. E. Shannon, *A Mathematical Theory of Communication*, 1948.

定义列表(HTML)

写法与效果:

<dl>
  <dt>熵 H(X)</dt>
  <dd>自信息的期望。</dd>
  <dt>交叉熵 H(P,Q)</dt>
  <dd>用 Q 的编码描述 P 的平均比特数。</dd>
</dl>
熵 H(X)
自信息的期望。
交叉熵 H(P,Q)
用 Q 的编码描述 P 的平均比特数。

行内 HTML:sub、sup、kbd、mark、abbr

写法:

取 log<sub>2</sub> 时熵的单位是 bit,取 log<sub>e</sub> 时是 nat。

按 <kbd>Ctrl</kbd> + <kbd>Enter</kbd> 运行,得到单个样本的交叉熵。

<mark>最小化交叉熵,就是最大似然。</mark>

<abbr title="Kullback–Leibler divergence">KL</abbr> 散度并非距离。

效果:

取 log2 时熵的单位是 bit,取 loge 时是 nat。

Ctrl + Enter 运行,得到单个样本的交叉熵。

最小化交叉熵,就是最大似然。

KL 散度并非距离。

链接与图片

写法:

[维基百科:Cross entropy](https://en.wikipedia.org/wiki/Cross_entropy)

![信息熵与交叉熵的关系示意](https://img.666570.xyz/api/file/msd1clew-w7mdnr.png)

转义与注释

Markdown 会把部分字符当语法吞掉,想原样显示需用 \ 转义;<!-- --> 内的注释不会渲染。

写法:

星号 \* 在此不是乘法;表格单元格里的竖线 \| 需转义。

<!-- 这一行不会出现在页面上 -->

分割线

三个或更多 - 独占一行,就是一条分割线——本页正是用它把正文与这篇写法笔记隔开。





附 · 全文源码

---
title: '从信息熵到交叉熵'
description: '理清香农熵、交叉熵与 KL 散度——它们如何度量「不确定」与「错配」。'
pubDate: 'Aug 02 2026'
---

香农在 1948 年《通信的数学理论》里提出的**信息熵**,是信息论的地基。今天每个人都在用 `log_loss` 训练分类器,但很少有人意识到:损失函数背后的「交叉熵」,不过是从「度量不确定」到「度量错配」的一小步。这篇文章用一页纸把它们串起来。

## 不确定:香农熵

先问一个朴素的问题:一个随机事件有多「意外」?概率 $p(x)$ 越小,它发生时带来的信息量越大。我们定义某个结果 $x$ 的**自信息**(self-information)为 $-\log_2 p(x)$,借鉴物理学的熵,把它的期望称为**香农熵**(Shannon entropy):

$$
H(X) = -\sum_{x} p(x) \log p(x)
$$

这里藏着 $-\log$ 的物理直觉:概率越小,信息越大。越是几乎必然发生的事,它带来的信息越少;越罕见的结果,一旦出现越「值钱」。对数还让「信息可加」与「概率相乘」天然对齐——两个独立事件(概率 $p_1$、$p_2$)同时发生的信息量等于各自信息量之和,即 $-\log(p_1 p_2) = -\log p_1 - \log p_2$,这正是信息论想要的可加性。

> 熵衡量的是**不确定性**:一个分布越平坦,结果越难预测,熵就越高。扔一枚均匀硬币,$H=1$ bit;而一枚几乎总是掷出正面的硬币,$H\approx 0$。

取 $\log_2$ 时熵的单位是 bit,取 $\ln$ 时是 nat——底数在正文里常写作 log<sub>2</sub> 与 log<sub>e</sub>;这个基的取舍不影响数学结构,只影响刻度。后面我们统一用自然对数。

## 错配:交叉熵

现在换一个视角。假设真实分布是 $P$,我们却用 $Q$ 来预测。用 $Q$ 的编码去描述 $P$ 的样本,平均需要多少比特?这就是**交叉熵**(cross-entropy):

$$
H(P,Q) = -\sum_{x} p(x) \log q(x)
$$

注意两个分布的角色**不对称**:加权的是 $P$(真实概率),取对数的是 $Q$(预测概率)。当且仅当 $P=Q$ 时,它在所有 $Q$ 中取到最小值。

## 代价:KL 散度

交叉熵和我们熟悉的香农熵差多少?把上式的 $-\log q(x)$ 拆成两层:

$$
D_{\mathrm{KL}}(P\|Q) = \sum_{x} p(x)\log\frac{p(x)}{q(x)}
$$

它度量的是 <mark>用 $Q$ 近似 $P$ 所付出的额外代价</mark>,故称**KL 散度**(Kullback–Leibler divergence)。三者的关系一目了然:

$$
H(P,Q) = H(P) + D_{\mathrm{KL}}(P\|Q)
$$

跟随直觉核对:$Q=P$ 时 $D_{\mathrm{KL}}=0$;对概率论稍熟的人也能验证,KL 恒非负。但正因为不对称,$D_{\mathrm{KL}}(P\|Q)\neq D_{\mathrm{KL}}(Q\|P)$——它**不是**距离,而是散度,这也是它名字的由来。

这种不对称有直觉上的道理。当 $p$ 很小而 $q$ 很大时,$p\log\frac{p}{q}$ 是个绝对值很小的负数,而且 $p$ 作为权重本就把它压得很低;反过来当 $p$ 很大而 $q$ 很小——即模型把高概率的真实事件估成几乎不可能——$p\log\frac{p}{q}$ 会趋向无穷大。也就是说,「低估真实分布」的惩罚远重于「高估」——前者($p$ 大、$q$ 小)让 $p\log\frac{p}{q}\to\infty$,后者($p$ 小、$q$ 大)则被小权重压成接近 $0$。这正是 KL 不对称、也因此不是距离的原因。

把三者串成一条演化链,自信息是起点,熵是它的期望,交叉熵是「用错分布」的熵,而 KL 散度是两者的差:

```mermaid
flowchart LR
    A["自信息 -log p"] --> B["香农熵 H(X) = E[-log p]"]
    B --> C["交叉熵 H(P,Q)"]
    C --> D["KL 散度 D_KL(P‖Q)"]
    D -. "H(P,Q) = H(P) + D_KL" .-> C
```

## 一张图串起整个信息论

把信息论的几个核心量放在同一张图里,彼此的关系就一目了然:

```mermaid
mindmap
  root((信息论 Information Theory))
    自信息
      -log p

      H(X)
    交叉熵
      H(P,Q)
    KL 散度
      D_KL
    互信息
      I(X;Y)
    与最大似然
      MLE
```

其中 **互信息**(mutual information, $I(X;Y)$)度量「知道了 $Y$ 之后,$X$ 的不确定减少多少」,它由熵与条件熵之差给出:

$$
I(X;Y) = H(X) - H(X\mid Y) = \sum_{x,y} p(x,y)\log\frac{p(x,y)}{p(x)p(y)}
$$

那棵树的每一根枝都是一条可验证的等式,而机器学习恰好站在互信息的一张特殊切片上:我们无法观测到真实的 $P$,只能退而求其次,用交叉熵去逼近它。

## 多分类损失是怎么算出来的

```mermaid
flowchart TD
    A["输入 batch x"] --> B["模型前向 forward"]
    B --> C["softmax 输出 ŷ"]
    C --> D{"取真实类别 y"}
    D --> E["one-hot 标签 y"]
    E --> F["-Σ y_i log ŷ_i"]
    F --> G["交叉熵损失 L"]
    G --> H["反向传播 backprop"]
    H --> I["梯度下降 gradient descent"]
```

注意 `softmax``one-hot` 是一对:前者把模型对 $C$ 类的打分压成概率分布 $\hat y$,后者把真实标签展开成只有一处为 $1$ 的向量。二者相乘后,损失只剩下「正确类别的负对数概率」这一项——这正是前文强调的「只惩罚打错的程度」。

## 训练一轮的序列

把上面的静态图展开成时间线,一轮训练就是数据、模型、损失、优化器四方的接力:

```mermaid
sequenceDiagram
    participant D as 数据 Data
    participant M as 模型 Model
    participant L as 损失 Loss
    participant O as 优化器 Optimizer
    D->>M: batch x
    M->>M: softmax → ŷ
    M->>L: ŷ, y
    L->>L: 交叉熵 -Σ y log ŷ
    L->>O: 梯度 ∇θ
    O->>M: 更新 θ
```

要把这次接力落到代码里,通常按下面的顺序动手:

1. 准备数据:把 batch 归一化、打乱,并划分训练/验证集
   1. 先做均值-方差归一化,再 shuffle
   2. 留出约 10% 当验证集,避免过拟合被训练指标掩盖
2. 前向:输入过一遍网络,得到 softmax 概率 $\hat y$
3. 反向:沿交叉熵的梯度回传,更新参数 $\theta$

> "Information is the resolution of uncertainty." — Claude Shannon, 1948
>
> 后世的教科书几乎都沿用这套视角:把「消除不确定」当作度量的目标,正文可见 <https://en.wikipedia.org/wiki/Information_theory>
>
> >> 香农本人坦言,他特意从统计力学借来「熵」这个词,只因它与热力学熵「形式相同而含义更广」——这层借用的历史,本身也是信息论一步步独立成科的一段注脚。

这正是交叉熵的深层身份:它把「分辨不确定」落实成一个可微的损失,让梯度能沿着 `softmax` 一路回传。全篇可以用一句英文收束——<mark>"Minimizing cross-entropy is maximum likelihood."</mark> 最小化交叉熵,就是最大似然。

顺带把散落在各处的术语收进一张对照表,方便查阅:

| 中文 | 英文 |
| --- | --- |
| 互信息 | mutual information, $I(X;Y)$ |
| 交叉熵 | cross-entropy, $H(P,Q)$ |
| softmax | softmax |
| one-hot 编码 | one-hot encoding |
| 梯度下降 | gradient descent |
| 反向传播 | backpropagation |
| 似然 | likelihood |

## 为什么分类损失用交叉熵

训练分类器时,我们有样本与其标签,却不知道真实分布 $P$ 本身(Cover & Thomas, 2006)。我们只能让模型输出 $Q$,目标是让 $Q$ 尽量接近近似 $P$ 的 <mark>经验分布</mark>(empirical distribution,即 label 的 one-hot)。

若用「误差平方」做主,参数更新慢、且损失平面存在大量鞍点;而交叉熵对 $Q$ 的梯度写得干净。看关系式:$H(P,Q)=H(P)+D_{\mathrm{KL}}$,其中 $H(P)$ 是常数,**最小化交叉熵 ≡ 最小化 KL 散度**

<!-- TODO: 补贝叶斯视角——从后验最大化的角度把这条等价链再推一遍 -->

更本质地,这与**最大似然估计**(maximum likelihood estimation, MLE)是同一件事:在经验分布 $\hat P$ 下,样本似然的对数期望正是 $-\hat H(\hat P,Q)$。最大化似然等价于最小化交叉熵——这就是分类用交叉熵的深层原因:它不是拍脑袋选的损失,而是从「让模型尽量像真实分布」的统计原则里自然长出来的。这条等价链可以画成:

```mermaid
flowchart LR
    A["最大化似然 log P(D|θ)"] --> B["最大化 Σ log q_i"]
    B --> C["最小化 -Σ log q_i"]
    C --> D["最小化交叉熵 H(P,Q)"]
    D --> E["最小化 KL 散度 D_KL"]
```

多分类时,$Q$ 由 `softmax` 输出,$P$ 是 one-hot 标签。记 $y_i$ 为标签、$\hat y_i$ 为模型对第 $i$ 类的预测概率,交叉熵写为:

$$
\mathcal{L} = -\sum_{i=1}^{C} y_i \log \hat y_i
$$

由于 one-hot 只在真实类别处为 $1$,上式实际上只惩罚「模型给正确类别打的概率」,其余项全部归零。

代码上它往往配合 `softmax` 一起用。NumPy 版本的交叉熵损失如下:

```python
import numpy as np

def cross_entropy(p, q, eps=1e-12):
    # p: one-hot 标签; q: softmax 输出, 剪裁避免 log(0)
    q = np.clip(q, eps, 1.0)
    return -np.sum(p * np.log(q))
```

这个 `eps` 的量级通常取 `10<sup>-12</sup>`:太小会触发浮点下溢,太大又会扭曲梯度。在 Jupyter 里复现这一小段,写完按 <kbd>Ctrl</kbd>+<kbd>Enter</kbd> 运行,就能看到单个样本的交叉熵。

### 更直观的对照

| 度量 | 公式 | 直觉 |
| --- | --- | --- |
| 熵 $H(P)$ | $-\sum p(x)\log p(x)$ | 一个分布**本身有多不确定** |
| 交叉熵 $H(P,Q)$ | $-\sum p(x)\log q(x)$ | 用 $Q$ 猜 $P$ 的**平均成本** |
| KL 散度 $D_{\mathrm{KL}}(P\Vert Q)$ | $\sum p(x)\log\frac{p(x)}{q(x)}$ | 猜错的**额外代价**(非对称) |

![信息熵与交叉熵的关系示意](https://img.666570.xyz/api/file/msd1clew-w7mdnr.png "三层关系:H(P) 是底,D_KL 是差距,H(P,Q) 是两者之和")

## 小记

顺一遍主线:<abbr title="香农熵">熵</abbr>度量「不确定」,交叉熵度量「错配」,KL 散度度量的正是这两者之差。二者不对称,是理解散度的钥匙。而在机器学习里,我们用一个恒定的 $H(P)$,把难算的 $D_{\mathrm{KL}}$ 悄悄换成了好算的 $H(P,Q)$。更完整的推导可参考 [维基百科:Cross entropy](https://en.wikipedia.org/wiki/Cross_entropy)

## 术语速查

核心概念用一句话收拢,方便对照正文:

<dl>
  <dt>熵 H(X)</dt>
  <dd>度量一个分布本身的不确定性——自信息 -log p 的期望。</dd>
  <dt>交叉熵 H(P,Q)</dt>
  <dd>用预测分布 Q 的编码去描述真实分布 P 的样本,所需的平均比特数。</dd>
  <dt>KL 散度 D_KL(P‖Q)</dt>
  <dd>用 Q 近似 P 相比用 P 描述 P 多花的那部分代价,非对称、恒非负。</dd>
  <dt>互信息 I(X;Y)</dt>
  <dd>知道 Y 后 X 的不确定减少量,即 H(X) − H(X|Y)。</dd>
</dl>

## 理解信息论 checklist

对照正文逐项核对,能勾掉的越多,说明整条脉络越清楚:

- [x] 理解自信息 $-\log p$ 的由来:概率越小,信息越大
- [x] 分清 $H(X)$、$H(P,Q)$、$D_{\mathrm{KL}}$ 三者:熵是「自信息的期望」,交叉熵是「用错分布」,KL 是「两者之差」
- [ ] 推导 $H(P,Q) = H(P) + D_{\mathrm{KL}}$
- [ ] 证明最小化交叉熵 ≡ 最大似然

> 顺带一提,写这类笔记时 Markdown 会吞掉一些记号,想让它们原样显示就得转义:星号 \* 在信息论里不表示乘法(概率相乘的乘号往往直接省略),列表项的连字符 \- 若不转义会被当成列表符号,表格单元格里的竖线 \| 也得转义才不会破坏列结构。

由此,<abbr title="交叉熵 (Cross-Entropy)">交叉熵</abbr>从一个纯数学对象,变成了**所有分类任务的默认准绳**。偏离真实越远,交叉熵惩罚越重——这就是逻辑回归与深度网络共享的同一块地基。

---

## 附 · 本页的 Markdown 写法

上面是正文,这一篇是它的写作笔记:把这篇用到的 Markdown 语法逐项拆开,每项都给「写法」与「效果」,示例仍取自信息论。

### 标题

正文从 `##` 起笔,小节用 `###`;页面大标题由 frontmatter 的 `title` 字段给出。

写法:

```markdown
## 二级标题
### 三级标题
```

### frontmatter(页面元数据)

文件最顶部的 `---` 包裹区是 frontmatter,用 YAML 写页面级信息。写作时对照下表,别漏字段:

| 字段 | 必填 | 用途 | 默认值 |
| --- | --- | --- | --- |
| `title` | ✅ 必填 | 页面大标题、浏览器标签页标题 ||
| `description` | ✅ 必填 | 列表卡片与搜索引擎摘要 ||
| `pubDate` | ✅ 必填 | 发布日期,决定文章排序 ||
| `updatedDate` | 可选 | 大改后填,页面显示「更新于」 ||
| `heroImage` | 可选 | 文章头图 ||
| `encrypted` | 可选 | 设为 `true` 正文需密码解锁 | `false` |
| `published` | 可选 | 设为 `false` 发布构建隐藏 | `true` |

必填三字段的写法:

```markdown
---
title: '从信息熵到交叉熵'
description: '理清香农熵、交叉熵与 KL 散度。'
pubDate: 'Aug 02 2026'
---
```

可选字段示例(用到才写):

```markdown
---
title: '从信息熵到交叉熵'
description: '理清香农熵、交叉熵与 KL 散度。'
pubDate: 'Aug 02 2026'
updatedDate: 'Aug 05 2026'      # 大改后填,页面显示「更新于」
heroImage: '../../assets/cover.jpg'  # 文章头图
encrypted: true                  # 正文需密码解锁(配合 CF Worker)
published: false                 # 设为 false 在发布构建中隐藏(dev 仍可见)
---
```

### 强调:粗体、斜体、行内代码

写法:

```markdown
**** 度量不确定性,*交叉熵* 度量错配,`log_loss` 是常见损失。
```

效果:

**** 度量不确定性,*交叉熵* 度量错配,`log_loss` 是常见损失。

### 公式(KaTeX)

行内公式夹单个 `$`,块级公式夹双 `$`

写法:

```markdown
自信息是 $-\log p(x)$,熵是它的期望:
$$
H(X) = -\sum_x p(x)\log p(x)
$$
```

效果:

自信息是 $-\log p(x)$,熵是它的期望:

$$
H(X) = -\sum_x p(x)\log p(x)
$$

### 引用块

行首 `>` 起引用。

写法:

```markdown
> 熵衡量的是不确定性:分布越平坦,结果越难预测。
```

效果:

> 熵衡量的是不确定性:分布越平坦,结果越难预测。

### 列表与嵌套

无序用 `-`,有序用 `1.`,缩进两层即嵌套。

写法:

```markdown
- 自信息:$-\log p(x)$
- 熵:$H(X)$
  - 交叉熵:$H(P,Q)$
  - KL 散度:$D_{KL}$
```

效果:

- 自信息:$-\log p(x)$
- 熵:$H(X)$
  - 交叉熵:$H(P,Q)$
  - KL 散度:$D_{KL}$

### 任务列表

`- [ ]` 未勾选,`- [x]` 已勾选。

写法:

```markdown
- [x] 理解自信息 $-\log p$ 的由来
- [ ] 推导 $H(P,Q) = H(P) + D_{KL}$
```

效果:

- [x] 理解自信息 $-\log p$ 的由来
- [ ] 推导 $H(P,Q) = H(P) + D_{KL}$

### 表格

表头、分隔行、表体三行构成,单元格用 `|` 分隔。

写法:

```markdown
| 度量 | 一句话 |
| --- | --- |
| 熵 $H(P)$ | 一个分布本身有多不确定 |
| 交叉熵 $H(P,Q)$ | 用 $Q$ 猜 $P$ 的平均成本 |
```

效果:

| 度量 | 一句话 |
| --- | --- |
| 熵 $H(P)$ | 一个分布本身有多不确定 |
| 交叉熵 $H(P,Q)$ | 用 $Q$ 猜 $P$ 的平均成本 |

### 代码块

三个反引号 + 语言名开启语法高亮。

写法:

````markdown
```python
import numpy as np

def cross_entropy(p, q, eps=1e-12):
    q = np.clip(q, eps, 1.0)
    return -np.sum(p * np.log(q))
```
````

效果:

```python
import numpy as np

def cross_entropy(p, q, eps=1e-12):
    q = np.clip(q, eps, 1.0)
    return -np.sum(p * np.log(q))
```

### mermaid 图

写法:

````markdown
```mermaid
flowchart LR
    A["自信息 -log p"] --> B["香农熵 H(X)"]
    B --> C["交叉熵 H(P,Q)"]
```
````

渲染后即正文里那些可放大拖拽的流程图。

### 脚注

正文用 `[^标记]` 引用,文末(通常文件末尾)写定义。这里只展示写法,不再另加脚注:

```markdown
信息论的地基是香农 1948 年的论文[^shannon]

[^shannon]: C. E. Shannon, *A Mathematical Theory of Communication*, 1948.
```

### 定义列表(HTML)

写法与效果:

```markdown
<dl>
  <dt>熵 H(X)</dt>
  <dd>自信息的期望。</dd>
  <dt>交叉熵 H(P,Q)</dt>
  <dd>用 Q 的编码描述 P 的平均比特数。</dd>
</dl>
```

<dl>
  <dt>熵 H(X)</dt>
  <dd>自信息的期望。</dd>
  <dt>交叉熵 H(P,Q)</dt>
  <dd>用 Q 的编码描述 P 的平均比特数。</dd>
</dl>

### 行内 HTML:sub、sup、kbd、mark、abbr

写法:

```markdown
取 log<sub>2</sub> 时熵的单位是 bit,取 log<sub>e</sub> 时是 nat。

按 <kbd>Ctrl</kbd> + <kbd>Enter</kbd> 运行,得到单个样本的交叉熵。

<mark>最小化交叉熵,就是最大似然。</mark>

<abbr title="Kullback–Leibler divergence">KL</abbr> 散度并非距离。
```

效果:

取 log<sub>2</sub> 时熵的单位是 bit,取 log<sub>e</sub> 时是 nat。

按 <kbd>Ctrl</kbd> + <kbd>Enter</kbd> 运行,得到单个样本的交叉熵。

<mark>最小化交叉熵,就是最大似然。</mark>

<abbr title="Kullback–Leibler divergence">KL</abbr> 散度并非距离。

### 链接与图片

写法:

```markdown
[维基百科:Cross entropy](https://en.wikipedia.org/wiki/Cross_entropy)

![信息熵与交叉熵的关系示意](https://img.666570.xyz/api/file/msd1clew-w7mdnr.png)
```

### 转义与注释

Markdown 会把部分字符当语法吞掉,想原样显示需用 `\` 转义;`<!-- -->` 内的注释不会渲染。

写法:

```markdown
星号 \* 在此不是乘法;表格单元格里的竖线 \| 需转义。

<!-- 这一行不会出现在页面上 -->
```

### 分割线

三个或更多 `-` 独占一行,就是一条分割线——本页正是用它把正文与这篇写法笔记隔开。

---

---

---

---