梯度函数决定学习规律

sin 和 tanh 之间的距离不是 0.76 到 3.06。是"自己打自己"和"方向从不出错"之间的距离。

一个失败的实验,一条意外的规律

Phase 1.0 的 RNN 实验测了 7 组 hidden_size,最佳 BLEU 3.06。到此为止,这是一个标准的调参实验。

然后我们做了一个看似无厘头的尝试:把 RNN 的激活函数从 tanh 换成 sin。

理由很朴素——sin 是周期函数。如果翻译本质是 hash 碰撞,周期函数天然支持"多桶"碰撞——同一个输出值可以从无限多个输入周期产生。tanh 只有一个桶(全局单调),sin 有无限个桶。理论上,多桶应该提供更多自由度。

结果:sin RNN 的最佳 BLEU = 0.76。 远低于 tanh 的 3.06。loss 从 6.32 跌到 6.19 就几乎不动了。

这不是"sin 比 tanh 差"这么简单。这个 0.76 里藏着一个更根本的问题。

梯度函数就是学习规律

神经网络的每一步训练都遵循同一个模式:

loss → 计算梯度 → 用梯度更新参数

而"计算梯度"这一步,激活函数的选择是决定性的一环。换个激活函数,就是换一套梯度规则——也就是换一种学习方式。

激活函数 梯度函数 梯度方向 学习特征
tanh tanh’(x) ∈ (0,1] 永远为正,单调衰减 笨但稳——方向从不出错
ReLU 0 或 1 永远非负 莽但快——不衰减,但会死
sin cos(x) ∈ [-1,1] 正负交替 聪明但自毁——自己否定自己

tanh’ 的范围是 (0,1]。值可以很小(接近饱和区),但符号不变。每一步梯度指向的方向,和全局最优方向一致。衰减只是让步子变小,不会让方向反了。

cos(x) 在每一个 π/2 的倍数处翻转符号。前半句学的方向,后半句亲手推翻。

模拟:为什么方向会反转

假设一段 RNN 的前激活值 z 随句子长度逐步偏移(模拟 W·h_{t-1} 的累积):

时间步 z_t tanh’(z) 方向 cos(z) 方向
1 0.2 +0.96 +0.98
2 0.8 +0.50 +0.70
3 1.8 +0.12 −0.23
4 2.5 +0.02 −0.80
5 3.0 +0.005 −0.99

tanh 所有时间步都往同一个方向推——力度越来越小,但方向一致。箱子被慢慢推到目标位置。

sin 在第 3 步翻转了方向。第 1-2 步往东推,第 3-5 步往西推。净位移接近零——箱子在原点附近来回跳舞。

这就是 BLEU=0.76 的根因。不是学不到东西,是学到的东西被自己亲手毁掉了。

好的梯度函数 = 自洽的向量场

把梯度想象成地形图上的箭头。每个参数位置都有一个箭头指向"下山"的方向——这就是向量场。

  • tanh 的向量场:所有箭头指向同一个象限。可以弱,但方向一致。优化器只要跟着走,迟早到谷底。
  • sin 的向量场:箭头来回翻转。优化器往前走两步,发现箭头指向回头了——刚走的路被否定。

“好的梯度函数"的标准不是"梯度够不够大”,而是"梯度方向是否和全局最优方向一致"。

tanh 的梯度小不是缺陷——它宁愿走得慢,也不走错方向。这是工程上的"慢就是快"。

loss 和 BLEU——两把不同的尺子

如果梯度函数的问题是方向,那还有一个更隐蔽的问题:梯度的方向是谁定的?

答案是 loss——CrossEntropy。但 CrossEntropy 追求的是"逐 token 预测精准",而 BLEU 考察的是"整句 n-gram 碰撞率"。两把尺子量的是不同的事。

H=512 跑 20 epoch 的铁证:

epoch loss BLEU
0 5.69 1.84
2 4.76 3.02
10 4.22 1.79
19 4.46 1.35

loss 持续下降(模型自认为越来越好),BLEU 在 epoch 2 达峰后一路衰退(实际翻译质量越来越差)。模型在 teacher forcing 的镜子里觉得自己很美,但别人看到的是东施效颦。

这意味着:即使我们选了一个"方向自洽"的梯度函数(如 tanh),梯度函数追的目标(loss)和最终评价标准(BLEU)之间存在结构性分歧

BLEU 为什么不能直接当 loss

BLEU 的公式里有一个不可微的步骤——argmax。模型输出 logits 后,必须选一个词(argmax),然后在 n-gram 表里计数。argmax 是离散跳变:无论你把 cat 的概率从 0.4 提到 0.49,选出来的词不变——选的都是其他词。直到概率超过 0.51,argmax 的结果才会突然跳变。

所以 BLEU 对每个参数 W 的偏导链中,∂argmax/∂logits 这一项处处为零。整个梯度链直接断了。

