离散概率空间 vs 线性空间

概率必须非负、总和为 1——这不是线性空间。但 softmax 之前的 logit 空间是自由的。从黑白球实验中看到从"三角形"到"全平面"的跨越。

实验设计

设样本空间为 10 次放回取样。两组实验:

表1 实验设计:

组别 颜色 可能结果 概率分布
A 黑白 $$\{黑, 白\}$$ $$p_{黑} + p_{白} = 1$$
B 黑白灰 $$\{黑, 白, 灰\}$$ $$p_{黑} + p_{白} + p_{灰} = 1$$

10 次放回后,各组得到一个频率向量:

A 组: (黑=6, 白=4)    →  经验概率 p = (0.6, 0.4)
B 组: (黑=6, 白=3, 灰=1)  →  经验概率 p = (0.6, 0.3, 0.1)

这个向量

$$\mathbf{p}$$

生活在概率单纯形上。

单纯形不是线性空间

A 组(二分类)

二分类的概率分布只有一个自由度:

$$p_{黑} = p, \quad p_{白} = 1-p, \quad 0 \leq p \leq 1$$

这个空间是实数轴上的一个线段

p=0:   ○白          p=0.5:   ●──○        p=1:   ●黑
[0, 1] 区间,两端封闭

线性空间要求:任意线性组合还在空间内。但这里:

  • $$p = 0.5$$ 在空间中(黑白各半)
  • $$p = -0.5$$ 不在空间中(概率不能为负)
  • $$p = 1.5$$ 不在空间中(概率不能大于 1)

所以概率单纯形 不是 线性空间——它是有界闭凸集。

B 组(三分类)

三分类的概率分布在二维平面上是一个三角形(2-单纯形):

              白
               ● (0,1,0)
              / \
             /   \
            /     \
           /       \
   (1,0,0)●─────────●(0,0,1)
         黑         灰

三点分别对应三组极端情况。内部任意一点对应一个有效概率分布。但这个空间仍然被边界封锁——你不能有负概率,也不能让总和超过 1。

Softmax:从三角形到全平面

Softmax 的参数是 logits

$$\mathbf{z} \in \mathbb{R}^k$$

,没有任何约束:

z = (z_黑, z_白)          A 组: z ∈ ℝ²,完全自由
z = (z_黑, z_白, z_灰)    B 组: z ∈ ℝ³,完全自由

通过 softmax:

$$p_i = \frac{e^{z_i}}{\sum_j e^{z_j}}$$

表2 z 空间 vs p 空间:

z 空间 p 空间
约束 $$p_i \geq 0, \sum p_i = 1$$
范围 $$z_i \in (-\infty, +\infty)$$ $$p_i \in [0, 1]$$
线性?
加法封闭 ✅ $$z_1 + z_2 \in \mathbb{R}$$ ❌ $$p_1 + p_2$$ 无意义
数乘封闭 ✅ $$2z \in \mathbb{R}$$ ❌ $$2p$$ 不再归一化

Softmax 把一个无约束的线性空间映射到了有约束的单纯形上。

图1 sigmoid 曲线(softmax 二分类特例):

Sigmoid:z ∈ R → p ∈ (0,1)

图2 A 组(二分类)的概率空间是一条线段 [0,1],而 logit 空间是整个实数轴:

二分类:概率线段 vs logit实数轴

图3 B 组(三分类)的概率空间是一个三角形(2-单纯形),内部每个点对应一个有效概率分布:

三分类概率单纯形

图4 同一组 logits 在 ℝ³ 里自由行走,softmax 把它们映射到概率空间——一条自由的路径被限制在了三角形内:

随机行走对比:logit自由 vs 概率被锁

图5 对数变换(log)将概率空间均匀铺满的网格映射到整个平面:

概率三角形 vs logit平面

点彩实验:概率密度如何在 logit 空间展开

取 6:3:1 的三色球(黑:白:灰),每次 10 次放回取样,重复 5000 组。每一组计算经验概率

$$\mathbf{p}$$

,然后取 log 得到 logits

$$\mathbf{z}$$

。把

$$\mathbf{p}$$

画在三角形上,

$$\mathbf{z}$$

画在平面上——空间变了,点的密度也跟着变了。

图6 点彩密度图(5000 组):

点彩密度图:5000组 6:3:1 放回实验

图7 只看 100 组,每一个采样点清晰可见:

点彩 100组:每个点是一个采样

