feat: 完整中文翻译 maths-cs-ai-compendium(数学·计算机科学·AI 知识大全)
翻译自英文原版 maths-cs-ai-compendium,共 20 章全部完成。 第01章 向量 | 第02章 矩阵 | 第03章 微积分 第04章 统计学 | 第05章 概率论 | 第06章 机器学习 第07章 计算语言学 | 第08章 计算机视觉 | 第09章 音频与语音 第10章 多模态学习 | 第11章 自主系统 | 第12章 图神经网络 第13章 计算与操作系统 | 第14章 数据结构与算法 第15章 生产级软件工程 | 第16章 SIMD与GPU编程 第17章 AI推理 | 第18章 ML系统设计 第19章 应用人工智能 | 第20章 前沿人工智能 翻译说明: - 所有数学公式 $...$ / $$...$$、代码块、图片引用完整保留 - mkdocs.yml 配置中文导航 + language: zh - README.md 已翻译为中文(兼 docs/index.md) - docs/ 目录包含指向各章文件的 symlink - 约 29,000 行中文内容,排除 .cache/ 构建缓存
This commit is contained in:
@@ -0,0 +1,167 @@
|
||||
# 计数
|
||||
|
||||
*计数是计算概率的前提——在分配可能性之前,你必须先知道有多少种结果。本文涵盖乘法与加法规则、阶乘、排列、组合、二项式系数,以及支撑机器学习中采样、哈希和概率分析的基本组合工具。*
|
||||
|
||||
- 在计算概率之前,我们需要先数清结果的数量。如果你想知道在扑克中拿到一手赢牌的概率,你必须先知道一共有多少种可能的牌型,以及其中有多少种是赢牌。计数正是让概率精确化的基础工具。
|
||||
|
||||
- 最简单的计数原则是**乘法规则**。如果一个选择有 $m$ 种选项,另一个独立的选择有 $n$ 种选项,那么组合起来的总结果数为 $m \times n$。
|
||||
|
||||
- 想象早上穿衣服的场景。你有 3 件衬衫和 4 条裤子。每件衬衫都能与每条裤子搭配,共有 $3 \times 4 = 12$ 种穿搭。
|
||||
|
||||

|
||||
|
||||
- 乘法规则可以推广到任意数量的选择。如果你还有 2 双鞋,那么总穿搭数就变成 $3 \times 4 \times 2 = 24$。每个新的独立选择都会乘到总计数中。
|
||||
|
||||
- **加法规则**处理"或"的场景。如果事件 A 有 $m$ 种发生方式,事件 B 有 $n$ 种发生方式,且它们不能同时发生(互斥),那么总的方式数为 $m + n$。
|
||||
|
||||
- 假设你要从城市 X 前往城市 Y:开车有 3 条路线,坐火车有 2 条路线。你无法同时选择两者,因此总选项数为 $3 + 2 = 5$。
|
||||
|
||||
- 当事件有重叠时,需要减去被重复计数的结果。如果 $A$ 和 $B$ 可以同时发生,计数为 $|A \cup B| = |A| + |B| - |A \cap B|$。这就是容斥原理,它将在我们讨论概率加法规则时再次出现。
|
||||
|
||||
- 非负整数 $n$ 的**阶乘**是从 1 到 $n$ 的所有正整数的乘积:
|
||||
|
||||
$$n! = n \times (n-1) \times (n-2) \times \cdots \times 2 \times 1$$
|
||||
|
||||
- 可以将阶乘理解为:将 $n$ 个不同的物体排成一列有多少种方式?三本书在书架上有 $3! = 3 \times 2 \times 1 = 6$ 种排列方式。按约定,$0! = 1$。
|
||||
|
||||
- 阶乘的增长速度极快。$10! = 3{,}628{,}800$,而 $20!$ 已经超过 $2.4 \times 10^{18}$。这种爆炸式增长正是暴力搜索在组合问题中变得不切实际的原因。
|
||||
|
||||
- **排列**是对物体的有序安排。当你从 $n$ 个不同的物体中选取 $r$ 个且顺序重要时,排列数为:
|
||||
|
||||
$$P(n, r) = \frac{n!}{(n - r)!}$$
|
||||
|
||||
- 想象从一个 10 人的俱乐部中选出会长、副会长和财务主管。第一个职位有 10 个候选人,第二个有 9 个,第三个有 8 个。因此 $P(10, 3) = 10 \times 9 \times 8 = 720$。公式也印证了这一点:$\frac{10!}{7!} = 720$。
|
||||
|
||||
- **组合**是无序的选择。当你从 $n$ 个中选取 $r$ 个且顺序无关紧要时,需要除去重复的排列顺序:
|
||||
|
||||
$$C(n, r) = \binom{n}{r} = \frac{n!}{r!(n - r)!}$$
|
||||
|
||||
- 符号 $\binom{n}{r}$ 读作"n 选 r"。核心思想是:每个组合对应 $r!$ 种排列(选出的 $r$ 个物品可以有 $r!$ 种重新排列的方式),因此我们将排列数除以 $r!$。
|
||||
|
||||

|
||||
|
||||
- 示例:从 10 人中组成一个 3 人委员会有多少种方式?顺序无关紧要(没有会长或副会长之分,只有成员),因此我们使用组合:
|
||||
|
||||
$$\binom{10}{3} = \frac{10!}{3! \cdot 7!} = \frac{10 \times 9 \times 8}{3 \times 2 \times 1} = 120$$
|
||||
|
||||
- 同样的 10 个人产生 720 种排列,但只有 120 种组合,因为每个 3 人组内部有 $3! = 6$ 种排序方式。
|
||||
|
||||
- 组合在概率中至关重要。二项式系数 $\binom{n}{r}$ 统计了在 $n$ 次试验中恰好获得 $r$ 次成功的方式数,这正是二项分布(见文件 03)的核心。
|
||||
|
||||
- 让我们通过一个经典的委员会问题来综合运用多种计数思路。
|
||||
|
||||
- **问题**:一个俱乐部有 8 名男性和 6 名女性。要组成一个 5 人委员会,其中恰好包含 3 名男性和 2 名女性,有多少种方式?
|
||||
|
||||
- **第 1 步**:从 8 人中选 3 名男性。
|
||||
|
||||
$$\binom{8}{3} = \frac{8!}{3! \cdot 5!} = \frac{8 \times 7 \times 6}{3 \times 2 \times 1} = 56$$
|
||||
|
||||
- **第 2 步**:从 6 人中选 2 名女性。
|
||||
|
||||
$$\binom{6}{2} = \frac{6!}{2! \cdot 4!} = \frac{6 \times 5}{2 \times 1} = 15$$
|
||||
|
||||
- **第 3 步**:应用乘法规则。每种男性选择可以与每种女性选择配对:
|
||||
|
||||
$$56 \times 15 = 840 \text{ 个委员会}$$
|
||||
|
||||
- 这种将复杂计数问题分解为独立子选择再相乘的模式,是组合数学中的标准方法。
|
||||
|
||||
- 还有**可重复的排列**。当物品可以重复时,从 $n$ 种类型中选 $r$ 个会产生 $n^r$ 种结果。一个使用数字 0-9 的 4 位 PIN 码有 $10^4 = 10{,}000$ 种可能性。每一位都有 10 种选择,乘法规则即可解决。
|
||||
|
||||
- **可重复的组合**(也称"星条法")统计从 $n$ 种类型中选 $r$ 个、允许重复且顺序无关的方式数:
|
||||
|
||||
$$\binom{n + r - 1}{r} = \frac{(n + r - 1)!}{r!(n - 1)!}$$
|
||||
|
||||
- 示例:从 4 种冰淇淋口味中选择 3 勺(允许重复)有 $\binom{4 + 3 - 1}{3} = \binom{6}{3} = 20$ 种选项。
|
||||
|
||||
- 总结计数工具箱:
|
||||
|
||||
| 场景 | 公式 |
|
||||
|---|---|
|
||||
| 有序,无重复(排列) | $P(n,r) = \frac{n!}{(n-r)!}$ |
|
||||
| 无序,无重复(组合) | $\binom{n}{r} = \frac{n!}{r!(n-r)!}$ |
|
||||
| 有序,可重复 | $n^r$ |
|
||||
| 无序,可重复 | $\binom{n+r-1}{r}$ |
|
||||
|
||||
- 每个涉及等可能结果(等概率结果)的概率计算都使用公式 $P(\text{事件}) = \frac{\text{有利结果数}}{\text{总结果数}}$。计数为我们提供了这两个数字。有了这个基础,我们将在下一个文件中正式定义概率本身。
|
||||
|
||||
## 编程练习(在 CoLab 或 notebook 中完成)
|
||||
|
||||
1. 使用阶乘公式和直接计算两种方式计算 $P(10, 3)$ 和 $\binom{10}{3}$。验证排列数总是组合数的 $r!$ 倍。
|
||||
```python
|
||||
import jax.numpy as jnp
|
||||
from math import factorial
|
||||
|
||||
n, r = 10, 3
|
||||
|
||||
perm = factorial(n) // factorial(n - r)
|
||||
comb = factorial(n) // (factorial(r) * factorial(n - r))
|
||||
|
||||
print(f"P({n},{r}) = {perm}")
|
||||
print(f"C({n},{r}) = {comb}")
|
||||
print(f"P / C = {perm // comb} (应等于 {r}! = {factorial(r)})")
|
||||
```
|
||||
|
||||
2. 通过程序解决委员会问题(8 人中选 3 名男性,6 人中选 2 名女性),并通过枚举所有有效委员会来验证。
|
||||
```python
|
||||
from itertools import combinations
|
||||
from math import factorial
|
||||
|
||||
def comb_count(n, r):
|
||||
return factorial(n) // (factorial(r) * factorial(n - r))
|
||||
|
||||
# 公式法
|
||||
men_ways = comb_count(8, 3)
|
||||
women_ways = comb_count(6, 2)
|
||||
print(f"公式法: {men_ways} × {women_ways} = {men_ways * women_ways}")
|
||||
|
||||
# 枚举法
|
||||
men = [f"M{i}" for i in range(1, 9)]
|
||||
women = [f"W{i}" for i in range(1, 7)]
|
||||
count = sum(1 for _ in combinations(men, 3) for _ in combinations(women, 2))
|
||||
print(f"枚举法: {count}")
|
||||
```
|
||||
|
||||
3. 统计由 26 个小写字母组成的 4 位密码有多少种(允许重复)。然后统计没有重复字母的密码有多少种。
|
||||
```python
|
||||
from math import factorial
|
||||
|
||||
n = 26
|
||||
r = 4
|
||||
|
||||
with_rep = n ** r
|
||||
without_rep = factorial(n) // factorial(n - r)
|
||||
|
||||
print(f"允许重复: {with_rep:>10,}")
|
||||
print(f"不允许重复: {without_rep:>10,}")
|
||||
print(f"含重复的比例: {1 - without_rep/with_rep:.2%}")
|
||||
```
|
||||
|
||||
4. 模拟生日问题:在 $k$ 人的群体中,至少两人共享生日的概率是多少?绘制 $k = 1$ 到 $60$ 的概率曲线,并找出概率超过 50% 的位置。
|
||||
```python
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def birthday_prob_exact(k):
|
||||
\"\"\"k 人群体中至少有一对共享生日的概率。\"\"\"
|
||||
p_no_match = 1.0
|
||||
for i in range(k):
|
||||
p_no_match *= (365 - i) / 365
|
||||
return 1 - p_no_match
|
||||
|
||||
ks = list(range(1, 61))
|
||||
probs = [birthday_prob_exact(k) for k in ks]
|
||||
|
||||
plt.figure(figsize=(8, 4))
|
||||
plt.plot(ks, probs, color="#3498db", linewidth=2)
|
||||
plt.axhline(y=0.5, color="#e74c3c", linestyle="--", alpha=0.7, label="50%")
|
||||
cross = next(k for k, p in zip(ks, probs) if p >= 0.5)
|
||||
plt.axvline(x=cross, color="#e74c3c", linestyle="--", alpha=0.7)
|
||||
plt.xlabel("群体大小 (k)")
|
||||
plt.ylabel("P(至少两人共享生日)")
|
||||
plt.title(f"生日问题(在 k={cross} 时超过 50%)")
|
||||
plt.legend()
|
||||
plt.grid(alpha=0.3)
|
||||
plt.show()
|
||||
```
|
||||
@@ -0,0 +1,243 @@
|
||||
# 概率概念
|
||||
|
||||
*概率论形式化了不确定性,并提供了在此框架下进行推理的规则。本文涵盖样本空间、事件、概率公理、条件概率、独立性、贝叶斯定理、频率派与贝叶斯派解释,这是机器学习中每个生成模型和判别模型背后的数学框架。*
|
||||
|
||||
- 概率为一个事件赋予一个介于 0 和 1 之间的数字,衡量该事件发生的可能性。
|
||||
|
||||
- 概率为 0 表示不可能,1 表示必然,0.5 则像抛硬币一样。
|
||||
|
||||
- 有两种主要解释。**频率派**观点认为概率是长期相对频率:抛一枚均匀硬币 10,000 次,正面大约会出现 50% 的次数。
|
||||
|
||||
- **贝叶斯派**观点认为概率是信念程度:你可能会说明天降雨的概率是 70%,尽管明天只会发生一次。
|
||||
|
||||
- 两种解释使用相同的数学规则。区别在于哲学层面,但在机器学习中这很重要。频率派方法给出点估计。贝叶斯派方法给出参数的完整分布。
|
||||
|
||||
- **样本空间** $S$ 是实验所有可能结果的集合。抛一枚硬币:$S = \{H, T\}$。掷一个骰子:$S = \{1, 2, 3, 4, 5, 6\}$。
|
||||
|
||||
- **事件**是样本空间的任意子集。"掷出偶数"是事件 $A = \{2, 4, 6\}$,它是 $S$ 的一个子集。
|
||||
|
||||
- 当所有结果等可能时,事件的概率就是简单的计数(来自文件 01):
|
||||
|
||||
$$P(A) = \frac{|A|}{|S|} = \frac{\text{有利结果}}{\text{总结果}}$$
|
||||
|
||||
- 对于偶数例子:$P(\text{偶数}) = \frac{3}{6} = 0.5$。
|
||||
|
||||