全行业用 CrossEntropy 当 loss 不是因为 CE 比 BLEU “好”——是只有 CE 能传梯度。BLEU 更好,但数学不让你用。

Soft BLEU——让 BLEU 听到梯度的声音

如果把 argmax 换成 softmax,把硬 n-gram 计数换成概率加权:

$$\text{SoftBLEU} = \frac{\sum_{w} \min(p(w|ctx), c_{ref}(w))}{\sum_{w} p(w|ctx)}$$

$p(w|ctx)$ 是模型预测 w 的连续概率。整条链可微——梯度可以直接从 BLEU 近似值流回模型参数。

训练时与 CrossEntropy 混合:

$$L_{total} = \lambda \cdot L_{CE} + (1-\lambda) \cdot (1 - \text{SoftBLEU})$$

当前仅测试了 λ=0.5(均衡权重)。λ 的最优值、λ 的退火策略(从 1.0 逐步降)仍需实验验证。

四层 Hash 碰撞框架

把翻译过程看作四次 hash 碰撞:

层次 hash 空间 碰撞判定 参与梯度?
1. Embedding E 维向量 token→向量 ✅ CrossEntropy
2. Hidden (RNN) 或 Attention (Transformer) H 维向量 整句→压缩向量 / 选择性碰撞 ✅ CrossEntropy
3. Decoder output V 维 logits 向量→token ✅ CrossEntropy
4. BLEU n-gram 表 输出←→参考 ❌ 不可微

前三次碰撞都参与梯度。第四次——BLEU 碰撞——模型根本听不到

RNN 的悲剧是第 2 层(时间轴压缩破坏信息结构),Transformer 换了第 2 层(Attention 选择性碰撞),但第 4 层的问题——BLEU 不参与梯度——Transformer 也没解决。

实验结果:SoftBLEU 突破 CE 天花板

H=512, E=128, seed=42, batch=64, 在纯 RNN 上对比 CE-only 和 SoftBLEU 混合损失:

$$L_{total} = \lambda \cdot L_{CE} + (1-\lambda) \cdot (1 - \text{SoftBLEU}), \quad \lambda = 0.5$$
epoch CE-only BLEU CE SoftBLEU BLEU mixed loss SoftBLEU 值
0 3.06 6.14 2.49 3.47 0.204
1 2.31 5.38 3.21 3.07 0.234
2 1.73 5.08 1.81 2.92 0.237
3 2.40 4.88 2.88 2.82 0.238
4 1.91 4.74 2.59 2.75 0.239

SoftBLEU best BLEU = 3.21(epoch 1),CE-only best = 3.06(epoch 0)。首次突破纯 CE 天花板。

SoftBLEU 值自身从 0.204 → 0.239 逐步提升——模型在学会优化 BLEU 的 soft 近似。但提升幅度只有 +0.15,随后也陷入了过拟合。

向量化是关键。最初的 Python 循环版 2 小时跑不出一个 epoch(详见 第六篇)。用 scatter_add_ 替代 4 层 Python 循环后,5 epoch 仅需 5 分钟,速度提升 1000 倍。

这条路通向哪里

sin 实验的失败,不是告诉我们"sin 不好"。它告诉我们:梯度函数的选择不是调参——是选择一种学习规律。 一个不能自洽的梯度函数,再大的模型也救不回来。

tanh 的梯度方向自洽,但目标是 loss 而非 BLEU。模型沿着 loss 的梯度方向走得太远,BLEU 反而掉进了过拟合的沟。这条沟就是 Soft BLEU 要填的。

后来的实验完整验证了这条规律——从 RNN (BLEU=3.0) 到 Attention (3.77) 再到 Transformer (11.70),架构在变,但 hash 编码 + 梯度积分的底层逻辑不变。K_lang 在弱模型上补缺陷,在强模型上多此一举。梯度方向的正确性,从 sin→tanh 到 CE→SoftBLEU 到词级→BPE,是一条贯穿 9 篇文章的红线。

详见 008 — 从 3 到 11 的跃迁


DAG 的血——为什么多项式不是前提,可用 backward() 才是

神经网络的训练本质是一个图上的血液系统

DAG 骨架 = 拓扑结构(矩阵运算的依赖关系)
grad 血液 = 方向信号(∂L/∂W 沿树往回流动)
矩阵肌肉 = 存储信息(被梯度反复拉扯,最终成形)

ReLU 不是多项式——分段线性,x=0 有折角,数学上不可导。但它能进 DAG——PyTorch 约定折角处梯度为 0,一根人造血管填了那个洞。BLEU 的 argmax 进不了 DAG——不是因为它不光滑,是因为它的 backward 被设计成返回全零。血凝固了。但如果给 argmax 一个人造的 backward:

argmax backward (0/1 风格):
  预测词 ∈ reference → grad = 1
  预测词 ∉ reference → grad = 0