关键观察:

  • 概率空间(左):点被锁在三角形里。靠近真实分布 (0.6, 0.3, 0.1) 的地方点最密——那是采样回落到真值的区域。
  • Logit 空间(右):点散布在整个平面上。三角形中心的密集区域映射到了平面上的某一团,而三角形边缘(概率接近 0 或 1 的点)映射到了很远的地方——log 把靠近边界的点推到了平面上很远的位置

这张点彩图回答了上面 “负 logits 是否只是输入合法性” 的问题——不只是合法性。logits 的负值对应了概率 ≤ 0.5 的情形(相对其他类证据较弱),正值对应概率 > 0.5。真正的概率密度团簇在 logit 空间里变成了椭圆状的云,而三角形边缘的稀疏地带变成了平面的散落尘埃。

这就是 softmax 的"等距映射"——三角形上的均匀网格被映射到对数空间后,网格在远处变得稀疏,在中心变得密集。这不是线性变换,而是一个"从有界到无界"的拓扑变换。

为什么 logit 点不是遍布全平面?

这个问题很有价值——也是点彩图能揭示的最关键的 insight。

每次只有 10 次放回取样,这意味着经验概率是量化的:(黑, 白, 灰) 的计数是 0 到 10 的整数,且总和必须等于 10。三个数满足这个约束有多少种?

$$\binom{10+3-1}{3-1} = \binom{12}{2} = 66 \text{ 种}$$

实际 5000 次试验只命中了其中 44 种组合。log(p) 把这 44 种离散组合映射到平面上 44 个点——所以点看起来聚在几个团里。

提高每组次数会发生什么?

图8 logit 分辨率随取样次数变化:

logit 分辨率:n_draws 从 10 到 500

10 次和 50 次时,概率是粗量化的——logit 点被限制在有限的格子上。到 500 次时,概率几乎是连续的,logit 点开始覆盖整个区域。但注意:所有点仍然围绕真实分布 (6:3:1) 形成的等高线,因为采样源自同一个真实分布。

要想 logit 点真正覆盖整个 ℝ² 平面,需要变化真实分布本身。当一个神经网络在训练时,参数的每次更新都在改变 logits——logit 空间确实可以收敛到任何位置。点彩图展示的是采样分布,不是空间的界限。

可视化:logits 的自由度

A 组(二分类)实际上自由度是 1——softmax 对 logits 平移不敏感:

$$\text{softmax}(z_1 + c, z_2 + c) = \text{softmax}(z_1, z_2)$$

所以有效自由度 = k − 1。但关键是:这 k−1 个自由度取任意实数值,不需要在 [0, 1] 内。

表3 概率 vs Logit 自由度:

概率 p Logit z
A 组(2 色) 线段 [0,1] ℝ¹ 全线
B 组(3 色) 三角形内部 ℝ² 全平面
允许负值?
允许 >1?

代码验证

import torch
import torch.nn.functional as F

# === A 组:黑白球,10 次放回 ===
print("=== A组 黑白二分类 ===")
counts_a = torch.tensor([6, 4], dtype=torch.float32)
p_a = counts_a / counts_a.sum()
print(f"概率 p: {p_a}")

# 从概率计算 logits(加 log,再中心化)
logits_a = torch.log(p_a)
print(f"logits z: {logits_a}")
print(f"softmax(z): {F.softmax(logits_a, dim=-1)}")

# 验证:logits 可以取任意值,softmax 仍然有效
for val in [-5, -2, 0, 2, 5]:
    z_test = torch.tensor([val, 0.0])
    p_test = F.softmax(z_test, dim=-1)
    print(f"  z=({val:3d}, 0) → p=({p_test[0]:.4f}, {p_test[1]:.4f})")

# 验证:概率空间有限制,logit 空间无限制
# p 必须满足 p∈[0,1], 但 z 可以是任何数
print(f"\n概率 p 的取值范围: [0, 1]")
print(f"logits z 的取值范围: (-∞, +∞)  ← 线性空间")

# === B 组:黑白灰球,10 次放回 ===
print("\n=== B组 黑白灰三分类 ===")
counts_b = torch.tensor([6, 3, 1], dtype=torch.float32)
p_b = counts_b / counts_b.sum()
print(f"概率 p: {p_b}, 总和={p_b.sum().item()}")

logits_b = torch.log(p_b)
print(f"logits z: {logits_b}")
print(f"softmax(z): {F.softmax(logits_b, dim=-1)}")