|
||||
|
||||
- 事件 $A$ 的**补集**,记作 $A'$ 或 $A^c$,是 $S$ 中所有不在 $A$ 中的元素。由于每个结果要么在 $A$ 中,要么不在:
|
||||
|
||||
$$P(A') = 1 - P(A)$$
|
||||
|
||||
- 补集通常是更简便的途径。与其计算 5 次抛硬币中至少得到一个正面的所有方式,不如计算得到全反面的一种方式然后相减:$P(\text{至少一个正面}) = 1 - P(\text{全反面}) = 1 - (0.5)^5 = 0.969$。
|
||||
|
||||
- 如果两个事件不能同时发生,则它们是**互斥**(不相交)的:$A \cap B = \emptyset$。一次掷骰子中掷出 2 和掷出 5 是互斥事件。
|
||||
|
||||
- **互斥事件的加法法则**很直接:
|
||||
|
||||
$$P(A \cup B) = P(A) + P(B) \quad \text{(若 } A \cap B = \emptyset\text{)}$$
|
||||
|
||||
- 当事件可能有重叠时,需要使用**一般加法法则**来避免重复计算交集:
|
||||
|
||||
$$P(A \cup B) = P(A) + P(B) - P(A \cap B)$$
|
||||
|
||||
- 这与计数中的容斥原理相对应。上方的维恩图说明了原因:紫色区域(交集)在 $P(A)$ 中被计算一次,在 $P(B)$ 中又被计算一次,因此我们减去一次。
|
||||
|
||||
- **联合概率** $P(A \cap B)$ 是 $A$ 和 $B$ 同时发生的概率。在一副扑克牌中,$P(\text{红色} \cap \text{国王}) = \frac{2}{52}$,因为有 2 张红色国王。
|
||||
|
||||
- **边际概率**是单个事件不考虑其他事件时的概率。$P(\text{红色}) = \frac{26}{52} = 0.5$ 是一个边际概率。如果你有关于两个变量的联合分布,通过对另一个变量求和(或积分)即可得到边际概率。
|
||||
|
||||
- **条件概率**回答的是:已知 $B$ 已经发生,$A$ 的概率是多少?我们将样本空间从 $S$ 缩小到 $B$,并问 $B$ 中同时属于 $A$ 的比例是多少:
|
||||
|
||||
$$P(A | B) = \frac{P(A \cap B)}{P(B)}, \quad P(B) > 0$$
|
||||
|
||||

|
||||
|
||||
- 示例:你抽一张牌,有人告诉你它是红色。它是国王的概率是多少?有 26 张红色牌,其中 2 张是国王,所以 $P(\text{国王} | \text{红色}) = \frac{2}{26} = \frac{1}{13}$。使用公式:$P(\text{国王} \cap \text{红色}) / P(\text{红色}) = \frac{2/52}{26/52} = \frac{1}{13}$。
|
||||
|
||||
- 如果知道一个事件发生了不会告诉你关于另一个事件的任何信息,则这两个事件是**独立**的。形式化定义:
|
||||
|
||||
$$P(A \cap B) = P(A) \cdot P(B)$$
|
||||
|
||||
- 等价地,$P(A | B) = P(A)$。分别抛两枚硬币是独立事件。无放回地抽两张牌不是独立的(第一次抽取会改变剩余牌的数量)。
|
||||
|
||||
- 独立性是一个巨大的简化工具。对于独立事件,联合概率分解为乘积形式,这使得计算可处理。许多机器学习模型假设特征之间独立(例如朴素贝叶斯),正是基于这种简化。
|
||||
|
||||
- 任意两个事件的**乘法法则**由条件概率公式重新排列得到:
|
||||
|
||||
$$P(A \cap B) = P(A | B) \cdot P(B) = P(B | A) \cdot P(A)$$
|
||||
|
||||
- 对于独立事件,由于条件概率等于边际概率,上式简化为 $P(A \cap B) = P(A) \cdot P(B)$。
|
||||
|
||||
- **贝叶斯定理**是概率论中最重要的结论之一,也是贝叶斯机器学习的基础。它让我们可以反转条件概率的方向:
|
||||
|
||||
$$P(A | B) = \frac{P(B | A) \cdot P(A)}{P(B)}$$
|
||||
|
||||
- 该定理直接源于将 $P(A \cap B)$ 写成两种形式:$P(B|A) \cdot P(A) = P(A|B) \cdot P(B)$,然后解出 $P(A|B)$。
|
||||
|
||||

|
||||
|
||||
- 每个部分都有名称:
|
||||
- **先验** $P(A)$:看到证据之前的初始信念
|
||||
- **似然** $P(B|A)$:假设 $A$ 为真的前提下,证据出现的概率
|
||||
- **证据** $P(B)$:看到证据的总概率,起归一化作用
|
||||
- **后验** $P(A|B)$:看到证据之后更新后的信念
|
||||
|
||||
- 让我们通过经典的医学诊断例子来理解。假设某种疾病影响 1% 的人口。针对该疾病的检测准确率为 95%:它能正确识别 95% 的患病者(灵敏度),并能正确识别 90% 的健康人(特异度)。
|
||||
|
||||
- 你的检测结果为阳性。你实际患病的概率是多少?
|
||||
|
||||
- 设 $D$ = 患病,$+$ = 检测阳性。
|
||||
- 先验:$P(D) = 0.01$
|
||||
- 似然:$P(+ | D) = 0.95$
|
||||
- 假阳性率:$P(+ | D') = 0.10$
|
||||
|
||||
- 我们需要 $P(+)$。根据全概率公式:
|
||||
|
||||
$$P(+) = P(+ | D) \cdot P(D) + P(+ | D') \cdot P(D')$$
|
||||
$$= 0.95 \times 0.01 + 0.10 \times 0.99 = 0.0095 + 0.099 = 0.1085$$
|
||||
|
||||
- 现在应用贝叶斯定理:
|
||||
|
||||
$$P(D | +) = \frac{P(+ | D) \cdot P(D)}{P(+)} = \frac{0.95 \times 0.01}{0.1085} \approx 0.088$$
|
||||
|
||||
- 尽管检测"准确率高达 95%",但阳性结果只能给你约 8.8% 的患病概率。先验至关重要。由于该疾病罕见,大多数阳性结果都是假阳性。这对机器学习中的任何分类问题都是一个关键见解:当类别不平衡时,仅靠准确率是具有误导性的。
|
||||
|
||||
- **全概率公式**将样本空间划分为互斥且完备的事件 $B_1, B_2, \ldots, B_n$,并将任意事件 $A$ 表示为:
|
||||
|
||||
$$P(A) = \sum_{i=1}^{n} P(A | B_i) \cdot P(B_i)$$
|
||||
|
||||
- 这正是我们在医学例子中计算 $P(+)$ 所用的方法:我们将人群分为"患病"和"未患病"两类。
|
||||
|
||||
- **概率的链式法则**将乘法法则推广到任意数量的事件:
|
||||
|
||||
$$P(A_1 \cap A_2 \cap \cdots \cap A_n) = P(A_1) \cdot P(A_2 | A_1) \cdot P(A_3 | A_1 \cap A_2) \cdots P(A_n | A_1 \cap \cdots \cap A_{n-1})$$
|
||||
|
||||
- 每个因子都以前面所有事件为条件。这是自回归语言模型的基石:一个句子的概率等于每个单词在给定前面所有单词条件下的概率的乘积。
|
||||
|
||||
- **条件独立**意味着两个事件在给定第三个事件的条件下是独立的。如果满足下式,则 $A$ 和 $B$ 在给定 $C$ 的条件下条件独立:
|
||||
|
||||
$$P(A \cap B | C) = P(A | C) \cdot P(B | C)$$
|
||||
|
||||
- 事件可以边际上相关但条件独立,反之亦然。例如,两名学生的考试成绩可能相关(都依赖于考试的难度),但给定考试难度后,他们的成绩是独立的。
|
||||
|
||||
- 条件独立是贝叶斯网络等图模型背后的关键假设。它允许将复杂的联合分布分解为可管理的部分,使推断在计算上可行。
|
||||
|
||||
## 编程练习(使用 CoLab 或 notebook)
|
||||
|
||||
1. 模拟医学诊断问题。生成 100,000 人的总体,应用疾病患病率和检测准确率,验证贝叶斯定理给出正确的后验概率。
|
||||
```python
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
|
||||
key = jax.random.PRNGKey(42)
|
||||
n = 100_000
|
||||
|
||||
# 生成总体
|
||||
k1, k2 = jax.random.split(key)
|
||||
has_disease = jax.random.bernoulli(k1, p=0.01, shape=(n,))
|
||||
|
||||
# 生成检测结果
|
||||
k3, k4 = jax.random.split(k2)
|
||||
# 灵敏度:P(+|D) = 0.95,特异度:P(-|D') = 0.90
|
||||
test_positive = jnp.where(
|
||||
has_disease,
|
||||
jax.random.bernoulli(k3, p=0.95, shape=(n,)),
|
||||
jax.random.bernoulli(k4, p=0.10, shape=(n,))
|
||||
)
|
||||
|
||||
# 在检测阳性的人群中,实际患病的比例是多少?
|
||||
positives = test_positive.astype(bool)
|
||||
true_positives = (has_disease & positives).sum()
|
||||
total_positives = positives.sum()
|
||||
|
||||
print(f"检测阳性总人数: {total_positives}")
|
||||
print(f"真阳性人数: {true_positives}")
|
||||
print(f"P(患病 | 阳性) = {true_positives / total_positives:.4f}")
|
||||
print(f"贝叶斯公式: {0.95 * 0.01 / 0.1085:.4f}")
|
||||
```
|
||||
|
||||
2. 通过模拟验证加法法则。生成具有已知概率和重叠程度的随机事件 A 和 B,然后验证 $P(A \cup B) = P(A) + P(B) - P(A \cap B)$。
|
||||
```python
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
|
||||
key = jax.random.PRNGKey(0)
|
||||
n = 200_000
|
||||
k1, k2 = jax.random.split(key)
|
||||
|
||||
# 事件:A = 值 < 0.4,B = 值 < 0.6(在 < 0.4 处重叠)
|
||||
vals_a = jax.random.uniform(k1, shape=(n,))
|
||||
vals_b = jax.random.uniform(k2, shape=(n,))
|
||||
|
||||
A = vals_a < 0.4
|
||||
B = vals_b < 0.6
|
||||
|
||||
p_a = A.mean()
|
||||
p_b = B.mean()
|
||||
p_a_and_b = (A & B).mean()
|
||||
p_a_or_b = (A | B).mean()
|
||||
|
||||
print(f"P(A) = {p_a:.4f}")
|
||||
print(f"P(B) = {p_b:.4f}")
|
||||
print(f"P(A ∩ B) = {p_a_and_b:.4f}")
|
||||
print(f"P(A ∪ B) 模拟值 = {p_a_or_b:.4f}")
|
||||
print(f"P(A) + P(B) - P(A∩B) = {p_a + p_b - p_a_and_b:.4f}")
|
||||
```
|
||||
|
||||
3. 演示条件概率随证据变化。模拟掷两个骰子,计算 $P(\text{和} = 7)$,然后计算 $P(\text{和} = 7 | \text{第一个骰子} = 3)$。
|
||||
```python
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
|
||||
key = jax.random.PRNGKey(1)
|
||||
n = 500_000
|
||||
k1, k2 = jax.random.split(key)
|
||||
|
||||
d1 = jax.random.randint(k1, shape=(n,), minval=1, maxval=7)
|
||||
d2 = jax.random.randint(k2, shape=(n,), minval=1, maxval=7)
|
||||
total = d1 + d2
|
||||
|
||||
# 无条件概率
|
||||
p_sum7 = (total == 7).mean()
|
||||
print(f"P(和=7) = {p_sum7:.4f} (精确值: {6/36:.4f})")
|
||||
|
||||
# 条件于第一个骰子 = 3
|
||||
mask = d1 == 3
|
||||
p_sum7_given_d1_3 = (total[mask] == 7).mean()
|
||||
print(f"P(和=7 | d1=3) = {p_sum7_given_d1_3:.4f} (精确值: {1/6:.4f})")
|
||||
```
|
||||
|
||||
4. 将贝叶斯定理实现为一个函数,并用它迭代更新信念。从硬币偏向的均匀先验开始,在观察到每次抛掷后更新。
|
||||
```python
|
||||
import jax.numpy as jnp
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def bayes_update(prior, likelihood):
|
||||
"""将先验乘以似然并归一化。"""
|
||||
posterior = prior * likelihood
|
||||
return posterior / posterior.sum()
|
||||
|
||||
# 离散化可能的偏向值
|
||||
theta = jnp.linspace(0, 1, 200)
|
||||
prior = jnp.ones_like(theta) # 均匀先验
|
||||
prior = prior / prior.sum()
|
||||
|
||||
# 观测到的抛掷结果:1=正面,0=反面
|
||||
flips = [1, 1, 0, 1, 1, 1, 0, 1, 0, 1]
|
||||
|
||||
plt.figure(figsize=(10, 5))
|
||||
plt.plot(theta, prior, "--", color="#999", label="先验")
|
||||
|
||||
for i, flip in enumerate(flips):
|
||||
likelihood = theta if flip == 1 else (1 - theta)
|
||||
prior = bayes_update(prior, likelihood)
|
||||
if i in [0, 2, 4, 9]:
|
||||
plt.plot(theta, prior, label=f"经过 {i+1} 次抛掷后", linewidth=2)
|
||||
|
||||
plt.xlabel("硬币偏向 θ")
|
||||
plt.ylabel("信念(归一化)")
|
||||
plt.title("贝叶斯更新:关于硬币偏向的信念")
|
||||
plt.legend()
|
||||
plt.grid(alpha=0.3)
|
||||
plt.show()
|
||||
```
|
||||
@@ -0,0 +1,238 @@
|
||||
# 概率分布
|
||||
|
||||
*概率分布描述了随机结果如何在可能取值上分布。本文档整理了关键的离散和连续分布:伯努利分布、二项分布、泊松分布、高斯分布、指数分布、贝塔分布等,给出了各自的公式、直观理解及其在机器学习中的应用(损失函数、先验、噪声模型)。*
|
||||
|
||||
- 在第4章中,我们介绍了随机变量、PMF、PDF和CDF。本章列出你在机器学习和统计学中最常遇到的重要概率分布,给出每个分布的直观理解、公式、均值和方差。
|
||||
|
||||
- 三种核心函数的快速回顾(完整定义见第4章):
|
||||
- **PMF** $P(X = x)$:给出每个离散结果的概率。即条形图中每个条形的高度。
|
||||
- **PDF** $f(x)$:给出连续变量在每个点上的密度。两点之间曲线下的面积即为概率。
|
||||
- **CDF** $F(x) = P(X \le x)$:累积到 $x$ 为止的概率。取值范围始终从0到1且单调不减。
|
||||
|
||||
- 分布的**支撑集**是指PMF或PDF取正值的集合。对掷骰子而言,支撑集为 $\{1,2,3,4,5,6\}$。对正态分布而言,支撑集为全体实数 $(-\infty, \infty)$。
|
||||
|
||||
- 分布清晰地分为两个家族:离散分布(结果可数,使用PMF)和连续分布(结果不可数,使用PDF)。
|
||||
|
||||
- **伯努利分布**:最简单的分布。单次试验有两种结果:成功(1)的概率为 $p$,失败(0)的概率为 $1-p$。
|
||||
|
||||
$$P(X = x) = p^x (1 - p)^{1-x}, \quad x \in \{0, 1\}$$
|
||||
|
||||
- 均值:$E[X] = p$。方差:$\text{Var}(X) = p(1-p)$。
|
||||
|
||||
- 每一次抛硬币、每一个是/否分类、每一个二元结果都是伯努利试验。在机器学习中,sigmoid函数的输出正是伯努利分布的参数 $p$。
|
||||
|
||||
- **二项分布**:计算 $n$ 次独立伯努利试验中成功的次数,每次试验的成功概率 $p$ 相同。
|
||||
|
||||
$$P(X = k) = \binom{n}{k} p^k (1-p)^{n-k}, \quad k = 0, 1, \ldots, n$$
|
||||
|
||||
- 二项式系数 $\binom{n}{k}$(见文件01)计算了 $k$ 次成功在 $n$ 次试验中的排列方式数量。
|
||||
|
||||
- 均值:$E[X] = np$。方差:$\text{Var}(X) = np(1-p)$。
|
||||
|
||||

|
||||
|
||||
- 示例:抛一枚有偏硬币($p = 0.7$)八次。恰好得到6次正面的概率为 $\binom{8}{6}(0.7)^6(0.3)^2 = 28 \times 0.1176 \times 0.09 \approx 0.296$。
|
||||
|
||||
- **泊松分布**:在固定的时间或空间区间内,以已知的平均速率 $\lambda$ 计算事件发生的次数。适用于事件稀少且相互独立的情形。
|
||||
|
||||
$$P(X = k) = \frac{\lambda^k e^{-\lambda}}{k!}, \quad k = 0, 1, 2, \ldots$$
|
||||
|
||||
- 均值:$E[X] = \lambda$。方差:$\text{Var}(X) = \lambda$。均值等于方差是其标志性特征。
|
||||
|
||||
- 示例:每小时收到的邮件数($\lambda = 5$)、每页的错别字数、每秒的服务器请求数。在机器学习中,泊松回归用于建模计数数据,而线性模型可能会预测出负的计数值。
|
||||
|
||||
- 当 $n \to \infty$ 且 $p \to 0$,且 $np = \lambda$ 保持不变时,二项分布 Binomial$(n,p)$ 收敛于泊松分布 Poisson$(\lambda)$。这就是泊松分布适用于大总体中稀有事件的原因。
|
||||
|
||||
- **几何分布**:计算直到首次成功所需的试验次数。"我要抛多少次硬币才能第一次得到正面?"
|
||||
|
||||
$$P(X = k) = (1-p)^{k-1} p, \quad k = 1, 2, 3, \ldots$$
|
||||
|
||||
- 均值:$E[X] = 1/p$。方差:$\text{Var}(X) = (1-p)/p^2$。
|
||||
|
||||
- 几何分布具有**无记忆性**:再等待 $k$ 次试验才成功的概率与你已经等待了多少次试验无关。这使得它在离散分布中非常特殊。
|
||||
|
||||
- **负二项分布**:推广了几何分布,计算直到第 $r$ 次成功所需的试验次数(几何分布是 $r=1$ 的特殊情形)。
|
||||
|
||||
$$P(X = k) = \binom{k-1}{r-1} p^r (1-p)^{k-r}, \quad k = r, r+1, r+2, \ldots$$
|
||||
|
||||
- 均值:$E[X] = r/p$。方差:$\text{Var}(X) = r(1-p)/p^2$。
|
||||
|
||||
- 负二项分布在实践中也用于建模过度离散的计数数据(方差超过均值的情形),这是泊松分布无法处理的。
|
||||
|
||||
- 接下来我们进入连续分布。
|
||||
|
||||
- **均匀分布**:区间 $[a, b]$ 内的所有值等可能。其PDF是一个平坦的矩形。
|
||||
|
||||
$$f(x) = \frac{1}{b - a}, \quad a \le x \le b$$
|
||||
|
||||
- 均值:$E[X] = \frac{a+b}{2}$。方差:$\text{Var}(X) = \frac{(b-a)^2}{12}$。
|
||||
|
||||
- 随机数生成器以生成均匀分布 Uniform(0,1) 样本为起点。其他分布通过对这些均匀样本进行变换得到。
|
||||
|
||||
- **正态(高斯)分布**:统计学中最重要的分布。它由中心极限定理(见第4章)自然导出:大量独立随机变量的平均值趋于正态分布,无论原始分布是什么。
|
||||
|
||||
$$f(x) = \frac{1}{\sigma\sqrt{2\pi}} \exp\!\left(-\frac{(x - \mu)^2}{2\sigma^2}\right)$$
|
||||
|
||||
- 均值:$E[X] = \mu$。方差:$\text{Var}(X) = \sigma^2$。
|
||||
|
||||
- **标准正态分布**的 $\mu = 0$ 且 $\sigma = 1$。任意正态变量 $X$ 可通过 $Z = (X - \mu)/\sigma$ 标准化为标准正态变量 $Z$。
|
||||
|
||||

|
||||
|
||||
- **经验法则**(68-95-99.7法则)指出:
|
||||
- 约68%的数据落在均值 $\pm 1\sigma$ 范围内
|
||||
- 约95%的数据落在 $\pm 2\sigma$ 范围内
|
||||
- 约99.7%的数据落在 $\pm 3\sigma$ 范围内
|
||||
|
||||
- 在机器学习中,正态分布无处不在:权重初始化、数据增强中的噪声、MSE损失背后的假设(其隐含假设高斯误差)、以及变分自编码器中的重参数化技巧。
|
||||
|
||||
- **指数分布**:模拟泊松过程中事件之间的时间间隔。如果事件以速率 $\lambda$ 到达,则它们之间的等待时间服从指数分布 Exponential$(\lambda)$。
|
||||
|
||||
$$f(x) = \lambda e^{-\lambda x}, \quad x \ge 0$$
|
||||
|
||||
- 均值:$E[X] = 1/\lambda$。方差:$\text{Var}(X) = 1/\lambda^2$。
|
||||
|
||||
- 与离散变量中的几何分布类似,指数分布也具有**无记忆性**:$P(X > s + t | X > s) = P(X > t)$。再等待 $t$ 个时间单位的概率与你已经等待了多长时间无关。
|
||||
|
||||
- **伽马分布**:推广了指数分布。它模拟泊松过程中第 $\alpha$ 个事件发生的时间(指数分布是 $\alpha = 1$ 的特殊情形)。
|
||||
|
||||
$$f(x) = \frac{\beta^\alpha}{\Gamma(\alpha)} x^{\alpha - 1} e^{-\beta x}, \quad x > 0$$
|
||||
|
||||
- 这里 $\alpha$(形状参数)控制形状,$\beta$(速率参数)控制尺度。$\Gamma(\alpha)$ 是伽马函数,它将阶乘推广到实数:对正整数 $n$ 有 $\Gamma(n) = (n-1)!$。
|
||||
|
||||
- 均值:$E[X] = \alpha/\beta$。方差:$\text{Var}(X) = \alpha/\beta^2$。
|
||||
|
||||
- **贝塔分布**:定义在区间 $[0, 1]$ 上,非常适合对概率、比例和比率进行建模。
|
||||
|
||||
$$f(x) = \frac{x^{\alpha - 1}(1 - x)^{\beta - 1}}{B(\alpha, \beta)}, \quad 0 \le x \le 1$$
|
||||
|
||||
- 分母 $B(\alpha, \beta) = \frac{\Gamma(\alpha)\Gamma(\beta)}{\Gamma(\alpha + \beta)}$ 是贝塔函数,起到归一化常数的作用。
|
||||
|
||||
- 均值:$E[X] = \frac{\alpha}{\alpha + \beta}$。方差:$\text{Var}(X) = \frac{\alpha\beta}{(\alpha+\beta)^2(\alpha+\beta+1)}$。
|
||||
|
||||
- 贝塔分布是伯努利和二项似然函数的共轭先验。这意味着如果先验是贝塔分布且数据服从伯努利分布,则后验也是贝塔分布,这使得贝叶斯更新在解析上易于处理。我们将在文件04中使用这一性质。
|
||||
|
||||

|
||||
|
||||
- **卡方分布**($\chi^2$):如果你取 $k$ 个独立的标准正态随机变量并求其平方和,结果服从自由度为 $k$ 的 $\chi^2$ 分布。
|
||||
|
||||
$$f(x) = \frac{1}{2^{k/2}\Gamma(k/2)} x^{k/2 - 1} e^{-x/2}, \quad x > 0$$
|
||||
|
||||
- 均值:$E[X] = k$。方差:$\text{Var}(X) = 2k$。
|
||||
|
||||
- $\chi^2$ 分布实际上是伽马分布的特殊情形,其中 $\alpha = k/2$ 且 $\beta = 1/2$。它出现在假设检验(第4章中的卡方检验)、拟合优度检验以及方差置信区间的计算中。
|
||||
|
||||
- **学生t分布**:形状类似于正态分布但尾部更重。当你使用小样本且总体方差未知时,对正态分布总体的均值进行估计时就会出现t分布。
|
||||
|
||||
$$f(x) = \frac{\Gamma\!\left(\frac{\nu+1}{2}\right)}{\sqrt{\nu\pi}\,\Gamma\!\left(\frac{\nu}{2}\right)} \left(1 + \frac{x^2}{\nu}\right)^{-(\nu+1)/2}$$
|
||||
|
||||
- 参数 $\nu$(自由度)。当 $\nu \to \infty$ 时,t分布收敛于标准正态分布。当 $\nu$ 较小时,更重的尾部赋予极端值更高的概率,反映了小样本带来的额外不确定性。
|
||||
|
||||
- 均值:$E[X] = 0$(当 $\nu > 1$ 时)。方差:$\text{Var}(X) = \frac{\nu}{\nu - 2}$(当 $\nu > 2$ 时)。
|
||||
|
||||
- t分布用于t检验(第4章),并出现在贝叶斯推断中,作为在积分消去未知方差时的边缘分布。
|
||||
|
||||
- 关键分布总结:
|
||||
|
||||
| 分布 | 类型 | 支撑集 | 均值 | 方差 |
|
||||
|---|---|---|---|---|
|
||||
| Bernoulli$(p)$ | 离散 | $\{0,1\}$ | $p$ | $p(1-p)$ |
|
||||
| Binomial$(n,p)$ | 离散 | $\{0,\ldots,n\}$ | $np$ | $np(1-p)$ |
|
||||
| Poisson$(\lambda)$ | 离散 | $\{0,1,2,\ldots\}$ | $\lambda$ | $\lambda$ |
|
||||
| Geometric$(p)$ | 离散 | $\{1,2,3,\ldots\}$ | $1/p$ | $(1-p)/p^2$ |
|
||||
| Uniform$(a,b)$ | 连续 | $[a,b]$ | $(a+b)/2$ | $(b-a)^2/12$ |
|
||||
| Normal$(\mu,\sigma^2)$ | 连续 | $(-\infty,\infty)$ | $\mu$ | $\sigma^2$ |
|
||||
| Exponential$(\lambda)$ | 连续 | $[0,\infty)$ | $1/\lambda$ | $1/\lambda^2$ |
|
||||
| Gamma$(\alpha,\beta)$ | 连续 | $(0,\infty)$ | $\alpha/\beta$ | $\alpha/\beta^2$ |
|
||||
| Beta$(\alpha,\beta)$ | 连续 | $[0,1]$ | $\alpha/(\alpha+\beta)$ | 见上文 |
|
||||
| $\chi^2(k)$ | 连续 | $(0,\infty)$ | $k$ | $2k$ |
|
||||
| Student's $t(\nu)$ | 连续 | $(-\infty,\infty)$ | $0$ | $\nu/(\nu-2)$ |
|
||||
|
||||
## 编程练习(使用CoLab或笔记本)
|
||||
|
||||
1. 绘制 $n=20$ 时二项分布PMF在不同 $p$ 取值下的图像。观察形状如何从左偏变为对称再变为右偏。
|
||||
```python
|
||||
import jax.numpy as jnp
|
||||
import matplotlib.pyplot as plt
|
||||
from math import comb
|
||||
|
||||
n = 20
|
||||
ks = jnp.arange(0, n + 1)
|
||||
|
||||
fig, axes = plt.subplots(1, 3, figsize=(12, 4), sharey=True)
|
||||
for ax, p, color in zip(axes, [0.2, 0.5, 0.8], ["#e74c3c", "#3498db", "#27ae60"]):
|
||||
pmf = jnp.array([comb(n, int(k)) * p**k * (1-p)**(n-k) for k in ks])
|
||||
ax.bar(ks, pmf, color=color, alpha=0.7)
|
||||
ax.set_title(f"Binomial(n={n}, p={p})")
|
||||
ax.set_xlabel("k")
|
||||
axes[0].set_ylabel("P(X = k)")
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
```
|
||||
|
||||
2. 验证泊松分布对二项分布的近似。设 $n = 1000$,$p = 0.003$,比较二项分布 Binomial$(n, p)$ 和泊松分布 Poisson$(\lambda = np)$。
|
||||
```python
|
||||
import jax.numpy as jnp
|
||||
import matplotlib.pyplot as plt
|
||||
from math import comb, factorial, exp
|
||||
|
||||
n, p = 1000, 0.003
|
||||
lam = n * p
|
||||
ks = jnp.arange(0, 15)
|
||||
|
||||
binom_pmf = jnp.array([comb(n, int(k)) * p**k * (1-p)**(n-k) for k in ks])
|
||||
poisson_pmf = jnp.array([lam**k * exp(-lam) / factorial(int(k)) for k in ks])
|
||||
|
||||
plt.figure(figsize=(8, 4))
|
||||
plt.bar(ks - 0.15, binom_pmf, width=0.3, color="#3498db", alpha=0.7, label=f"Binomial({n},{p})")
|
||||
plt.bar(ks + 0.15, poisson_pmf, width=0.3, color="#e74c3c", alpha=0.7, label=f"Poisson({lam})")
|
||||
plt.xlabel("k")
|
||||
plt.ylabel("P(X = k)")
|
||||
plt.title("泊松分布对二项分布的近似")
|
||||
plt.legend()
|
||||
plt.show()
|
||||
```
|
||||
|
||||
3. 从正态分布中采样并验证经验法则。计算落在1、2和3个标准差内的样本比例。
|
||||
```python
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
|
||||
key = jax.random.PRNGKey(42)
|
||||
mu, sigma = 5.0, 2.0
|
||||
samples = mu + sigma * jax.random.normal(key, shape=(100_000,))
|
||||
|
||||
for k in [1, 2, 3]:
|
||||
within = jnp.abs(samples - mu) <= k * sigma
|
||||
print(f"Within {k}σ: {within.mean():.4f} (expected: {[0.6827, 0.9545, 0.9973][k-1]:.4f})")
|
||||
```
|
||||
|
||||
4. 通过改变 $\alpha$ 和 $\beta$ 探索贝塔分布。绘制几种形状,观察分布如何从均匀变为偏斜再变为集中。
|
||||
```python
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
x = jnp.linspace(0.01, 0.99, 200)
|
||||
|
||||
def beta_pdf(x, a, b):
|
||||
# 未归一化,用于形状比较
|
||||
return x**(a-1) * (1-x)**(b-1)
|
||||
|
||||
plt.figure(figsize=(10, 5))
|
||||
params = [(1,1,"均匀"), (2,5,"左偏"), (5,2,"右偏"),
|
||||
(5,5,"对称"), (0.5,0.5,"U形")]
|
||||
colors = ["#999", "#e74c3c", "#3498db", "#27ae60", "#9b59b6"]
|
||||
|
||||
for (a, b, label), color in zip(params, colors):
|
||||
y = beta_pdf(x, a, b)
|
||||
y = y / jnp.trapezoid(y, x) # 归一化
|
||||
plt.plot(x, y, label=f"α={a}, β={b} ({label})", color=color, linewidth=2)
|
||||
|
||||
plt.xlabel("x")
|
||||
plt.ylabel("密度")
|
||||
plt.title("贝塔分布形状")
|
||||
plt.legend()
|
||||
plt.grid(alpha=0.3)
|
||||
plt.show()
|
||||
```
|
||||
@@ -0,0 +1,292 @@
|
||||
# 贝叶斯方法与序列模型
|
||||
|
||||
*贝叶斯方法将先验信念与观测数据相结合,生成模型参数的后验分布。本文涵盖最大似然估计、最大后验估计、共轭先验、贝叶斯推断、隐马尔可夫模型和EM算法——这些技术是垃圾邮件过滤器、语言模型和不确定性感知机器学习的基础。*
|
||||
|
||||
- 到目前为止,我们介绍了各种分布以及如何计算概率。现在我们来处理机器学习的核心问题:给定观测数据,如何找到模型的最佳参数?
|
||||
|
||||
- **最大似然估计 (MLE)** 直接回答了这个问题:选择使观测数据概率最大的参数值。
|
||||
|
||||
- 形式上,给定数据 $D = \{x_1, x_2, \ldots, x_n\}$ 和带有参数 $\theta$ 的模型,**似然函数**为:
|
||||
|
||||
$$L(\theta | D) = P(D | \theta) = \prod_{i=1}^{n} P(x_i | \theta)$$
|
||||
|
||||
- 乘积假设数据点独立同分布(i.i.d.)。MLE估计量为:
|
||||
|
||||
$$\hat{\theta}_{\text{MLE}} = \arg\max_\theta L(\theta | D)$$
|
||||
|
||||
- 实践中我们最大化**对数似然**,因为对数将乘积转化为求和,并防止数值下溢:
|
||||
|
||||
$$\ell(\theta) = \log L(\theta | D) = \sum_{i=1}^{n} \log P(x_i | \theta)$$
|
||||
|
||||
- 由于 $\log$ 是单调递增函数,使得 $\ell(\theta)$ 最大的 $\theta$ 也同样使得 $L(\theta)$ 最大。
|
||||
|
||||
- **抛硬币示例**:你抛一枚硬币10次,得到7次正面。硬币偏置 $p$(正面概率)的MLE估计是多少?
|
||||
|
||||
- 每次抛掷服从 Bernoulli($p$),因此10次抛掷中出现7次正面的似然为:
|
||||
|
||||
$$L(p) = \binom{10}{7} p^7 (1-p)^3$$
|
||||
|
||||
- 取对数并求导:$\frac{d\ell}{dp} = \frac{7}{p} - \frac{3}{1-p} = 0$,解得 $\hat{p}_{\text{MLE}} = 7/10 = 0.7$。
|
||||
|
||||
- MLE直观且简单。如果10次抛掷中得到7次正面,最可能的偏置是0.7。但注意一个问题:如果10次抛掷中得到10次正面,MLE会得出 $\hat{p} = 1$,意味着硬币将永远正面朝上。仅凭10次观测就得出这样的结论似乎过于自信。
|
||||
|
||||
- **最大后验估计 (MAP)** 通过加入先验信念来修复这个问题。MAP不是仅最大化似然,而是最大化后验:
|
||||
|
||||
$$\hat{\theta}_{\text{MAP}} = \arg\max_\theta P(\theta | D) = \arg\max_\theta P(D | \theta) \cdot P(\theta)$$
|
||||
|
||||
- 我们省略了分母 $P(D)$,因为它不依赖于 $\theta$,不影响argmax的结果。
|
||||
|
||||
- 先验 $P(\theta)$ 编码了我们在看到数据之前对 $\theta$ 的信念。如果我们使用 Beta(2, 2) 先验来表示硬币偏置(表达"硬币大致是公平的"这一温和信念),MAP估计就不再仅仅是正面的比例,而是被拉向0.5。
|
||||
|
||||

|
||||
|
||||
- 使用 Beta($\alpha$, $\beta$) 先验,观测到 $h$ 次正面和 $t$ 次反面后,后验为 Beta($\alpha + h$, $\beta + t$),MAP估计为:
|
||||
|
||||
$$\hat{p}_{\text{MAP}} = \frac{\alpha + h - 1}{\alpha + \beta + h + t - 2}$$
|
||||
|
||||
- 对于我们的示例,Beta(2,2)先验,7次正面,3次反面:$\hat{p}_{\text{MAP}} = \frac{2 + 7 - 1}{2 + 2 + 10 - 2} = \frac{8}{12} = 0.667$。
|
||||
|
||||
- 注意MAP估计(0.667)相比MLE(0.7)如何被拉向0.5。先验起到了正则化的作用。在机器学习中,L2正则化(权重衰减)完全等价于在权重上使用高斯先验的MAP估计。
|
||||
|
||||
- **完整的贝叶斯推断**比MAP更进一步。它不是寻找单一的最佳 $\theta$,而是维护整个后验分布 $P(\theta | D)$。这不仅给你一个点估计,还给出了不确定性的度量。
|
||||
|
||||
- 对于具有Beta(2,2)先验和7次正面、3次反面的偏置硬币,完整的后验是 Beta(9, 5)。该分布的均值为 $9/14 \approx 0.643$,其弥散程度告诉我们置信度的高低。数据越多,后验越窄。
|
||||
|
||||
- 三种方法形成了一个谱系:
|
||||
- **MLE**:无先验,仅依赖数据。速度快,但数据少时可能过拟合。
|
||||
- **MAP**:带先验正则化的点估计。增加鲁棒性。
|
||||
- **完整贝叶斯**:完整的后验分布。信息量最大,但通常计算成本高。
|
||||
|
||||
- **马尔可夫链**对序列进行建模,其中下一状态仅依赖于当前状态,而不依赖于历史。这种"无记忆性"称为**马尔可夫性**:
|
||||
|
||||
$$P(X_{t+1} | X_t, X_{t-1}, \ldots, X_1) = P(X_{t+1} | X_t)$$
|
||||
|
||||
- 以天气为例。明天的天气取决于今天的天气,但不取决于上周的天气(这是一个简化,但出奇地有用)。
|
||||
|
||||
- 马尔可夫链具有有限个**状态**和一个**转移矩阵** $T$,其中元素 $T_{ij}$ 表示从状态 $i$ 转移到状态 $j$ 的概率。每一行之和为1。
|
||||
|
||||

|
||||
|
||||
- 对于上图的天气示例,转移矩阵为:
|
||||
|
||||
```math
|
||||
T = \begin{pmatrix} 0.3 & 0.4 & 0.3 \\ 0.2 & 0.5 & 0.3 \\ 0.4 & 0.3 & 0.3 \end{pmatrix}
|
||||
```
|
||||
|
||||
- 如果今天是雨天(状态向量 $\mathbf{s}_0 = [1, 0, 0]$),明天天气的概率分布为 $\mathbf{s}_1 = \mathbf{s}_0 T = [0.3, 0.4, 0.3]$。两天后:$\mathbf{s}_2 = \mathbf{s}_0 T^2$。这使用了第一章中的矩阵乘法。
|
||||
|
||||
- 许多马尔可夫链会收敛到一个**平稳分布** $\pi$,满足 $\pi T = \pi$。无论从哪里出发,经过足够多的步数后,链会收敛到 $\pi$。这一性质是MCMC(马尔可夫链蒙特卡罗)的基础,MCMC是贝叶斯机器学习中广泛使用的采样技术。
|
||||
|
||||
- **隐马尔可夫模型 (HMM)** 通过增加一层间接性来扩展马尔可夫链。真实状态是隐藏的(不可观测的),每个时间步隐藏状态会发出一个可观测的信号。
|
||||
|
||||

|
||||
|
||||
- HMM 有三个组成部分:
|
||||
- **转移概率** $P(z_t | z_{t-1})$:隐藏状态如何演化(马尔可夫链)
|
||||
- **发射概率** $P(x_t | z_t)$:每个隐藏状态产生什么可观测输出
|
||||
- **初始分布** $P(z_1)$:起始隐藏状态的概率
|
||||
|
||||
- **雨伞示例**:假设你不能直接看到天气,但可以观察到你的朋友是否带伞。隐藏状态为 {雨天, 晴天},观测为 {带伞, 不带伞}。
|
||||
|
||||
- 转移概率:$P(\text{雨天}|\text{雨天}) = 0.7$,$P(\text{晴天}|\text{雨天}) = 0.3$,$P(\text{雨天}|\text{晴天}) = 0.4$,$P(\text{晴天}|\text{晴天}) = 0.6$。
|
||||
|
||||
- 发射概率:$P(\text{带伞}|\text{雨天}) = 0.9$,$P(\text{不带伞}|\text{雨天}) = 0.1$,$P(\text{带伞}|\text{晴天}) = 0.2$,$P(\text{不带伞}|\text{晴天}) = 0.8$。
|
||||
|
||||
- HMM 的关键问题有:
|
||||
- **解码**:给定观测,最可能的隐藏状态序列是什么?由**维特比算法**求解。
|
||||
- **评估**:观测序列的概率是多少?由**前向算法**求解。
|
||||
- **学习**:给定观测,最佳模型参数是什么?由**Baum-Welch算法**求解(期望最大化算法的一个实例)。
|
||||
|
||||
- **维特比演算**:假设你观测到 [带伞, 带伞, 不带伞],想找到最可能的天气序列。
|
||||
|
||||
- 从初始概率开始。假设 $P(R) = 0.5$,$P(S) = 0.5$。
|
||||
|
||||
- **第1天**(观测到带伞):
|
||||
- $V_1(R) = P(R) \cdot P(U|R) = 0.5 \times 0.9 = 0.45$
|
||||
- $V_1(S) = P(S) \cdot P(U|S) = 0.5 \times 0.2 = 0.10$
|
||||
|
||||
- **第2天**(观测到带伞):
|
||||
- $V_2(R) = \max(V_1(R) \cdot P(R|R), V_1(S) \cdot P(R|S)) \cdot P(U|R)$
|
||||
- $= \max(0.45 \times 0.7, 0.10 \times 0.4) \times 0.9 = \max(0.315, 0.04) \times 0.9 = 0.2835$
|
||||
- $V_2(S) = \max(V_1(R) \cdot P(S|R), V_1(S) \cdot P(S|S)) \cdot P(U|S)$
|
||||
- $= \max(0.45 \times 0.3, 0.10 \times 0.6) \times 0.2 = \max(0.135, 0.06) \times 0.2 = 0.027$
|
||||
|
||||
- **第3天**(观测到不带伞):
|
||||
- $V_3(R) = \max(0.2835 \times 0.7, 0.027 \times 0.4) \times 0.1 = 0.1985 \times 0.1 = 0.01985$
|
||||
- $V_3(S) = \max(0.2835 \times 0.3, 0.027 \times 0.6) \times 0.8 = 0.08505 \times 0.8 = 0.06804$
|
||||
|
||||
- 第3天的最大值在晴天。回溯:第3天 = 晴天(来自R),第2天 = 雨天(来自R),第1天 = 雨天。最可能的序列:**雨天, 雨天, 晴天**。
|
||||
|
||||
- **前向-后向算法**计算在给定整个观测序列条件下,每个时间步处于每个隐藏状态的概率。前向过程计算 $P(z_t, x_{1:t})$,后向过程计算 $P(x_{t+1:T} | z_t)$。两者相乘得到平滑后的状态概率。
|
||||
|
||||
- **Baum-Welch算法**在隐藏状态不可观测时从数据中学习HMM参数。它是一种期望最大化(EM)算法:E步使用前向-后向算法估计哪些隐藏状态生成了观测,M步更新转移概率和发射概率。
|
||||
|
||||
- HMM在历史上主导了语音识别(隐藏的音素状态发出声学信号)和生物信息学(隐藏的基因状态发出DNA碱基对)。虽然深度学习在很大程度上已取代了这些领域中的HMM,但隐藏状态、发射和序列推断的思想仍然是序列模型的核心。
|
||||
|
||||
- **条件随机场 (CRF)** 通过去除发射独立假设来改进HMM。在HMM中,时间 $t$ 的观测仅依赖于时间 $t$ 的隐藏状态。CRF允许位置 $t$ 的标签依赖于整个输入序列。
|
||||
|
||||
- 线性链CRF对给定输入序列 $\mathbf{x}$ 条件下标签序列 $\mathbf{y}$ 的条件概率建模:
|
||||
|
||||
$$P(\mathbf{y} | \mathbf{x}) = \frac{1}{Z(\mathbf{x})} \exp\!\left(\sum_t \left[\sum_k \lambda_k f_k(y_t, y_{t-1}, \mathbf{x}, t)\right]\right)$$
|
||||
|
||||
- 其中 $f_k$ 是特征函数(可以查看输入的任意部分),$\lambda_k$ 是学习到的权重,$Z(\mathbf{x})$ 是归一化常数。
|
||||
|
||||
- CRF是判别式模型(直接建模 $P(\mathbf{y}|\mathbf{x})$),而HMM是生成式模型(建模 $P(\mathbf{x}, \mathbf{y})$)。这一区别与逻辑回归(判别式)和朴素贝叶斯(生成式)之间的区别相同。
|
||||
|
||||
- 在现代NLP中,CRF层通常被加在神经网络之上(BiLSTM-CRF、BERT-CRF),用于命名实体识别和词性标注等需要捕捉标签依赖关系的任务。
|
||||
|
||||
## 编程练习(使用 CoLab 或 notebook)
|
||||
|
||||
1. 实现抛硬币实验的MLE和MAP。观察MAP估计如何随不同的先验和不同的数据量而变化。
|
||||
```python
|
||||
import jax.numpy as jnp
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# 数据:观测到的硬币抛掷结果
|
||||
heads, tails = 7, 3
|
||||
|
||||
# MLE
|
||||
p_mle = heads / (heads + tails)
|
||||
print(f"MLE: {p_mle:.4f}")
|
||||
|
||||
# 使用 Beta 先验的 MAP
|
||||
for alpha, beta in [(1,1), (2,2), (5,5), (10,10)]:
|
||||
p_map = (alpha + heads - 1) / (alpha + beta + heads + tails - 2)
|
||||
print(f"MAP (Beta({alpha},{beta})): {p_map:.4f}")
|
||||
|
||||
# 可视化 Beta(2,2) 先验下的后验
|
||||
theta = jnp.linspace(0.01, 0.99, 200)
|
||||
# 后验为 Beta(alpha+heads, beta+tails)
|
||||
a_post, b_post = 2 + heads, 2 + tails
|
||||
posterior = theta**(a_post-1) * (1-theta)**(b_post-1)
|
||||
posterior = posterior / jnp.trapezoid(posterior, theta)
|
||||
|
||||
plt.figure(figsize=(8, 4))
|
||||
plt.plot(theta, posterior, color="#e74c3c", linewidth=2, label=f"后验 Beta({a_post},{b_post})")
|
||||
plt.axvline(p_mle, color="#3498db", linestyle="--", label=f"MLE = {p_mle:.2f}")
|
||||
plt.axvline((a_post-1)/(a_post+b_post-2), color="#e74c3c", linestyle="--", label=f"MAP = {(a_post-1)/(a_post+b_post-2):.3f}")
|
||||
plt.xlabel("θ (硬币偏置)")
|
||||
plt.ylabel("密度")
|
||||
plt.title("7次正面、3次反面后 Beta(2,2) 先验下的后验分布")
|
||||
plt.legend()
|
||||
plt.grid(alpha=0.3)
|
||||
plt.show()
|
||||
```
|
||||
|
||||
2. 为天气模型构建一个马尔可夫链并进行模拟。分别通过模拟和求解 $\pi T = \pi$ 计算平稳分布。
|
||||
```python
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
|
||||
# 转移矩阵:R(雨天), S(晴天), C(多云)
|
||||
T = jnp.array([
|
||||
[0.3, 0.4, 0.3],
|
||||
[0.2, 0.5, 0.3],
|
||||
[0.4, 0.3, 0.3]
|
||||
])
|
||||
states = ["雨天", "晴天", "多云"]
|
||||
|
||||
# 模拟 100,000 步
|
||||
key = jax.random.PRNGKey(42)
|
||||
n_steps = 100_000
|
||||
state = 0 # 从雨天开始
|
||||
counts = jnp.zeros(3)
|
||||
|
||||
for i in range(n_steps):
|
||||
key, subkey = jax.random.split(key)
|
||||
state = jax.random.choice(subkey, 3, p=T[state])
|
||||
counts = counts.at[state].add(1)
|
||||
|
||||
sim_stationary = counts / n_steps
|
||||
print("模拟得到的平稳分布:")
|
||||
for s, p in zip(states, sim_stationary):
|
||||
print(f" {s}: {p:.4f}")
|
||||
|
||||
# 解析法:找到特征值为1的左特征向量
|
||||
eigenvalues, eigenvectors = jnp.linalg.eig(T.T)
|
||||
idx = jnp.argmin(jnp.abs(eigenvalues - 1.0))
|
||||
pi = jnp.real(eigenvectors[:, idx])
|
||||
pi = pi / pi.sum()
|
||||
print("\n解析得到的平稳分布:")
|
||||
for s, p in zip(states, pi):
|
||||
print(f" {s}: {p:.4f}")
|
||||
```
|
||||
|
||||
3. 为雨伞HMM实现维特比算法,并解码一个观测序列。
|
||||
```python
|
||||
import jax.numpy as jnp
|
||||
|
||||
# HMM 参数
|
||||
states = ["雨天", "晴天"]
|
||||
obs_names = ["带伞", "不带伞"]
|
||||
|
||||
trans = jnp.array([[0.7, 0.3], # R->R, R->S
|
||||
[0.4, 0.6]]) # S->R, S->S
|
||||
|
||||
emit = jnp.array([[0.9, 0.1], # R->带伞, R->不带伞
|
||||
[0.2, 0.8]]) # S->带伞, S->不带伞
|
||||
|
||||
init = jnp.array([0.5, 0.5])
|
||||
|
||||
# 观测:带伞=0,不带伞=1
|
||||
observations = [0, 0, 1] # 带伞, 带伞, 不带伞
|
||||
|
||||
def viterbi(obs, init, trans, emit):
|
||||
n_states = len(init)
|
||||
T = len(obs)
|
||||
V = jnp.zeros((T, n_states))
|
||||
path = jnp.zeros((T, n_states), dtype=int)
|
||||
|
||||
# 初始化
|
||||
V = V.at[0].set(init * emit[:, obs[0]])
|
||||
|
||||
# 递推
|
||||
for t in range(1, T):
|
||||
for j in range(n_states):
|
||||
probs = V[t-1] * trans[:, j]
|
||||
V = V.at[t, j].set(jnp.max(probs) * emit[j, obs[t]])
|
||||
path = path.at[t, j].set(jnp.argmax(probs))
|
||||
|
||||
# 回溯
|
||||
best = [int(jnp.argmax(V[-1]))]
|
||||
for t in range(T-1, 0, -1):
|
||||
best.insert(0, int(path[t, best[0]]))
|
||||
return best, V
|
||||
|
||||
decoded, scores = viterbi(observations, init, trans, emit)
|
||||
print("观测序列:", [obs_names[o] for o in observations])
|
||||
print("解码结果:", [states[s] for s in decoded])
|
||||
```
|
||||
|
||||
4. 可视化随着观测更多抛硬币结果,后验如何演化。从 Beta(1,1) 先验(均匀分布)开始,每次抛掷后更新后验。
|
||||
```python
|
||||
import jax
|
||||
import jax.numpy as jnp
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
theta = jnp.linspace(0.01, 0.99, 300)
|
||||
key = jax.random.PRNGKey(7)
|
||||
|
||||
# 真实偏置 = 0.65
|
||||
flips = jax.random.bernoulli(key, p=0.65, shape=(50,))
|
||||
|
||||
plt.figure(figsize=(10, 5))
|
||||
a, b = 1, 1 # Beta(1,1) = 均匀分布
|
||||
|
||||
for n_obs in [0, 1, 5, 10, 25, 50]:
|
||||
h = int(flips[:n_obs].sum())
|
||||
t = n_obs - h
|
||||
a_post = a + h
|
||||
b_post = b + t
|
||||
y = theta**(a_post-1) * (1-theta)**(b_post-1)
|
||||
y = y / jnp.trapezoid(y, theta)
|
||||
plt.plot(theta, y, linewidth=2, label=f"n={n_obs} (h={h})")
|
||||
|
||||
plt.axvline(0.65, color="black", linestyle=":", alpha=0.5, label="真实 p=0.65")
|
||||
plt.xlabel("θ")
|
||||
plt.ylabel("密度")
|
||||
plt.title("贝叶斯更新:数据越多后验越窄")
|
||||
plt.legend()
|
||||
plt.grid(alpha=0.3)
|
||||
plt.show()
|
||||
```
|
||||
@@ -0,0 +1,191 @@
|
||||
# 信息论
|
||||
|
||||
*信息论量化了信息、惊奇度以及概率分布之间的差异。本文涵盖熵、交叉熵、KL散度、互信息和自信息——这些概念是机器学习中每一个分类损失函数、VAE目标和数据压缩方案背后的理论基础。*
|
||||
|
||||
- 信息论由克劳德·香农于1948年创立,为我们提供了量化信息的数学框架。它回答了诸如此类的问题:一个事件应当让你感到多惊讶?一条消息携带了多少信息?两个概率分布之间有多大的差异?
|
||||
|
||||
- 这些问题看似抽象,但它们是机器学习损失函数、数据压缩和通信系统的基础。交叉熵损失——分类中最常见的损失函数——直接源于信息论。
|
||||
|
||||
- 从最简单的问题开始:单个事件携带了多少信息?
|
||||
|
||||
- **自信息**(surprisal,也称 self-information)衡量一个事件的惊奇程度。如果某件极有可能发生的事情真的发生了,你几乎学不到任何新信息。如果某件罕见的事情发生了,你则会获得大量信息。
|
||||
|
||||
- 如果你住在沙漠里,有人告诉你今天是大晴天,这并没有什么信息量。但如果他们告诉你正在下雪,那信息量就极其丰富。自信息将这种直觉形式化:
|
||||
|
||||
$$I(x) = \log_2 \frac{1}{p(x)} = -\log_2 p(x)$$
|
||||
|
||||
- 使用 $\log_2$ 时,单位是**比特**。一枚公平的硬币抛掷的自信息为 $-\log_2(0.5) = 1$ 比特。一个概率为 $1/8$ 的事件具有 $ \log_2(8) = 3$ 比特的自信息。
|
||||
|
||||
- 为什么用对数而不是简单的 $1/p$?三个原因:
|
||||
- 必然事件($p = 1$)应给出零信息:$\log(1) = 0$ 但 $1/1 = 1$。
|
||||
- 独立事件的信息应该是可加的:$\log(1/p_1 p_2) = \log(1/p_1) + \log(1/p_2)$。
|
||||
- 我们需要一个平滑、性质良好的函数。$1/p$ 会爆炸;$\log(1/p)$ 则平缓增长。
|
||||
|
||||
- **熵**是自信息的期望值,即从一个分布中每次采样获得的平均信息量。它衡量该分布的不确定性或"不可预测性":
|
||||
|
||||
$$H(X) = E[I(X)] = -\sum_{x} p(x) \log_2 p(x)$$
|
||||
|
||||

|
||||
|
||||
- 一枚公平硬币的熵为 $H = -0.5\log_2(0.5) - 0.5\log_2(0.5) = 1$ 比特。不确定性最大。
|
||||
|
||||
- 一枚偏倚硬币,$p = 0.9$,其熵为 $H = -0.9\log_2(0.9) - 0.1\log_2(0.1) \approx 0.469$ 比特。不太确定,因此熵更小。
|
||||
|
||||
- 一个确定性事件($p = 1$)的熵为 $H = 0$。完全没有不确定性。
|
||||
|
||||
- 当所有结果等可能时,熵达到最大。对于 $n$ 个等可能结果,$H = \log_2 n$。一颗公平骰子的熵为 $\log_2 6 \approx 2.585$ 比特。
|
||||
|
||||
- 熵的实际意义在于**压缩**。香农的源编码定理指出,如果不丢失信息,你无法将数据压缩到低于其熵率。一幅每个像素都等可能的图像(最大熵)无法压缩。一幅几乎全是白色的图像(低熵)则可以很好地压缩。
|
||||
|
||||
- 快速感受一下数量级:一个灰度像素(256 个值)的最大熵为 8 比特。一张 1080p 的灰度图像最多有 $1920 \times 1080 \times 8 \approx 1660$ 万比特。真实图像的熵要低得多,因为相邻像素是相关的——这正是 JPEG 压缩能够工作的原因。
|
||||
|
||||
- 对于连续随机变量,离散求和变为积分。**微分熵**定义为:
|
||||
|
||||
$$h(X) = -\int_{-\infty}^{\infty} f(x) \log f(x)\, dx$$
|
||||
|
||||
- 方差为 $\sigma^2$ 的高斯分布的微分熵为 $h = \frac{1}{2}\log_2(2\pi e \sigma^2)$。在所有具有相同方差的分布中,高斯分布具有最大熵。这也是高斯分布在建模中如此常见的原因之一:它在指定均值和方差之外做出了最少的假设。
|
||||
|
||||
- **互信息**衡量知道一个变量能告诉你关于另一个变量的多少信息。它是观察到 $Y$ 后 $X$ 不确定性的减少量:
|
||||
|
||||
$$I(X; Y) = H(X) - H(X|Y) = H(Y) - H(Y|X)$$
|
||||
|
||||
- 等价形式:
|
||||
|
||||
$$I(X; Y) = \sum_{x,y} p(x,y) \log_2 \frac{p(x,y)}{p(x) p(y)}$$
|
||||
|
||||
- 如果 $X$ 和 $Y$ 独立,则 $p(x,y) = p(x)p(y)$,互信息为零。它们依赖程度越高,互信息就越大。
|
||||
|
||||
- 在机器学习中,互信息用于特征选择(挑选与目标具有高 MI 的特征)、信息瓶颈方法以及聚类质量评估。
|
||||
|
||||
- **交叉熵**衡量使用针对分布 $q$ 优化的编码方案来编码来自分布 $p$ 的事件所需的平均比特数:
|
||||
|
||||
$$H(p, q) = -\sum_{x} p(x) \log_2 q(x)$$
|
||||
|
||||
- 如果 $q$ 与 $p$ 完全匹配,则交叉熵等于熵:$H(p, p) = H(p)$。如果 $q$ 是一个糟糕的近似,交叉熵就会更高。"额外"的比特来自这种不匹配。
|
||||
|
||||
- 这正是交叉熵成为机器学习中分类标准损失函数的原因。真实标签定义了 $p$(一个 one-hot 分布),模型的预测概率定义了 $q$。最小化交叉熵推动 $q$ 趋近于 $p$:
|
||||
|
||||
$$\mathcal{L} = -\sum_{c} y_c \log \hat{y}_c$$
|
||||
|
||||
- 对于单个样本,若真实类别为 $c$,上式简化为 $\mathcal{L} = -\log \hat{y}_c$。该损失就是模型预测下真实类别的自信息。如果模型对正确类别赋予高概率,则损失较低。
|
||||
|
||||
- **KL 散度**(Kullback-Leibler 散度,也称相对熵)衡量一个分布与另一个分布的差异程度:
|
||||
|
||||
$$D_{\text{KL}}(p \| q) = \sum_{x} p(x) \log \frac{p(x)}{q(x)} = H(p, q) - H(p)$$
|
||||
|
||||
- KL 散度是"使用分布 $q$ 而非真实分布 $p$ 的额外代价"。它总是非负的($D_{\text{KL}} \ge 0$),且仅在 $p = q$ 时为零。
|
||||
|
||||

|
||||
|
||||
- KL 散度不是对称的:$D_{\text{KL}}(p \| q) \ne D_{\text{KL}}(q \| p)$。这种不对称性很重要。$D_{\text{KL}}(p \| q)$ 惩罚 $q$ 在 $p$ 具有高概率处放置低概率(因为 $\log(p/q)$ 会趋于无穷大)。$D_{\text{KL}}(q \| p)$ 则惩罚相反的情况。
|
||||
|
||||
- 这种不对称性导致了两种近似风格:
|
||||
- 最小化 $D_{\text{KL}}(p \| q)$ 产生**矩匹配**行为:$q$ 覆盖 $p$ 的所有模态,但可能过于分散。
|
||||
- 最小化 $D_{\text{KL}}(q \| p)$ 产生**模式寻找**行为:$q$ 集中于 $p$ 的某一个模态,但可能错过其他模态。变分推断使用的正是这一种。
|
||||
|
||||
- 由于 $H(p)$ 相对于模型是常数,最小化交叉熵 $H(p, q)$ 等价于最小化 $D_{\text{KL}}(p \| q)$。这就是为什么我们可以使用交叉熵损失,同时知道我们也在最小化真实分布与预测分布之间的 KL 散度。
|
||||
|
||||
- KL 散度在**贝叶斯更新**中扮演着核心角色。后验 $P(\theta | D)$ 是在 KL 散度意义上与先验 $P(\theta)$ 最接近且与观测数据一致的分布。每一次新的观测都会更新后验,减少关于 $\theta$ 的不确定性。
|
||||
|
||||
- 在变分自编码器(VAE)中,损失函数包含两项:重构损失(交叉熵)和一个 KL 散度项,后者对潜在空间进行正则化,使其保持接近标准正态分布。
|
||||
|
||||
- 将所有概念联系起来:熵告诉你一个分布内在的不确定性,交叉熵告诉你的模型对现实的近似程度,而 KL 散度则告诉你两者之间的差距。这三个量构成了现代机器学习优化的基石。
|
||||
|
||||
## 编程练习(使用 CoLab 或 notebook)
|
||||
|
||||
1. 计算各种分布的熵,并验证在给定结果数量下,均匀分布的熵最大。
|
||||
```python
|
||||
import jax.numpy as jnp
|
||||
|
||||
def entropy(p):
|
||||
"""以比特为单位计算熵。过滤掉概率为零的事件。"""
|
||||
p = p[p > 0]
|
||||
return -jnp.sum(p * jnp.log2(p))
|
||||
|
||||
# 公平骰子
|
||||
fair = jnp.ones(6) / 6
|
||||
print(f"公平骰子熵: {entropy(fair):.4f} 比特 (最大 = log2(6) = {jnp.log2(6.):.4f})")
|
||||
|
||||
# 灌铅骰子
|
||||
loaded = jnp.array([0.1, 0.1, 0.1, 0.1, 0.1, 0.5])
|
||||
print(f"灌铅骰子熵: {entropy(loaded):.4f} 比特")
|
||||
|
||||
# 确定性
|
||||
det = jnp.array([0.0, 0.0, 0.0, 0.0, 0.0, 1.0])
|
||||
print(f"确定性: {entropy(det):.4f} 比特")
|
||||
|
||||
# 公平硬币
|
||||
coin = jnp.array([0.5, 0.5])
|
||||
print(f"公平硬币熵: {entropy(coin):.4f} 比特")
|
||||
```
|
||||
|
||||
2. 计算真实分布与多个近似分布之间的交叉熵和 KL 散度。验证 $D_{\text{KL}}(p \| q) = H(p, q) - H(p)$。
|
||||
```python
|
||||
import jax.numpy as jnp
|
||||
|
||||
def cross_entropy(p, q):
|
||||
return -jnp.sum(p * jnp.log2(jnp.clip(q, 1e-10, 1.0)))
|
||||
|
||||
def kl_divergence(p, q):
|
||||
mask = p > 0
|
||||
return jnp.sum(jnp.where(mask, p * jnp.log2(p / jnp.clip(q, 1e-10, 1.0)), 0.0))
|
||||
|
||||
def entropy(p):
|
||||
p = p[p > 0]
|
||||
return -jnp.sum(p * jnp.log2(p))
|
||||
|
||||
p = jnp.array([0.4, 0.3, 0.2, 0.1]) # 真实分布
|
||||
|
||||
for name, q in [("完全匹配", p),
|
||||
("轻微偏差", jnp.array([0.35, 0.30, 0.25, 0.10])),
|
||||
("严重偏差", jnp.array([0.1, 0.1, 0.1, 0.7]))]:
|
||||
h_p = entropy(p)
|
||||
h_pq = cross_entropy(p, q)
|
||||
kl = kl_divergence(p, q)
|
||||
print(f"{name:20s}: H(p)={h_p:.4f}, H(p,q)={h_pq:.4f}, "
|
||||
f"KL={kl:.4f}, H(p,q)-H(p)={h_pq-h_p:.4f}")
|
||||
```
|
||||
|
||||
3. 通过计算两个不同分布之间的 $D_{\text{KL}}(p \| q)$ 和 $D_{\text{KL}}(q \| p)$,证明 KL 散度不是对称的。
|
||||
```python
|
||||
import jax.numpy as jnp
|
||||
|
||||
def kl_div(p, q):
|
||||
mask = p > 0
|
||||
return float(jnp.sum(jnp.where(mask, p * jnp.log2(p / jnp.clip(q, 1e-10, 1.0)), 0.0)))
|
||||
|
||||
p = jnp.array([0.9, 0.1])
|
||||
q = jnp.array([0.5, 0.5])
|
||||
|
||||
print(f"D_KL(p || q) = {kl_div(p, q):.4f}")
|
||||
print(f"D_KL(q || p) = {kl_div(q, p):.4f}")
|
||||
print("不相同!KL 散度是不对称的。")
|
||||
```
|
||||
|
||||
4. 模拟训练过程中交叉熵损失的变化。创建一个"真实"的 one-hot 标签,展示随着模型预测概率的改善,损失如何下降。
|
||||
```python
|
||||
import jax.numpy as jnp
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# 真实标签:4 个类别中的第 2 类
|
||||
true_label = jnp.array([0, 0, 1, 0])
|
||||
|
||||
# 模拟预测逐步改善
|
||||
steps = []
|
||||
losses = []
|
||||
for confidence in jnp.linspace(0.25, 0.99, 50):
|
||||
# 模型对类别 2 的置信度逐渐提高
|
||||
remaining = (1 - confidence) / 3
|
||||
pred = jnp.array([remaining, remaining, confidence, remaining])
|
||||
loss = -jnp.sum(true_label * jnp.log(jnp.clip(pred, 1e-10, 1.0)))
|
||||
steps.append(float(confidence))
|
||||
losses.append(float(loss))
|
||||
|
||||
plt.figure(figsize=(8, 4))
|
||||
plt.plot(steps, losses, color="#e74c3c", linewidth=2)
|
||||
plt.xlabel("模型对真实类别的置信度")
|
||||
plt.ylabel("交叉熵损失")
|
||||
plt.title("交叉熵损失随预测改善而下降")
|
||||
plt.grid(alpha=0.3)
|
||||
plt.show()
|
||||
```
|
||||
Reference in New Issue
Block a user