它就有了血。矩阵就能动。数学纯度不重要,方向正确才重要。 sin 失败不是因为进不了 DAG——它是真导数。它失败是因为 cos 正负交替,方向自己打自己。

神经网络的训练,只需要两个条件:血在流(不全零),血的方向不对冲(不反转)。满足这两条,不管信号来自微积分、次梯度、还是 0/1 人造血,矩阵都会进化。


梯度训练 = Hash 编码 + Riemann 积分

神经网络的训练,本质上是把语言逐词逐句 hash 编码进权重张量。每一步梯度是当前 batch 的语言统计快照,训练过程就是把这些快照永久存储:

$$W_T = W_0 + \sum_{t=0}^{T} (-\eta \cdot \nabla \mathcal{L}_t) \quad \xrightarrow{\eta \to 0} \quad W_0 + \int_0^T \nabla \mathcal{L}(t) \, dt$$

每一个 optimizer.step() 的执行流程:

  1. 词 → embedding hash:token → $\mathbb{R}^d$ 向量,查表
  2. 前向撞桶:hidden 层把向量推过 attention/FFN,到 output 层做 softmax 查桶
  3. 比对碰撞:预测桶 vs 目标桶 → 算出误差
  4. 反向修正:$\nabla\mathcal{L}$ 告诉你桶壁该往哪边挪
  5. 积分存储:$W \mathrel{-}= \eta \cdot \nabla\mathcal{L}$ 把这次碰撞经验热记录进权重

这就是 DAG 之血的完整循环:血液(梯度)在骨架(DAG)上流动,每次循环把一次 hash 碰撞的教训写入肌肉(权重矩阵)。

架构和损失函数——同一枚硬币的两面

在 hash 编码框架下,架构和损失函数不再是竞争关系:

  • 架构改变 → hidden_seq 的表示能力变了 → ∂L/∂W 经由不同路径回传 → 梯度的接收面不同
  • 损失函数改变 → L 的定义变了 → ∂L/∂W 的量级和方向变了 → 梯度的来源不同

Attention 上用 K_lang +0.18 BLEU,Transformer 上一轮架构跳变就 +7.7 BLEU。不是因为 Architecture > Loss,而是因为 Attention 的瓶颈在表示能力(LSTM 时序链),不是梯度方向。当架构表达力够了,但梯度目标离 BLEU 太远——这就是 SoftBLEU / K_lang 该上场的时候。

梯度的多寡和方向才是学习的唯一原料。架构和损失函数只是不同的食谱。

在这个框架下,所有调试的变量都有了统一的物理意义:

变量 物理意义
激活函数(tanh/sin/ReLU) 梯度方向的符号——是自洽推进还是自我否定
损失函数(CE/SoftBLEU) 碰撞的"靶心"定义——逐 token 精准 vs n-gram 覆盖
K_lang(k) 每次积分时,多少个桶参与修正——噪声滤波器
lr(η) Riemann 积分的步长(dt)
深度(n_layers) hash 链的长度——每个 token 经历多少次碰撞
宽度(d_model) hash 桶的容量——每个桶能存多少信息
BPE vs 词级 hash 桶的大小选择——大桶少量 vs 小桶多量

其中 lr 和 K_lang 是耦合的——同一个参数更新公式 ΔW = η · ∂L/∂W 里,η 决定走多远,K_lang 决定梯度分配到哪些桶。桶数错了,lr 再调也白搭。


频域梯度——用 IFFT 把离散 BLEU 变成可微曲面

HM 提出一个新的视角:离散函数不可导,不是因为"离散不好"——是微积分不自洽。如果换个数学基底,离散也许就可导了。

傅里叶逆变换就是把时域的离散方波变成频域的正弦波叠加:

$$\text{BLEU}(t) \approx \sum_k c_k \cdot e^{i\omega_k t}$$

原信号是二值的(0 或 1,n-gram 碰上了没有),IFFT 重建后变成一个带限连续函数——在采样点之间自动做了光滑插值。

梯度会学到什么? 不是每个 token 该改什么——是整句的频谱结构应该向哪个方向偏移:

频段 物理意义 梯度信号
低频 句长、全局流畅度 brevity penalty 方向
中频 2~4 gram 词组边界 词序排列方向
高频 token 噪声 过拟合指标

IFFT 的梯度天然多尺度——同时看低频和高频,不会像 CE 那样在 token 级别上过拟合。本质上是给 BLEU 套了一个频域的正则化外壳——在频率空间里,离散跳变被展开成了光滑的正弦基底。

待验证:Phase 1 RNN 上跑 CE + DCT 频谱损失对照实验。


May the Code be with us.


License: GPLv3
本文《SameTime》系列采用 GNU 通用公共许可证第三版 (GNU General Public License v3.0) 协议进行开源发布与分发。允许任何形式的复制、修改和分发,但必须继承相同的开源协议,承认在算力宇宙中所有的迭代与变异。