# 验证:概率只能走三角形内部,logits 可以走全平面
print("\n概率空间的移动(沿边界):")
p_moves = [
    (0.8, 0.15, 0.05),
    (0.5, 0.4, 0.1),
    (0.3, 0.3, 0.4),
]
for p in p_moves:
    p_t = torch.tensor(p)
    z_t = torch.log(p_t)
    print(f"  p=({p[0]:.1f},{p[1]:.1f},{p[2]:.1f})  ←  z=({z_t[0]:.1f},{z_t[1]:.1f},{z_t[2]:.1f})")

print("\nLogits 空间的自由行走(允许负数、允许任意值):")
z_moves = [
    (5.0, 0.0, -2.0),
    (-1.0, 3.0, 0.5),
    (0.0, 0.0, 0.0),
]
for z in z_moves:
    z_t = torch.tensor(z)
    p_t = F.softmax(z_t, dim=-1)
    print(f"  z=({z[0]:.1f},{z[1]:.1f},{z[2]:.1f})  →  p=({p_t[0]:.3f},{p_t[1]:.3f},{p_t[2]:.3f})")

输出:

=== A组 黑白二分类 ===
概率 p: tensor([0.6000, 0.4000])
logits z: tensor([-0.5108, -0.9163])
softmax(z): tensor([0.6000, 0.4000])

# logits 可以取任意值,softmax 仍然有效
  z=( -5, 0) → p=(0.0067, 0.9933)
  z=( -2, 0) → p=(0.1192, 0.8808)
  z=(  0, 0) → p=(0.5000, 0.5000)
  z=(  2, 0) → p=(0.8808, 0.1192)
  z=(  5, 0) → p=(0.9933, 0.0067)

概率 p 的取值范围: [0, 1]
logits z 的取值范围: (-∞, +∞)  ← 线性空间

=== B组 黑白灰三分类 ===
概率 p: tensor([0.6000, 0.3000, 0.1000]), 总和=1.0
logits z: tensor([-0.5108, -1.2040, -2.3026])
softmax(z): tensor([0.6000, 0.3000, 0.1000])

Logits 空间的自由行走:
  z=(5.0, 0.0, -2.0)  →  p=(0.993, 0.007, 0.001)
  z=(-1.0, 3.0, 0.5)  →  p=(0.014, 0.776, 0.210)
  z=(0.0, 0.0, 0.0)   →  p=(0.333, 0.333, 0.333)

频率 = 概率:FFT 的谱视角

在中文里,“频率"既指信号振动的快慢(frequency),也指事件发生的多少(frequency of occurrence)。这不是语言的巧合——这两个"频率"共享同一个数学结构:傅里叶变换

把三色球的概率向量

$$p = [0.6, 0.3, 0.1]$$

直接做 FFT:

import numpy as np

p = np.array([0.6, 0.3, 0.1])
F = np.fft.fft(p)      # 概率 → 频谱
p_recovered = np.fft.ifft(F).real   # 频谱 → 概率

表4 偏斜分布 p=[0.6,0.3,0.1] 的 FFT:

频率分量 含义
F[0] = 1.0 DC 分量 总概率 = 1,守恒量
F[1] = 0.40 − 0.17j 基频 分布不均匀的证据
F[2] = 0.40 + 0.17j 倍频 F[1] 的共轭,保证实数性

表5 均匀分布 p=[1/3,1/3,1/3] 的 FFT:

频率分量 含义
F[0] = 1.0 DC 分量 总概率 = 1
F[1] = 0 基频 零能量,均匀分布无结构
F[2] = 0 倍频 零能量

当概率分布完全均匀时,所有高频分量为零——和信号分析完全一样:白噪声没有结构,均匀分布也没有结构。概率分布的"偏斜"程度编码在非零频率分量的幅度里。

统一的谱视图

                               FFT/IFT
        概率质量函数  ◄──────────────────►  频谱(特征函数)
        p(x)                                  φ(ω)
        ┌───┐                                 ┌───┐
        │0.6│ 黑                              │DC │ = 总概率
        │0.3│ 白                             ─┤   ├─ 高频 = 结构信息
        │0.1│ 灰                             ─┤   ├─ 共轭 = 实数约束
        └───┘                                 └───┘
          ▲                                      ▲
          │  softmax(z)                          │  所有信息可逆
          │  ←→  log(p)                          │  完全恢复
          ▼                                      ▼
         Logit 空间                            复频域
         z ∈ ℝᵏ                               F ∈ ℂᵏ

