🧠 三值量化学习逻辑

直通估计器(STE)如何“骗过”梯度 · 零基础直观理解

1. 正常训练:光滑的“溜滑梯”

正常的神经网络训练,就像站在一个光滑的斜坡(损失函数)上。

flowchart TD A["权重 w(当前位置)"] --> B["前向计算(往下滑)"] B --> C["算出损失(多高)"] C --> D["反向求导(感受坡度)"] D --> E["梯度下降(朝反方向迈步)"] E --> A
✅ 关键点: 因为斜坡是连续的,坡度(梯度)永远存在,永远知道该往哪走。

2. 三值化的问题:变成“断裂的楼梯”

三值化时,我们把权重强制变成 -1、0、+1。这就好比把光滑的斜坡,改成了只有三级的陡峭台阶。

⛔ 致命问题: 台阶的平面是平的(导数为0),台阶的边缘是垂直的(导数无穷大)。
站在台阶上时,感觉不到坡度(梯度消失了)!根本不知道是该往左走还是往右走。
flowchart TD W["全精度权重"] --> Q["前向:强制四舍五入
(踩上台阶)"] Q --> T["变成离散值 {-1, 0, +1}"] T --> M["计算损失"] M --> G["反向求导"] G --> X["❌ 台阶是平的,梯度=0"] X --> END["权重无法更新,训练卡死"]

这就是“梯度消失” —— 如果没有 STE,三值化网络根本训练不动。

3. STE 的魔法:假装有个“隐形斜坡”

STE(直通估计器)想了个鬼点子:前向传播时,我踩台阶(做三值化);反向传播时,我假装台阶不存在,直接穿透过去!

🎯 比喻: 就像闭着眼睛下楼梯。脚踩空了(前向离散化),但大脑以为“刚才那一步是平的”(反向直通),手还是能扶住墙(梯度),继续往下摸。

前向传播:踩台阶

flowchart TD W["全精度权重"] --> R["四舍五入(踩台阶)"] R --> T["变成 {-1, 0, +1}"] T --> L["计算损失"]

反向传播:假装台阶不存在

flowchart TD L["损失"] --> G["计算梯度"] G --> STE["🔮 STE 直通
(忽略四舍五入,原样传回)"] STE --> U["更新全精度权重
(继续往前走)"]
✅ 代码就是这一句: return grad_output, None。直接把梯度原样扔回给全精度权重,假装 Round 和 Clamp 从来没发生过。

4. 震荡与收敛:为什么“瞎摸”也能到终点?

既然 STE 是“乱传”梯度,为什么模型最后还能收敛?我们看一个简单的物理场景。

场景:权重在 0.6,目标需要 0

1
前向:0.6 四舍五入 = +1(踩到了 +1 的台阶)。损失巨大(因为本来想要 0)。
2
STE 反向:梯度说“太大了,赶紧减小!”。这个巨大推力直接打在 0.6 上。
3
更新:0.6 被猛地推到了 0.1(甚至可能负值)。
4
下一轮前向:0.1 四舍五入 = 0(终于踩到了 0 的台阶!)。
5
最终:虽然 0.1 不是 0,但前向输出已经变成 0 了。模型只要把 0.1 稳住(或继续推向 0),就完美收敛。
🎯 核心机制(推箱子过沟):
权重就是箱子。STE 的梯度就是一股巨大的推力。
虽然推力很粗暴(导致震荡),但它能把箱子从“+1 的沟”里推出来,推过 0.5 的边界,掉进“0 的沟”里。一旦掉进正确的沟(桶),前向输出就稳定了。

5. 最终对比:全精度 vs 三值化 STE

flowchart TD A1["权重=0.6"] --> A2["输出=0.6×2=1.2"] --> A3["完美命中"] A3 --> A4["梯度=0,权重不变"]
flowchart TD B1["权重=0.6"] --> B2["三值化=1"] --> B3["输出=2,偏大"] B3 --> B4["STE梯度巨大"] --> B5["权重被推到-1.0(震荡)"] B5 --> B6["三值化=-1"] --> B7["输出=-2,偏小"] B7 --> B8["STE反方向推"] --> B9["权重推回0.8"] B9 --> B10["三值化=1,输出≈2"] B10 --> B11["反复震荡,但落进桶里"]

📌 终极结论:

全精度训练是“精准制导”,一次到位。三值化 STE 是“推箱子过沟”,虽然来回震荡,但因为有 STE 这股“蛮力”推着,权重总能越过离散边界,掉进 -1、0、+1 这三个正确的坑里。一旦掉进去,前向输出就稳了,模型也就学会了。

华杉的技术博客 · 苏ICP备2026063680号-1
首页