概率空间里的"概率之和为 1"在频域里变成了 “DC = 1”。概率空间的"非负性约束"在频域里变成了"共轭对称性”。两者等效——只是换了一个观测角度。

信号处理中的一句老话适用这里:没有一个域比另一个更真实——它们只是同一个测度的不同基底

时域与频域:不可同时精确,但可以同时学习

留一个问题给读者思考。

看这两句中文:

“我的确累了” “我的的确确累了”

“的确"在第一句出现了一次,在第二句出现了两次。频率变了——softmax 能抓到"的确"的频率翻倍,生成梯度去学习。

词的"邻接"呢?“的的确确"里的 AABB 叠词模式(的→的确→确),频率域看不到。你把 [我的确累了] 按词袋打散——得到 {我,的确,累,了} 各 0.25,和原文的顺序毫无关系。

这就是频率域的盲区:词序信息全部丢失。

信号处理里用短时傅里叶变换解决——窗口滑动,每帧独立做 FFT,时域和频域同时保留:

信号:  sin(2πt) + sin(5πt) + sin(3πt)
         ↓
      ┌──────────────────────────┐
      │  STFT: 帧帧 FFT          │
      │  窗口1: 低频强              │
      │  窗口2: 高频强              │   →  时变频谱图
      │  窗口3: 中频强              │
      └──────────────────────────┘

NLP 里的对应物就是 Attention

序列:  "我的的确确累了"
         ↓
      ┌──────────────────────────┐
      │  Self-Attention          │
      │  t=0 "我":   关注"的确"       │
      │  t=1 "的":   关注"的确"       │
      │  t=2 "的确": 关注"的确"+"确"   │  →  token-token 权重矩阵  
      │  t=3 "确":   关注"的确"+"累"   │     每个时间步看到不同的频率分布
      │  t=4 "累":   关注"了"         │
      └──────────────────────────┘

每一次 Attention 计算

$$QK^T$$

,本质上是在当前时间点上重新做傅里叶风格的谱分解:哪些 token 的信号强(相似度大),哪些弱。这个分解在每个时间步是不同的——所以 Transformer 既保留了"哪个词经常出现”(频域),也保留了"谁挨着谁、谁关注谁”(时域)。

三个域的对应

表6 信号域 ↔ ML 域对应:

信号处理 概率/ML 解决的问题
时域 $$f(t)$$ 词序列 “我-的确-累了” 谁挨着谁
频域 $$F(\omega)$$ 词袋概率 softmax(p) 哪个词重要
时频域 STFT Transformer Attention 同时拥有两者

这就是 WMT 翻译模型能从词袋进化到 Attention/Transformer 的原因——频率给出了"这是什么",序列给出了"它怎么排列的"。两者交汇的地方,就是理解。

结论

表7 全文概念总结:

概念 数学空间 特性 不是线性空间的原因
概率 $$\mathbf{p}$$ k-维单纯形 $$\sum p_i = 1, p_i \geq 0$$ 有界、封闭、凸组合不保持
Logits $$\mathbf{z}$$ $$\mathbb{R}^k$$ $$z_i \in (-\infty, \infty)$$ ✅ 无约束,线性封闭
Softmax $$\mathbb{R}^k \to \Delta^k$$ 前向:exp + 归一化,收束为有效概率
log $$\Delta^k \to \mathbb{R}^k$$(带常数模糊) p ↦ z − log(Σe^z),还原到平移等价类

Softmax 做的事:把一个无约束的欧几里得空间(线性空间)映射到了有约束的概率单纯形上。 反过来,log 把概率拉回线性空间。

这就是分类任务能用梯度下降的根本原因——模型在 logit 空间(线性)里做参数更新,softmax 保证更新后的 logits 总能变成有效的概率分布。如果你直接在概率空间里做梯度下降,你会撞墙:概率不能为负、不能大于 1、必须保持总和为 1——三个约束锁死了优化。

回到 WMT:翻译模型在 56K 维的 logit 空间里自由行走(梯度可以大胆地更新任何 logit),softmax 把每一步更新映射到 56K 维的概率单纯形上。K_lang 限制 softmax 分母相当于缩小了单纯形的有效维度——从 56652 维缩到 170 维。

May the Code be with us.


License: GPLv3
本文《Watermelon》系列采用 GNU 通用公共许可证第三版 (GNU General Public License v3.0) 协议进行开源发布与分发。