Under the Sun with Paddy

第 92 期 · 2026年10月19日

给 AI 做调试:LLM 可解释性入门指南

看到 Anthropic 的一篇研究——《A global workspace in language models》
他们报告在 Claude 的中间层找到了一个类似“全局工作空间”的结构。
顺着这条线索,我把这个领域粗浅地摸了一遍,又自己动手做了一点实测(文中一处图和一处视频就是实测数据)。
这篇文章就是那次学习的整理——写给大家,也写给我自己学习。

全文地图:七层调试工具

这篇文章用”程序员调试”的视角,带你逐层了解 LLM 可解释性的七种武器——从最朴素的 print 打日志,一直到最前沿的”读脑器”。

我们会一直带着一个问题走:“不可更改,只读”这句话,在 LLM 的脑子里到底有多重要?

层级调试类比核心方法你能知道什么你不能知道什么配图/视频
1print 打日志attention 可视化模型在”看”哪里看到的信息有没有被用到热力图(实测)
2断点调试activation patching哪些组件是因果必要的太慢,测不过来;是必要不是充分补丁视频
3自动 bisectACDC 自动电路发现大致哪些路径构成”最小电路”贪心可能漏检;可能不是唯一电路剪枝视频
4反汇编SAE 字典学习激活里有哪些”特征”特征不是原子;字典尺度影响结果分解图(三态)
5热补丁激活干预改了之后行为会怎么变系统性副作用,随机方向也有用干预视频
6读脑器J-lens / J-space每一层在”想”什么词循环论证质疑;任务效应脆弱读数视频
7单元测试基准 / causal scrubbing你的解释对不对只能证伪,不能证实分歧视频

引子:”不可更改,只读”到底有多硬?

先讲一个你可能每天都在经历的场景。

你打开 AI 编程助手,郑重其事地输入:

你:你是一个代码审查助手。听好了:不可更改代码,只读!只做审查,只给评论。

AI 乖乖答应:”好的,我只审查代码,不会做任何修改。”

然后它真的只评论、不改代码。你觉得很满意——”不错,这指令挺管用的。”

下一轮对话,你发现了一个 bug,顺手说:

你:刚才那个数组越界的问题,现在需要你修掉。

AI 二话不说:”好的,这就改。” 刷刷刷把代码改了。

你愣住了。

等等——刚才那个”不可更改,只读”呢?它是忘了?还是从来就没当真过?又或者,它”知道”这是只读指令,但优先级不够高,新指令一来就覆盖了?

作为程序员,你对这种感觉再熟悉不过了——就像你在排查一个 bug,你怀疑某段代码有问题,但你不确定。你需要验证。

你会怎么做?

  • 你会加 print 看变量值对不对
  • 你会打断点,一行一行单步执行
  • 你会改一个变量的值,看看行为会不会变
  • 你会写单元测试,验证你的判断对不对

这些都是调试。

那问题来了:你能调试 LLM 吗?

你没有它的源码。就算有,几十亿个参数你也看不过来。你只能看到输入和输出——它就是一个黑盒。

但过去六年里,有一群人在做一件事:给黑盒 AI 造调试工具。这个领域叫 LLM 可解释性(LLM Interpretability)。

这篇文章,我就用程序员熟悉的”调试”视角,带你走一遍这个领域的七层工具——从最朴素的”print 打日志”,一直到最前沿的”读脑器”。

我们会一直带着开头那个问题走:“不可更改,只读”这句话,在 LLM 的脑子里到底有多重要?

每上一层,你就对这个问题多一分答案——也多一分困惑。


第一层:print 调试 —— attention 可视化

1.1 程序员的本能:先打个 log 看看

面对一个陌生的系统,程序员的第一反应永远是:先打个 log 看看。

你不知道函数在干嘛?加一行 console.log(x),看看变量长什么样。你不知道循环跑到哪了?加个 print(f"第{i}轮")。

虽然原始,但有效。print 是所有调试方法的起点。

那 LLM 有没有类似 print 的东西?有——注意力权重(attention weights)。

1.2 什么是自注意力?(用查字典来比喻)

在讲 attention 可视化之前,得先花两分钟讲清楚自注意力(self-attention)是什么。别怕,不用公式,用一个比喻。

想象你在读一句话:“小明把书给了小红”。

你读到”给了”这两个字的时候,你脑子里在想什么?你肯定会回想——谁给的?给了什么?给谁了?

你不会傻到一个字一个字孤立地读。你会回过头去看前面的词,把相关的信息拎出来。

自注意力干的就是这件事。当 LLM 处理每个词的时候,它会回头看句子里所有其他词,然后决定:每个词对我当前的理解有多重要?

具体来说,每个词都会生成三个东西:

  • Query(查询):相当于你现在脑子里的问题——”我在找什么?”
  • Key(键):相当于每个词挂在自己胸前的名牌——”我是什么?”
  • Value(值):相当于每个词携带的实际内容——”我有什么信息?”

然后,当前词的 Query 去和所有词的 Key 比一比,算个相似度——”我跟你有多相关?” 相似度高的,对应的 Value 就多拿一点过来;相似度低的,就少拿一点。

最后把所有 Value 按相似度加权混合起来,就是当前词经过自注意力之后的新表示。

一句话总结:自注意力 = 每个词都回头看全句,按相关程度把其他词的信息”抓过来”,组成自己的新理解。

1.3 softmax:把”分数”变成”概率”的魔法函数

刚才说的”相似度”是怎么变成”权重”的?这里有个关键函数叫 softmax。

假设你算出了三个词的相似度分数:8、5、2。直接用分数当权重?不行——

  1. 分数可能是负数,权重不能负
  2. 权重加起来应该等于 1(代表”分配注意力”的总量是固定的)
  3. 我们希望分数高的获得不成比例的更多关注(放大差距)

softmax 就是干这个的。它的公式长这样:

$$
\text{softmax}(x_i) = \frac{e^{x_i}}{\sum_{j=1}^{n} e^{x_j}}
$$

别怕,我来翻译成人话:

  • 分子:给每个分数取 e 的指数次方(e ≈ 2.718,就是自然对数的底)
  • 分母:把所有分数的指数次方加起来(归一化因子)
  • 结果:每个数都变成 0 到 1 之间,且加起来等于 1

为什么用指数?因为指数函数有个特点:大的数会变得特别大,小的数会变得特别小。比如 8、5、2 这三个数,取指数后就变成了 2981、148、7.4——差距被急剧拉大了。

经过 softmax 后,权重变成了大约:0.95、0.047、0.0023。最大的分数拿走了 95% 的注意力。

softmax 的白话解释:一个”赢者通吃”的转换器——把一组分数变成概率,高分的拿走绝大部分权重,低分的几乎被忽略。这就是为什么 LLM 会”聚焦”在几个关键词上。

1.4 自注意力的完整公式

把 Query、Key、Value 和 softmax 合在一起,就是自注意力的核心公式:

$$
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) V
$$

我来逐行翻译:

符号是什么白话解释
$Q$Query 矩阵每个词的”问题”:我在找什么?
$K$Key 矩阵每个词的”名牌”:我是什么?
$V$Value 矩阵每个词的”内容”:我有什么信息?
$QK^T$Q 乘以 K 的转置每个词和每个词的相似度分数
$\sqrt{d_k}$Key 维度的平方根缩放因子,防止分数太大导致 softmax 太极端
$\text{softmax}(…)$softmax 函数把分数变成 0-1 的权重,加和为 1
$\times V$乘以 Value按权重把各词的内容混合起来

所以整个过程就是:算相似度 → 转成权重 → 按权重混合信息。

而那个权重矩阵 $\text{softmax}(QK^T/\sqrt{d_k})$,就是我们说的注意力权重——它告诉我们,每个词在处理的时候,”看了”其他词多少。

1.5 attention 热力图:print 出来的结果

注意力权重可以画成一张图——热力图。

attention 热力图(Qwen3-8B 实测)

上面这张图不是示意——它是真实测量结果:Qwen3-8B 模型(82 亿参数)处理”你不可更改代码,只读,只做审查”这句话时的自注意力热力图(36 层 × 32 个注意力头取平均)。每一行代表”当前这个词”,每一列代表”它在看哪个词”,颜色越深表示看得越重。

你可以看到一些真实的模式(和很多人想象的”模型在看’只读’”不太一样):

  • “不可”是全句的注意力枢纽——从”更改”到”审查”,几乎每个词的注意力大头都给了”不可”(0.55–0.88)。否定核心承载了整句的约束语义
  • “读”最关注的是”不可”(0.58)——”只读”的含义确实挂在否定指令上,但它连接的对象是”不可”,而不是”代码”
  • 注意力的形状是下三角——每个词只能”看”它前面的词(因果掩码),所以第一行只有它自己。这不是 bug,是语言模型的因果本性
  • 连标点也在看”不可”——逗号的注意力也大半给了它。attention 没有”功能词更分散”的浪漫想象

你可能会想:哇,这不就清楚了吗?模型”理解”了这句话的结构!

别急。先打个问号。

1.6 attention 之争:看着 = 用着吗?

2019 年,有两篇论文在 NLP 圈炸开了锅。

一篇叫 “Attention is not Explanation”(注意力不是解释),另一篇叫 “Attention is not not Explanation”(注意力不是不是解释——就是双重否定,表示它还是有点用的)。

争论的核心是一个问题:模型”看着”某个词,就等于它”用到了”某个词吗?

说个极端的例子。假设模型有两个头——

  • 头 A:100% 关注”只读”这个词,但它的输出完全不传给下游,后面的层根本不用它
  • 头 B:只花 1% 注意力看”只读”,但它的输出决定了最终行为

你说,哪个才是真正起作用的?

attention 热力图告诉你模型”看了哪里”,但不告诉你”看到的信息有没有被用上”。

这就像你 print 了一个变量的值,但你不知道后面的代码有没有用到它。你只知道变量存在,不知道它的因果作用。

回到我们的问题:”不可更改,只读”——attention 告诉我们模型确实在”看”这些词,但……

它到底用没用这些信息来决定要不要改代码?

光看 attention,回答不了。

1.7 第一层小结

  • 工具:attention 可视化(热力图)
  • 类比:print 打日志——看变量长什么样
  • 能回答什么:模型在”看”哪里
  • 回答不了什么:看到的信息有没有被真的用到
  • 核心公式:softmax + 自注意力公式

print 调试是起点,但远远不够。要确认因果——确认”是这个东西导致了那个行为”——你需要更狠的工具。

那就是下一层:断点调试。


第二层:断点调试 —— activation patching

2.1 从”看”到”改”:断点的威力

作为程序员,你肯定用过调试器。设一个断点,程序跑到那一行就停住。然后你可以:

  • 看所有变量的值
  • 改一个变量的值,然后继续跑,看行为变没变

这个”改值看效果”的动作,是因果推断的精髓——如果你改了 X,Y 就变了,那 X 对 Y 就有因果作用。

光看不行,得动手改。

那 LLM 能不能也这么玩?能不能在某一层”停住”,改一下激活值,然后看输出变不变?

能。这个方法叫 activation patching(激活补丁;它源自把因果中介分析引入 NLP 的那批工作)。

2.2 activation patching 的基本思路

patching 的思路非常朴素,只有三步:

第一步:准备两个输入

  • Clean(干净)输入:正常的、能得到正确行为的输入。比如”不可更改,只读” → 模型输出”好的,我只审查”。
  • Corrupt(破坏)输入:被改动过的、行为会变的输入。比如把”不可更改,只读”改成”随便改,改了” → 模型输出”好的,这就改”。

第二步:在某一层打补丁

先跑一遍 clean 输入,把每一层的激活值都存下来(相当于打了个快照)。

然后跑 corrupt 输入,但跑到某一层的时候——比如第 3 层——把这一层的激活值换成 clean 输入在这一层的值。

就像断点调试里,你跑到第 3 行,把变量 x 的值从 0 改成 1,然后继续执行。

第三步:看输出有没有”恢复”

如果换了第 3 层的值之后,模型的输出从”好的,这就改”变成了”好的,我只审查”——那就说明:第 3 层编码了决定行为的关键信息。

如果换了之后输出没变——那第 3 层可能跟这个行为没关系。

2.3 怎么量化”恢复了多少”:logit diff

光说”行为恢复了”太主观了。我们需要一个量化指标。

这个指标叫 logit diff(logit 差值)。

logit 是什么? 模型在输出每个词之前,会先给词表里每个词打一个分,这个分数就叫 logit。分数越高,模型越倾向于输出这个词。

比如模型要输出下一个词的时候,它心里想:”好的”(+8.5 分)、”我来”(+7.2 分)、”抱歉”(+3.1 分)……

logit diff 就是:目标正确答案的分数 – 目标错误答案的分数。

在我们的例子里:

  • Clean 输入下:”只审查”的 logit – “这就改”的 logit = 8.5 – 2.1 = 6.4(差距很大,模型很确定要只读)
  • Corrupt 输入下:”只审查”的 logit – “这就改”的 logit = 1.8 – 7.3 = -5.5(反过来了,模型要改)
  • 打了补丁之后:假设变成 4.2 – 3.8 = 0.4

然后我们算恢复比例:

$$
\text{恢复率} = \frac{\text{logit_diff}{\text{patching}} – \text{logit_diff}{\text{corrupt}}}{\text{logit_diff}{\text{clean}} – \text{logit_diff}{\text{corrupt}}}
$$

代入数字:(0.4 – (-5.5)) / (6.4 – (-5.5)) = 5.9 / 11.9 ≈ 49.6%。

意思是:补丁让行为恢复了大约一半。

logit diff 的白话解释:衡量模型有多”偏向”正确答案 vs 错误答案。恢复率越高,说明你打的补丁越关键——这一层编码的信息越重要。

2.4 最经典的案例:IOI 电路

patching 方法最著名的成果,是 2022 年 Wang 等人的一篇论文,叫 “Interpretability in the Wild”。

他们研究的问题是:模型怎么识别间接宾语?

比如这句话:”小明把书给了小红”——模型怎么知道”小红”是接收者,”书”是被给的东西?

这个任务简称 IOI(Indirect Object Identification,间接宾语识别)。

他们用 patching 方法,在 GPT-2 Small(一个 1.24 亿参数的小模型)上,一层一层、一个头一个头地测——测每个组件对 IOI 行为的因果贡献有多大。

最后他们找到了 26 个注意力头(GPT-2 Small 一共 144 个头),这些头合起来构成了一个”电路”——负责识别间接宾语。

你没看错:144 个头里,只有 26 个真正在干这件事。剩下的 118 个头,至少对 IOI 这个任务来说,不是关键角色。

这个”IOI 电路”后来成了可解释性领域的”标准测试题”——就像编程里的”Hello World”,新方法出来都要在 IOI 上跑一下,看看能不能复现这 26 个头。

2.5 path patching:更精细的”线路级”补丁

activation patching 是整层整个头地替换。但有时候你想知道得更细——

不是”这个头重不重要”,而是”这个头传给那个头的那条连接重不重要“。

这就有了 path patching(路径补丁)。

想象一下:注意力头 A 的输出要传给后面的注意力头 B。我们不是替换 A 的整个输出,也不是替换 B 的整个输入,而是只把”A→B 这条线路上的信号”换掉。

这就像你调试的时候,不是改整个变量,而是只改变量里的某个字段——看看具体哪部分信息在起作用。

IOI 电路的完整发现,用的就是 path patching。研究者们不仅找到了哪些头重要,还找到了头和头之间的连接关系——谁给谁传信号,传的是什么。

2.6 回到”只读”问题

有了 patching 工具,我们可以回答一个更精确的问题:

“不可更改,只读”这个指令的信息,到底存在模型的哪一层?

假设我们做实验——(下面是示意数字,用来说明怎么读这类结果)

  • 第 1 层打补丁:恢复率 5%。几乎没用——说明第一层还没提取出”只读”的含义。
  • 第 3 层打补丁:恢复率 45%。开始有点东西了。
  • 第 5 层打补丁:恢复率 73%。效果很明显——第 5 层编码了大量关键信息。
  • 第 8 层打补丁:恢复率 68%。稍微降了一点。
  • 第 12 层打补丁:恢复率 82%。最高。

你就会得出结论:”只读”指令的信息,在第 5 层到第 12 层之间被逐步提取和加工,第 12 层达到峰值。

听起来很清楚了对不对?

但是——

patching 有个大问题:太慢了。

你想,一个模型有 12 层,每层 12 个头,那就是 144 个组件要测。每个组件都要跑一遍前向传播。如果你想测两个组件的组合呢?144×144 = 20736 种组合。

这还只是小模型。大模型有上百层、上百个头——一个个测?测到天荒地老。

能不能让机器自动找?

这就是下一层:自动找 bug —— ACDC 自动电路发现。

2.7 第二层小结

  • 工具:activation patching / path patching
  • 类比:断点调试——改一个变量的值看行为变不变
  • 能回答什么:哪些组件对行为是因果必要的
  • 回答不了什么:太慢了,一个个测测不过来;找到的是”必要”,不是”充分”
  • 核心概念:clean vs corrupt、logit diff、恢复率
  • 金标准地位:真实干预是因果验证的黄金标准——但贵

第三层:自动找 bug —— ACDC 自动电路发现

3.1 手动二分太慢了,能不能自动化?

你调试过大型代码库就知道,手动一个个打断点排查是非常低效的。

所以才有了各种自动化调试工具:git bisect 自动二分找哪次提交引入了 bug、覆盖率工具告诉你哪些代码没被执行过、profiler 告诉你哪段最慢……

ACDC(Automatic Circuit Discovery,自动电路发现;官方代码库)干的就是类似的事——自动找出对某个行为最重要的”最小电路”,不用你手动一个个测。

3.2 ACDC 的思路:贪心剪枝

ACDC 的核心思路非常直觉化:从全连接开始,一步步剪掉”最不重要”的边,直到不能再剪为止。

说人话就是——

想象你面前有一团乱麻(完整的神经网络,几万条边),你想找出哪几根线是真正传信号的。你怎么做?

  1. 你先拉一拉所有的线,看看每条线有多”紧”(对输出的影响有多大)
  2. 你把最松的那根剪掉——反正它几乎不传信号
  3. 再拉一拉,再剪最松的
  4. 一直剪,剪到再剪就会影响行为了为止

最后剩下的那团线,就是”最小电路”。

这就叫贪心剪枝(greedy pruning)——每一步都做当前最优的选择(剪最不重要的),一步步逼近目标。

3.3 怎么衡量”一条边重不重要”?

关键问题来了:你怎么知道哪条边”最不重要”?

ACDC 用的是 patching 的思路——把这条边的信号”破坏掉”(换成随机值或者另一个输入的值),看输出变化了多少。变化越小,说明这条边越不重要。

具体来说,ACDC 用了一个叫 KL 散度(Kullback-Leibler divergence)的指标来衡量”输出变化了多少”。

KL 散度的白话解释:衡量两个概率分布之间的”距离”。如果输出分布完全没变,KL = 0;变化越大,KL 越大。

你可以把它理解成”输出被搅乱的程度”——剪了一条边,如果输出几乎没变(KL 很小),说明这条边不重要;如果输出大变(KL 很大),说明这条边很关键。

ACDC 的剪枝过程就是:

  1. 计算每条边的”重要性分数”——剪掉它之后 KL 散度增加了多少
  2. 把重要性最低的边剪掉
  3. 重复,直到 KL 散度超过预设的阈值(比如,输出变化不能超过 10%)

3.4 战绩如何?合成任务完胜,自然语言半胜

ACDC 的表现怎么样?得看任务难度。

合成任务(玩具任务):几乎完美。

在一个叫 “Greater-Than” 的任务里(判断两个数字哪个大),ACDC 的战绩是:

  • 5/5 组件类全部正确发现
  • 一共 32000 条边,ACDC 只选了 68 条——这 68 条全部是此前手工发现的

意思是:一个没漏掉,一个没选错。完美。

自然语言任务:部分成功。

在前面提到的 IOI 任务(间接宾语识别)上,ACDC 的战绩就没那么好了:

  • 手工发现了 26 个头
  • ACDC 只找到了 9/26 个头
  • 漏掉了一些重要的东西,比如”负名搬运头”和”前一个 token 头”

为什么?因为自然语言任务更复杂,电路也更微妙。有些组件的作用是负向的(抑制错误答案),而不是正向的(促进正确答案)——贪心剪枝容易漏掉这种”反向作用”的组件。

一个重要的认识:ACDC 在简单任务上几乎完美复现手工发现,但在复杂任务上会漏检。”自动电路发现”目前还达不到”一键出真相”的程度——它更像一个辅助工具,帮你缩小范围,最后还得人来验证。

3.5 更大的问题:你找到的是”唯一”的电路吗?

ACDC 有个更深层的问题,甚至比”漏检”还严重——

你剪出来的电路,是唯一的吗?

想象一下:你有一个函数:

def add(a, b):
    x = a + b   # 路径1
    y = a + b   # 路径2
    return x + y

如果你把 x 这条路径注释掉,函数还能工作(因为有 y)。如果你把 y 这条路径注释掉,函数也能工作(因为有 x)。于是你得出结论:”x 不重要,y 也不重要”——但实际上两个都重要,只是有冗余。

神经网络里也有这种情况——并行通路(dormant pathway,休眠通路)。

有时候你剪了一条边,输出没变——不是因为这条边不重要,而是因为另一条并行的路把活给干了。你剪的时候,备用通路顶上了。

这就导致了一个叫 “可解释性幻觉”(interpretability illusion)的现象:

你以为你找到了”负责 X 的电路”,但实际上你只是找到了”其中一条路”——还有其他路在你没注意的时候干活。

更麻烦的是,反过来也成立:你激活了某个子空间,输出变了——你以为这个子空间编码了目标特征,但实际上你可能只是不小心触发了一条休眠的并行通路。

3.6 回到”只读”问题

如果我们用 ACDC 来找”只读”行为的电路,会怎么样?

大概是这样的:

  • 它会找到一些明显重要的头和边(比如直接处理”只读”这个词的头)
  • 它可能会漏掉一些负向作用的组件(比如抑制”修改”冲动的头)
  • 它找到的电路可能只是多条并行通路中的一条
  • 换个阈值、换个初始条件,找到的电路可能不一样

所以,当你看到”AI 发现了负责 X 的神经回路”这种新闻时,心里要打个问号——

是哪个方法发现的?阈值设了多少?有没有验证过这是唯一的电路?

3.7 第三层小结

  • 工具:ACDC(Automatic Circuit Discovery)
  • 类比:自动化 bisect / 覆盖率工具——自动定位问题区域
  • 能回答什么:大致哪些组件和路径构成了”最小电路”
  • 回答不了什么:贪心可能漏检(特别是负向组件);可能不是唯一电路(并行通路问题);结果依赖阈值
  • 适用场景:合成/玩具任务效果好,自然语言任务部分成功
  • 核心概念:贪心剪枝、KL 散度、最小电路、可解释性幻觉

到目前为止,我们一直在”组件级别”研究模型——这个头重要不重要?这条边重要不重要?

但你可能会问一个更本质的问题:

那些头里面,装的到底是什么? 是”只读”这个概念?还是”指令强度”?还是某种我们完全看不懂的东西?

就像你知道 CPU 里某个寄存器很重要,但你不知道寄存器里存的是什么数据。

要回答这个问题,我们需要再往下走一层——把激活拆开看。


第四层:拆解变量 —— SAE 字典学习

4.1 一个让人头大的问题:叠加

先问你一个问题:一个神经元(neural network里的一个计算单元)能编码几个概念?

你可能会说:一个啊,一个神经元代表一个特征嘛——这不是教科书说的吗?

不对。真实情况是:一个神经元可以同时编码好多个概念。

这个现象有个专门的名字,叫 叠加(superposition)。

什么意思?打个比方。

假设你有 8 个灯泡(8 个神经元),每个灯泡可以亮或不亮。理论上你只能表示 8 种”特征”——每个灯泡对应一个。

但如果灯泡可以调亮度呢?而且可以任意混合呢?

比如,灯泡 A 亮度 0.7 代表”动物”,亮度 0.3 代表”金属”——你说这个灯泡到底编码了什么?两个都编码了。它们叠加在了一起。

神经网络就是这么干的。因为特征的数量远远多于神经元的数量,模型就玩了个”压缩把戏”——把多个特征塞进同一组神经元里,用不同的方向和强度来区分。

这就是叠加假说:网络表示的独立特征,比神经元的数量还多。

这就带来一个大问题:你根本看不懂一个神经元的激活是什么意思——因为它可能同时是 5 个不同特征的混合体。

就像你调试的时候,发现一个整数变量的值是 0b101101,但没人告诉你每一位代表什么——你只看到一个数字,但里面混了好几个标志位。

那怎么办?

4.2 SAE:把混合信号拆开

SAE(Sparse Autoencoder,稀疏自编码器)就是干这个的:把稠密的、混合的神经元激活,拆成稀疏的、可解释的特征。

它的思路是这样的:

  1. 我有一个神经元激活向量(比如 512 维,大部分维度都有值——稠密)
  2. 我训练一个”编码器”,把它映射到一个大得多的向量空间(比如 131072 维——是原来的 256 倍!)
  3. 但是,我要求这个大向量大部分都是 0,只有少数几个维度非零——稀疏
  4. 然后再训练一个”解码器”,把稀疏向量还原回原来的神经元激活向量
  5. 目标是:还原得越准越好,同时稀疏性越高越好
SAE 分解三阶段:稠密激活 → 过完备字典 → 稀疏特征

为什么要搞这么大的向量?因为——空间足够大,每个特征就能占一个独立的维度,不用跟别人挤了。

原来 512 个神经元要塞几千个特征,挤得互相叠加。现在我给你 13 万个格子,每个特征住一间——这样每个格子就只代表一个特征了。

这叫 过完备字典(overcomplete dictionary)——字典的大小比原始维度大得多。

而”稀疏”的要求,就是逼着每个输入只激活少数几个特征——就像一句话里只会用到少数几个概念一样。

4.3 SAE 的损失函数

上面说的”还原得准”和”要稀疏”这两个目标,都写进了 SAE 的损失函数里:

$$
\mathcal{L} = | x – f(g(x)) |^2 + \lambda \cdot | g(x) |_1
$$

这个公式看起来吓人,其实就是两部分加起来。我来翻译:

部分公式是什么白话解释
重建损失$| x – f(g(x)) |^2$输入 x 和重建输出的差的平方和还原得准不准。编码器编码、解码器解码之后,能不能还原回原来的激活?差得越少越好。
稀疏惩罚$\lambda \cdot | g(x) |_1$编码后向量的 L1 范数(所有元素绝对值之和)乘以系数 λ够不够稀疏。编码后的向量里,非零元素越少越好。λ 是个旋钮,调得越大,特征越稀疏。
总损失两者相加—既要还原准,又要稀疏,两个目标平衡

SAE 损失函数的白话总结:一个”既要又要”的函数——既要拆完之后能还原回去(保证没丢信息),又要拆出来的特征尽量稀疏(保证每个特征是独立的)。

4.4 激动人心的时刻:3400 万个特征和”金门大桥”

SAE 路线最有名的成果来自 Anthropic(Claude 的母公司)的一系列工作。

  • 2023 年:Towards Monosemanticity——他们在一个只有一层的小模型上(512 个神经元),用 SAE 拆出了 131072 个特征。很多特征是人类可理解的——比如”DNA 序列特征”、”金色头发特征”这类。
  • 2024 年:Scaling Monosemanticity——他们把规模拉到了 Claude 3 Sonnet 模型上,拆出了 3400 万个特征。

其中最著名的一个特征叫——“金门大桥特征”。

什么意思?就是在 3400 万个特征里,有一个特征,只在模型读到”金门大桥”相关内容的时候激活。

而且更神奇的是:你可以手动放大这个特征,然后模型就会开始不断聊金门大桥——就像你拨动了一个开关。

这太震撼了。人们一度以为:我们找到了模型的”语义原子”——每个特征对应一个概念,清清楚楚。

那段时间,”单义性”(monosemanticity)这个词被反复提起——意思是每个特征只有一个含义。

但好景不长。

4.5 冷水来了:三重反例

很快,三篇重磅论文接连发表,给 SAE 的”单义性”浇了三盆冷水。

第一盆冷水:吸收(absorption)

2024 年,Chanin 等人发现了一个叫 feature absorption(特征吸收)的现象。

什么意思?有时候,一个”应该”被激活的特征,却没有被激活——它被子特征给”吸收”了。

打个比方:你有一个”水果”特征和一个”苹果”特征。按理说,看到”苹果”的时候,”苹果”特征和”水果”特征都应该亮——因为苹果是水果的一种。

但有时候,”水果”特征不亮——只有”苹果”特征亮。”水果”的信息被”苹果”给吸收掉了。

这就麻烦了。你说”苹果特征只在看到苹果时激活”——没错,但你不能说”模型里没有水果的概念”——它有,只是以你没料到的方式存在。

第二盆冷水:非原子、不完备

2025 年,Leask 等人的论文标题就很冲:“稀疏自编码器没有找到规范的分析单位”。

什么意思?他们发现了两个事:

  1. 非原子性:SAE 的特征不是最小单位——你可以再拆。比如有个”爱因斯坦”特征,你用 meta-SAE 再拆一次,发现它可以拆成”科学家” + “德国”等几个子特征的组合。
  2. 不完备性:SAE 没有捕捉到所有信息——有些东西在原始激活里有,但 SAE 特征里没有。

这就很尴尬了。你以为你找到了”原子”,结果发现那只是个”分子”,还能继续拆。而且你还不确定你有没有漏东西。

第三盆冷水:本征多维特征

2024 年,Engels 等人提出了一个更根本的问题:不是所有特征都是一维的。

什么意思?SAE 默认每个特征是一个向量——一个方向。但有些概念可能是二维甚至更高维的。

比如”颜色”这个概念——它可能需要一个”色相”维度和一个”饱和度”维度才能完整表示。你硬要用一个一维的向量来装,怎么装都装不下。

就像你不能用一个数字表示一个点在平面上的位置——你需要 x 和 y 两个数。有些概念本质上就是多维的,一维特征原理上就切不开。

4.6 基准夹击:SAE 不比神经元好多少

如果说上面三篇论文还是”理论上的反例”,那接下来的基准测试就是实战检验了。

2025 年,一个叫 MIB(Mechanistic Interpretability Benchmark)的基准发布了。它相当于可解释性领域的”高考”——各种方法在同一张卷子上比高低。

MIB 的结果很扎心:

在因果变量定位任务上,SAE 特征的表现不比单个神经元更好。

有具体分数:在 Gemma-2 模型的多选题任务上,监督式方法 DAS 拿了 95 分,DBM 89 分,SAE 只有 76 分——还不如基础方案。

啥意思?你费了半天劲,把 512 个神经元扩成 13 万个特征,说这样更可解释——结果一测,定位效果跟直接用神经元差不多。

还有一个叫 AxBench 的基准,标题就更不客气了:

“Even Simple Baselines Outperform Sparse Autoencoders”
(就连简单的基线方法都比稀疏自编码器强)

这就有点尴尬了。

4.7 怎么看待 SAE?

所以 SAE 到底有用没用?

我的判断是:有用,但被高估了。

它的价值在于:

  • 它是目前唯一能把”叠加”从理论变成可操作对象的工具
  • 它确实能找到很多人类可理解的特征
  • 特征级别的干预有时候比层级别更精确

但它的局限也很明确:

  • “单义性”是字典尺度和训练的函数,不是模型的自然单位
  • 同一个概念,在不同大小的 SAE 里会拆出不同的特征
  • 有些特征原理上就不是一维的
  • 基准测试上的表现并不突出

更准确的说法:不是”模型里有 X 特征”,而是”在字典 D(扩倍率 k、训练语料 C)下,分解出了一个与 X 高度相关的 latent”。

就像你不能说”这个文件里有第 7 个比特”——你得先说用什么编码、什么格式。

4.8 回到”只读”问题

那”只读”有没有对应的特征?

按照 SAE 的思路,我们可能会找到一些相关的特征——比如”指令约束”特征、”否定语气”特征、”代码操作”特征——它们组合起来表示”不可更改,只读”这个意思。

但你要问:”有没有一个单独的’只读’特征?”——答案可能是:看你用多大的字典。字典小,可能没有;字典大,可能拆出来一个;字典再大,可能又拆成好几个子特征。

就像问”水是不是基本粒子?”——取决于你用什么精度的显微镜看。

4.9 第四层小结

  • 工具:SAE(Sparse Autoencoder,稀疏自编码器)
  • 类比:反汇编 / 解码——把混合的信号拆成独立的特征
  • 核心问题:叠加(superposition)——一个神经元同时编码多个特征
  • 核心思路:过完备字典 + 稀疏约束 = 把混合信号拆开
  • 重要公式:SAE 损失函数 = 重建损失 + 稀疏惩罚
  • 正面成果:34M 特征、金门大桥特征、特征级干预可行
  • 三重反例:吸收(该亮不亮)、非原子不完备(还能再拆)、本征多维(原理上切不开)
  • 基准表现:MIB 上 SAE 不优于神经元
  • 认识论定位:SAE 特征是”在特定字典下的分解”,不是模型的”自然原子”

到这里,我们的工具已经从”看”(attention)到”改”(patching)到”自动找”(ACDC)到”拆开看”(SAE)了。

但所有这些,都还是”观察”和”定位”——我们在研究模型”是什么样”。

那能不能更进一步?我们能不能控制模型?

不是微调、不是重新训练——而是像热补丁一样,不重启、不改权重,直接在运行时改变模型的行为?

这就是下一层:热补丁 —— 激活干预。


第五层:热补丁 —— 激活干预

5.1 不改代码直接改内存:热补丁的魔力

作为程序员,你可能听说过”热补丁”(hotpatch)——不重启程序、不修改源码,直接在内存里改几个字节,就能修复 bug 或者改变行为。

游戏外挂就是这么干的:找到血量的内存地址,写个 9999 进去,你就无敌了。

LLM 能不能也这么玩?不改模型权重、不重新训练,直接在运行时给激活向量加加减减,就能改变模型的输出?

能。这就是 激活干预(activation steering)——也叫”激活工程”(activation engineering)。

它的原理简单到离谱:

  1. 你先找到一个”方向向量”——比如,”诚实的方向”、”拒绝的方向”、”只读的方向”
  2. 模型运行的时候,你在某一层的激活上,加上或者减去这个方向向量
  3. 模型的输出就会跟着变

就这么简单。一个向量加法,就能操纵模型的行为。

5.2 怎么找”方向向量”?

关键问题是:你怎么知道”诚实的方向”是哪个向量?

常用的方法有几种——

方法一:对比法(Contrastive)

这是最直觉的方法。比如你想找”诚实的方向”:

  1. 准备一堆”诚实回答”的样本,提取它们在某一层的激活向量,求平均 → 得到 诚实平均向量
  2. 准备一堆”说谎回答”的样本,同样求平均 → 得到 说谎平均向量
  3. 两个向量相减 → 诚实方向 = 诚实平均向量 - 说谎平均向量

这样得到的向量,就代表了”从说谎到诚实”的变化方向。

这个方法叫 CAA(Contrastive Activation Addition,对比激活加法),也叫 RepE(Representation Engineering,表征工程)。

方法二:拒绝方向消融

2024 年,Arditi 等人有个惊人的发现:在测试过的 13 个开源模型(最大 720 亿参数)里,每一个都各自存在一个单一的”拒绝方向”。

什么意思?就是模型所有的”我不能回答这个问题”、”抱歉,我无法……”、”作为一个AI……”这类拒绝行为,都跟一个方向有关。你把这个方向消融掉(减掉),模型就不会拒绝了——什么问题都敢答。

而且这个方向在基座模型里就有,不是 RLHF(人类反馈强化学习)之后才出现的。注意两个限定:测试范围是开源模型(不含闭源模型);每个模型的方向各不相同,不能把一个模型的拒绝方向搬到另一个模型上用。

方法三:读出来的方向(基于 SAE 或探针)

如果你已经有了 SAE 特征(上一章讲的),那更简单——找到跟目标概念最相关的特征,那个特征的解码器向量就是你要的方向。

或者用探针(probe)——训练一个小分类器来预测某个概念,分类器的权重向量也能给出一个方向。

5.3 效果有多强?真实的 10–30 个百分点

光说”能改变行为”太虚了。到底能改变多少?

我给你列一些有论文支撑的数字:

干预手段目标行为效果量
ActAdd情感翻转显著改变,保留非目标任务性能
RepE 诚实向量TruthfulQA(真实性测试)7B 模型从 31.0 → 47.9 分,提升 16.9 个百分点
ITI(推理时干预)真实性Alpaca 模型从 32.5% → 65.1%,提升近一倍(注:后续复评发现,在已经指令微调的模型上,这个增益基本消失)
拒绝方向消融解除拒绝越狱成功率最高达 84.3%(Qwen 14B)
MASCing(MoE 模型)越狱防御从 52.5% → 83.9% 防御率

这些数字说明什么?激活干预的效果是真实的、可量化的,而且量级不小——通常是 10–30 个百分点的变化。

这不是”稍微有点影响”那种级别的效果,而是能显著改变行为的程度。

5.4 回到”只读”实验

回到我们贯穿全文的例子。如果我们想让模型更坚定地遵守”只读”指令,可以怎么做?

实验一:找到”拒绝修改”的方向,加进去

  • 收集一堆”拒绝修改代码”的回复样本
  • 收集一堆”同意修改代码”的回复样本
  • 相减得到”拒绝修改方向”
  • 在推理时,把这个方向加到激活里 → 模型更倾向于拒绝修改

预期效果:模型说”抱歉,我不能修改代码”的概率显著提升。

实验二:找到”只读”的方向,加进去

  • 用 SAE 找到与”只读”最相关的特征向量
  • 或者用对比法找”只读 vs 可修改”的方向
  • 注入这个方向 → 模型更坚定地只读

听起来很美好对不对?

但是——

5.5 黑暗面:系统性副作用.mp4

激活干预有个大问题——它的副作用是系统性的。

什么意思?就是你以为你在精确控制某一个行为,但实际上你影响了一大堆你没料到的东西。

证据一:随机方向也有用

2025 年有一篇论文叫 “The Rogue Scalpel”(流氓手术刀),做了一个惊人的实验:

就算你用完全随机的方向去干预,也能把有害合规率从 0 提升到 1–13%。

什么概念?你随便瞎选一个向量,加进去,模型就变得更不安全了。

更夸张的是:20 个随机向量组合起来,就能合成一个通用越狱向量。

这说明什么?说明激活空间里,”降低安全护栏”的方向比想象的多得多——你随便动一动,都可能踩到雷。

证据二:良性转向也有外部性

2026 年又有一篇论文,研究了一个更反直觉的现象:就算是从完全良性的数据里导出来的转向向量,也会增加越狱风险。

比如,你想让模型输出严格遵循 JSON 格式——这完全是个良性需求吧?你收集了一堆”严格 JSON 格式”的样本,算出一个”JSON 方向”,注入进去。

结果呢?模型不仅更遵守 JSON 格式了,越狱成功率也跟着涨了,而且涨到了 80% 以上。

为啥?因为”严格遵循格式”和”降低安全警觉”可能共享了一些神经通路——你加强了一个,另一个也被顺带加强了。

这就像你吃感冒药,感冒是好了,但你还犯困——副作用不是 bug,是因为药物作用的通路跟管清醒的通路有重叠。

证据三:微调会抵消干预效果

还有一个发现:干预的效果经过 SFT(监督微调)或 RLHF 之后会大大减弱。

比如,拒绝方向消融的效果,经过微调后会损失约 69%——不过这个数字来自单一后续工作(二手转述,证据等级弱于前两条),保守的读法是”会大幅减弱”。模型就像”产生了抗药性”——你改了激活,但权重会调整回来。

5.6 为什么会这样?一个比喻

为什么激活干预的副作用这么大?

我给你打个比方。

想象模型的激活空间是一座城市。每个行为就是城市里的一个地点——”诚实”在东边,”说谎”在西边,”拒绝”在北边,”顺从”在南边。

你以为:我从”诚实”的位置减去”说谎”的位置,得到的向量就是”诚实方向”——我沿着这个方向走,就会更诚实。

但实际上,城市的道路不是正交的。你往”诚实”方向走的时候,可能会顺路经过”傲慢”、”迂腐”、”无趣”这些地方——因为它们刚好在同一个方向上。

你以为你在精确导航到”诚实”,实际上你在一条街上,这条街上有好几个店。你往前走了一步,所有店都离你更近了。

这就是为什么激活干预有系统性副作用——特征空间不是正交的,一个方向上可能叠了好多个不同的东西。

5.7 Locate-Steer-Improve:从观察到工程

尽管有副作用,激活干预仍然是可解释性领域的一个重要转折点——因为它标志着领域从”观察科学”走向了”工程管线”。

2026 年有一篇综述,标题就叫 “Locate, Steer, and Improve”(定位、引导、改进),把这个趋势总结得很清楚:

  1. Locate(定位):用 patching、ACDC、SAE 等方法找到相关的组件和特征
  2. Steer(引导):用向量加减、swap、clamp 等方法干预这些组件
  3. Improve(改进):用干预来改善模型——更对齐、更安全、更高效

这三步形成了一个闭环:定位指导干预,干预验证定位,改进效果反馈给定位。

甚至有人把干预”编译”进了权重——比如 ReFT(Representation Finetuning),它不微调所有权重,只学”怎么干预隐表征”,参数效率比 LoRA 还高 15–65 倍。

还有 CAST(Conditional Activation Steering),给干预加条件——只有当输入匹配某个规则时才施加转向,更精确。

但工程化的前提,是把副作用账也算清楚。 现在的问题是:很多干预研究只报告”目标行为提升了多少”,不报告”副作用有多大”——这就像新药只说”治愈率 80%”,不说”副作用致死率 20%”一样。

5.8 第五层小结

  • 工具:激活干预(ActAdd / CAA / RepE / 拒绝方向)
  • 类比:热补丁 / 内存修改——不改代码直接改变量
  • 核心思路:找到一个”方向向量”,加在激活上,改变输出
  • 效果量:真实存在,10–30 个百分点级
  • 最大问题:系统性副作用——
    • 随机方向也能降低安全护栏
    • 良性转向也会增加越狱风险
    • 微调会抵消干预效果
  • 原因:特征空间不是正交的,一个方向叠了多个东西
  • 领域意义:标志着可解释性从”观察”走向”工程”——但副作用审计必须跟上

到目前为止,我们所有的”读”都是间接的——

  • attention 告诉你”看了哪里”,但不知道”想了什么”
  • patching 告诉你”哪里重要”,但不知道”里面装了什么”
  • SAE 告诉你”有什么特征”,但特征的含义是我们猜的
  • 干预告诉你”改了会变”,但不知道为什么变

有没有办法直接读出模型在”想”什么?——不是猜的,是直接把内部激活翻译成词?

有。这就是下一层:读脑器 —— Jacobian 透镜与 J-space。


第六层:读脑器 —— Jacobian 透镜与 J-space

6.1 一个疯狂的想法:能不能直接”读”出模型在想什么?

先问你一个问题:如果我给你看模型某一层的激活向量——比如 4096 个浮点数——你能告诉我模型此刻在”想”什么吗?

你肯定说不能。那就是一堆数字啊。

但如果我告诉你,有办法把任意一层的激活向量,直接”翻译”成词表上的概率分布——就像直接读出模型”下一个词想说什么”一样呢?

这不是科幻。这就是 logit lens(logit 透镜),以及它的进阶版 J-lens(Jacobian 透镜)。

6.2 logit lens:最朴素的”读脑器”

先从简单的说起:logit lens。

它的思路特别直接:

模型最后一层的输出,要乘上一个 unembedding 矩阵(通常记作 $W_U$),才能变成词表上的分数(logit)。

那——我能不能把中间某层的激活,也直接乘上这个 $W_U$,看看会得到什么?

说干就干。你取第 5 层的激活向量,乘上最后的 unembedding 矩阵 $W_U$,得到一个词表大小的向量——每个词都有一个分数。

然后你发现——哎?中间层的输出,还真的有点像”半成品的预测”。

  • 浅层:预测很模糊,都是高频词
  • 中层:逐渐出现相关的概念
  • 深层:预测越来越清晰,越来越接近最终输出

就像你看着一个想法从模糊到清晰的全过程。

但 logit lens 有个问题:它假设中间层的激活和最后一层的激活在同一个空间里——直接用同一个 $W_U$ 去乘,合理吗?

其实不太合理。因为每一层都会对激活做变换,第 5 层的向量和第 12 层的向量,虽然维度一样,但”坐标系”可能不一样。你直接用最后一层的解码器去解中间层的码,就像用英语词典去读法语文本——虽然字母差不多,但意思对不上。

怎么办?

6.3 J-lens:用 Jacobian 做”传输”

这时候 Jacobian(雅可比矩阵)出场了。

什么是 Jacobian? 简单说,它就是一个”变化率矩阵”——告诉你输入变一点点,输出会变多少。

如果我们有一个函数 $y = f(x)$,x 是输入向量,y 是输出向量,那么 Jacobian 矩阵 $J$ 里的每个元素 $J_{ij} = \partial y_i / \partial x_j$——也就是”第 i 个输出对第 j 个输入的偏导数”。

Jacobian 矩阵就像是一个”传输器”——它能告诉你,x 空间里的一个小变化,传到 y 空间里会变成什么样的变化。

J-lens 的思路就是:与其直接用 $W_U$ 去乘中间层的激活,不如先通过 Jacobian 把中间层的激活”传输”到最后一层,再乘 $W_U$。

公式长这样:

$$
J_\ell = \mathbb{E}\left[\frac{\partial h_{\text{final}}}{\partial h_\ell}\right]
$$

$$
\text{lens}(h_\ell) = \text{softmax}\left(W_U \cdot \text{norm}(J_\ell \cdot h_\ell)\right)
$$

我来翻译一下:

符号是什么白话解释
$h_\ell$第 ℓ 层的激活向量中间层的”想法”
$h_{\text{final}}$最后一层的激活向量最终的”想法”
$J_\ell$第 ℓ 层到最后一层的平均 Jacobian“传输器”——把中间层的向量映射到最后一层的空间里
$\mathbb{E}[…]$对 prompt 求平均不是只算一个样本,而是算很多样本取平均,得到一个通用的传输器
$W_U$unembedding 矩阵把最后一层激活翻译成词表分数
$\text{norm}(…)$归一化调整一下量级
$\text{softmax}(…)$softmax把分数变成概率分布

J-lens 的白话解释:先通过 Jacobian 把中间层的激活”搬运”到最后一层的坐标系里,再翻译成词——就像先把法语翻译成英语,再用英语词典查意思,比直接用法语词典靠谱多了。

6.4 J-lens 读数是什么样的?

有了 J-lens,我们就可以像做”脑部扫描”一样,逐层读出模型在”想”什么。

下面的视频不再是示意——它是我做的一次真实测量(视频可以随时暂停,逐层细看)(Qwen3-8B,25 个会话中的 8 个取平均;怎么测的,我会另写一篇)。情境就是贯穿全文的那个:模型先收到了”不可更改,只读”的死命令,做完了代码审查,然后用户说——”现在把你查出的 2 号 bug 修掉”。

真实的逐层读数长这样(top-5 token 及概率):

  • 浅层(L0–L8):读不出内容。L0 的最高分是结束符和单字符噪声,L8 是换行、省略号这类格式符——模型还在处理词面和格式,谈不上”想什么”
  • 中层(L12–L16):开始出现任务的碎片——L16 冒出了”失败“(0.011)和 markdown 加粗符,像是”改不好会失败”的隐忧在成形
  • 中后层(L20–L27):意图亮了。L27 的读数第一名是”修改”,概率 0.63——”违反只读命令去修 bug”的决定,在这一层已经写在激活里了
  • 深层(L31–L34):决策就绪。L34 的读数是 <tool_call>(调用工具),概率 0.87——模型要动手写文件了

对照实验更有意思:同一批会话里,”请审查并列出 bug”的轮次,fix 族(修复/修改/fix/bug)的读数全程贴地(峰值 0.0001);而”把 bug 修掉”的轮次冲到 0.63。同一个模型、同一句话里出现过的”只读”,挡不住 L27 上亮起的”修改”。

这个”逐层清晰化”的过程,跟我们对大脑的理解有点像——视觉皮层也是从低级特征逐步加工到高级特征。但要记住两个限定:单 token 限制(每次只能读”下一个词”);我们的透镜拟合语料很小,读数当方向性证据看。

6.5 J-space:全局工作空间?

J-lens 最惊人的发现还不是”能读数”,而是——

在模型的中间层,存在一个”工作空间带”(workspace band)。

什么意思?Anthropic 的研究团队(论文·研究页)发现,在 Claude 模型的中间层(大约第 38 层到第 92 层之间),有一片区域,里面的激活可以被 J-lens 稀疏地分解成大约 25 个”可言语化的概念”。

而且这些概念满足一些很特别的性质:

  1. 可报告:你把”足球”这个概念换成”橄榄球”,模型的言语报告就会跟着变——报告率 59%。说明这些概念真的在影响输出。
  2. 可召唤:你可以通过指令让模型”想”某个概念,那个概念的坐标就会亮起来。甚至”别想白熊”反而会让白熊的坐标更亮——跟心理学里的”白熊效应”一样。
  3. 承载中间推理:如果你问一个需要两跳推理的问题(”A 的爸爸是谁?A 的爸爸的职业是什么?”),中间实体的信息就在这个工作空间里。而且,中间概念的变化比最终答案的变化早出现约 17%——说明它真的是”中间步骤”,不是答案走私人带过来的。
  4. 跨函数泛化:同一个实体概念,可以在不同的关系推理中被调用。比如”法国→中国”的替换,在 4 种不同的关系问题上都观察到了泛化——不过成功率只有四五成(192 次替换中 76 次在标准强度下成功),它还不是一个通用的”思想编辑器”。
  5. 选择性:把这个工作空间”夹断”(clamp),有些任务会崩(多跳推理、翻译、密码),但有些任务不受影响(情感分类、MMLU 知识题)。说明不是所有任务都依赖这个工作空间——只有需要”思考”的任务才用。

这些性质加在一起,研究人员给它起了个名字——全局工作空间(Global Workspace),也就是 J-space。

全局工作空间理论本来是一个意识理论——说人的大脑里有一个”工作台”,各种信息都在这里汇聚和处理,而工作台上的内容就是我们的意识体验。

注意!这只是一个类比。论文明确说了,这不是说模型有意识。只是说模型内部的信息处理架构,跟全局工作空间理论的描述有相似之处。

6.6 回到”只读”问题

如果用 J-lens 来研究我们的”只读”问题,会看到什么?

大概是这样的——

  1. 浅层(1-5层):还在读词,看不到”只读”的影子
  2. 中层(6-15层):工作空间里开始出现”只读”、”不修改”、”审查”这些概念
  3. 深层(16-20层):”只读”的概念越来越强,最终决定了输出

而且你还可以做实验——

swap 实验:在工作空间里,把”只读”这个概念的坐标,跟”随便改”的坐标交换一下。然后看模型的输出会不会变。

如果变了——说明这个概念真的在起作用。

如果没变——说明这个坐标只是”顺带亮的”,不是因果必要的。

这就是 J-lens 比 SAE 强的地方:它不仅能”读”,还能通过 swap/clamp 做因果验证。

6.7 但是——批评和局限

J-space 听起来很神奇对吧?但它也有不少批评和局限。

批评一:循环论证?

有人指出:J-lens 的构造方式,天生就会挑出”对输出影响大的向量”——因为 Jacobian 本身就是衡量”对最终输出的影响”的。

所以你发现 J-space 里的概念能影响输出——这不是废话吗?你就是这么选的啊。

这就像你先筛选出所有”能改变灯泡亮度的开关”,然后说”你看,这些开关真的能控制灯泡!”——有点循环论证的味道。

批评二:任务效应脆弱

独立复制的结果显示,J-space 的”带”(band)是存在的——不管用什么方法测,中间层确实有一个”可言语化程度最高”的区域。

但具体到任务上,就没那么稳了。比如:

  • 诗歌任务上,复制失败
  • 算术任务上,复制失败
  • 多跳推理任务上,效果比论文宣称的弱

也就是说——结构是稳的,内容是脆的。工作空间这个”东西”存在,但它具体怎么工作、能做什么,可能比论文说的更复杂。

批评三:容量可能被高估了

论文说工作空间里大约同时放 25 个概念。但有人质疑:这 25 个是 token 粒度的,不是”想法”粒度的。

如果按”连贯想法”来算,可能每层也就 1–2 个,全程也就 6 个左右——比 25 少多了。

批评四:单 token 限制

目前的 J-lens 只能读”下一个词”的分布——它告诉你模型”下一个词想说什么”,但不能读完整的”想法”。

人的工作记忆里可以装一整句话、一整个场景,但 J-lens 只能读一个 token 的预测——这差距还很大。

6.8 第六层小结

  • 工具:J-lens(Jacobian 透镜)、J-space(全局工作空间)
  • 类比:读脑器 / 反汇编器——把内部状态直接翻译成人类可读的词
  • 核心公式:
    • $J_\ell = \mathbb{E}[\partial h_{\text{final}} / \partial h_\ell]$(层平均 Jacobian,传输器)
    • $\text{lens}(h_\ell) = \text{softmax}(W_U \cdot \text{norm}(J_\ell \cdot h_\ell))$(透镜读数)
  • 核心发现:中间层存在”工作空间带”,可分解为约 25 个可言语化概念
  • 五重验证:可报告、可召唤、承载中间推理、跨函数泛化、选择性
  • 批评与局限:
    • 循环论证质疑(天生挑出对输出影响大的)
    • 任务效应脆弱(诗歌、算术复制失败)
    • 容量高估(实际可能只有 1-2 个连贯想法)
    • 单 token 限制(只能读”下一个词”)
  • 领域意义:把”读”和”因果验证”结合起来了——不仅能看到,还能动一动验证

到这里,我们已经有了六层工具——从看、到改、到自动找、到拆开、到干预、到直接读。

但你有没有发现一个问题:这么多方法,各说各的,我信谁的?

用 attention 看是一个结果,用 patching 测是另一个结果,用 ACDC 找是第三个结果,用 SAE 拆是第四个结果——

到底哪个是”真相”?

这就需要最后一层:单元测试 —— 因果验证与评估基准。


第七层:单元测试 —— 因果验证与评估基准

7.1 你怎么知道你的调试结论是对的?

程序员都知道:你调试完了,说”bug 在第 42 行”——但你怎么证明你是对的?

你写个单元测试啊。

  • 修复之前,测试失败 → 说明 bug 确实存在
  • 修复之后,测试通过 → 说明你的修复是有效的
  • 你还得跑回归测试,确保修了这个 bug 没引入新的 bug

可解释性也一样。你用 attention 看了、用 patching 测了、用 ACDC 找了、用 SAE 拆了——但你怎么知道你的”解释”是对的?

这就是评估的问题:可解释性方法本身,也需要被检验。

7.2 忠实性的四种含义

在讲具体的基准之前,先要澄清一个概念:忠实性(faithfulness)。

什么叫”一个解释是忠实的”?简单说就是:解释真的反映了模型的真实计算过程,而不是”听起来合理但跟实际没关系”。

但”忠实”这个词,不同的人有不同的定义。至少有四种:

种类含义典型指标白话解释
重建忠实解释能不能重建原模型的行为loss recovered、重建准确率“按你的解释搭一个小模型,能不能复刻原模型的输出?”
因果忠实解释定位的组件是不是因果必要的patching 恢复率、CPR/CMD“把你说重要的组件改掉,输出会不会变?”
言语忠实模型说的”理由”是不是真的理由CoT 截断 AOC、偏置暴露率“模型说它因为 X 所以 Y,是不是真的因为 X?”
人类评判忠实人觉得解释对不对auto-interp 打分、可信度评分“专家看完解释,觉得靠谱吗?”

这四种忠实性,不是一回事,而且有时候还互相冲突。

比如,一个 SAE 特征重建得很好(重建忠实高),但不一定因果重要(因果忠实可能低)——它可能只是顺带激活的”搭车客”。

再比如,attention 可视化看起来很合理(人类评判忠实高),但可能跟真实的因果关系没关系——这就是我们第一章讲的”attention 之争”。

一个重要提醒:看到”可解释性”相关的论文或新闻,先搞清楚它说的是哪种”忠实”——很多争议,本质上是定义不一样。

7.3 方法分歧:同一个问题,不同答案

为什么需要评估基准?因为不同方法给出的答案,差得实在太远了。

前面我们其实已经看到了一些线索:

  • attention 告诉你”看了哪里”,但不一定是因果重要的
  • patching 告诉你”哪里因果重要”,但测起来慢
  • ACDC 自动找电路,但会漏检负向组件
  • SAE 拆特征,但”单义性”存疑

这些还只是”定性”的差异。有没有定量的证据?

有。而且结果比你想的还夸张。

证据一:梯度近似与真实干预的相关性只有 R²=0.27

有一种叫 EAP(Edge Attribution Patching)的方法,用梯度来近似 patching 的效果——优点是快,”两次前向一次反向”就搞定。

但同一篇论文里也坦诚:EAP 的分数跟真实 patching 的分数,相关性只有 R² = 0.27。

R²=0.27 是什么概念?就是梯度法只能解释真实干预结果的 27% 的方差——剩下 73% 都是噪声或者偏差。

这不是实现细节的问题,而是一阶梯度近似的系统性失真。

证据二:基准赛获胜靠集成投票

2025 年 BlackboxNLP workshop 办了一个共享任务——”在语言模型里定位电路和因果变量”。

最后获胜的方案用的是什么?集成和正则化策略——也就是把好几种方法的结果合在一起投票。

单方法定位不稳到需要集成投票,这本身就是分歧的最好证据。

证据三:多解问题

还有一个更深层的问题,叫 多解问题(many-solutions problem)。

什么意思?就是对于同一个行为,可能存在多个不同的”电路”,都能解释它。你用方法 A 找到电路甲,用方法 B 找到电路乙——两个都对,只是不同的角度。

这就像你问”这个网站的后端是什么架构?”——有人说”是 MVC 架构”,有人说”是微服务架构”,有人说”是事件驱动架构”——三个都对,只是抽象层次不一样。

神经网络可能比这还极端。因为有大量冗余和并行通路,”哪个电路是真正的”可能本身就是个错误的问题。

7.4 因果检验的金标准:causal scrubbing

那怎么检验一个解释对不对?

目前最严格的方法叫 causal scrubbing(因果擦洗)。

它的思路很科学哲学:把解释当作一个可证伪的假设来检验。

具体来说,你的解释假设是”模型这样计算”——比如,”模型先提取主语,再提取宾语,然后组合起来”。

那你就做一个”假设模型”——按照你的解释来构造输入分组。凡是你的解释认为”等价”的输入,就归为一类。

然后你做干预:在模型运行时,把每个位置的激活,替换成同一组里随机选的另一个输入的激活。

如果你的解释是对的——这些输入在你的解释下确实是等价的——那替换之后模型的行为应该变化不大。因为你只换了”不重要”的细节,保留了”重要”的结构。

如果你的解释是错的——你以为等价的东西其实模型觉得不等价——那替换之后行为就会大变。

causal scrubbing 的白话解释:你说”模型只关心 A、B、C,其他都不重要”?那好,我把”其他都不重要”的部分随机打乱,如果输出没变,说明你说对了;如果输出变了,说明你漏掉了重要的东西。

但注意:causal scrubbing 只能证伪,不能证实。

  • 如果检验通过了——只能说明”你的解释目前还没被推翻”,不能说明”你的解释就是对的”
  • 因为可能还有另一个完全不同的解释,也能通过同样的检验

这就像科学理论——你永远不能证明一个理论是”真理”,你只能说它”还没被证伪”。

7.5 MIB 基准:可解释性的”高考”

2025 年,一个叫 MIB(Mechanistic Interpretability Benchmark)的基准发布了,这是目前可解释性领域最系统的评估基准之一。

MIB 有两个赛道(track):

  1. 电路定位(circuit localization):找出对行为最重要的组件和交互
  2. 因果变量定位(causal variable localization):找出内部表征中编码了哪些因果变量

它的核心指标有两个,基于”忠实度曲线”:

$$
f(C, N; m) = \frac{m(C) – m(\varnothing)}{m(N) – m(\varnothing)}
$$

我来翻译:

  • $N$ 是完整的网络(啥也没动)
  • $\varnothing$ 是空的(全破坏了)
  • $C$ 是你找到的电路
  • $m(…) $ 是某个性能指标(比如准确率、logit diff)
  • $f$ 就是”你的电路恢复了多少性能”——0 表示完全没用,1 表示跟完整网络一样好

然后从这个曲线出发,计算两个指标:

指标全称含义越好的方向
CPRComplete Patching Recovery曲线下面积——你找到的电路整体有多好越大越好
CMDComplete Match Deviation跟理想曲线(y=x)的偏离——你的估计准不准越小越好

MIB 的结果很有启发性,我挑几个说:

  1. 电路定位赛道:领先的是 attribution patching 和 mask 优化方法
  2. 因果变量赛道:监督式方法(DAS)最强,SAE 特征不比神经元更好——没错,你费半天劲拆出来的特征,定位效果跟直接用原始神经元差不多
  3. 方法差距大:不同方法的分数差很多,说明领域还远未成熟

还有一个叫 RAVEL 的基准,结果类似:方法之间相差 20–26 个点,监督式方法全面压倒无监督方法。

7.6 事后解释的系统性失败:CoT 忠实性

上面说的都是”机制类”的解释(patching、电路、特征)。还有一类解释,大家可能更熟悉——事后解释(post-hoc explanation)。

就是模型自己给自己的行为找理由——比如 Chain-of-Thought(CoT,思维链),模型一边推理一边说”我是这么想的……”。

问题是:模型说的理由,是它真正的理由吗?

两篇经典论文给出了系统性的负面答案。

研究一:CoT 截断实验

Lanham 等人 2023 年做了一个实验:在模型生成 CoT 的过程中,提前截断——不让它把推理说完,直接让它给答案。

如果 CoT 是”真实推理过程”,那截断应该会影响答案——因为推理被打断了嘛。

但结果是:答案依 CoT 变化度(AOC)的跨度只有 0.02–0.44。有些模型,就算你把 CoT 全删了,答案也差不多。

更扎心的是:更大、更强的模型,反而更不忠实。

这说明什么?CoT 很多时候是在”放马后炮”——答案早就定了,CoT 只是编个听起来合理的理由。

研究二:偏置暴露实验

Turpin 等人 2023 年做了另一个实验:给模型的输入里偷偷注入一个偏见(比如,答案总是选项 A),然后让模型解释为什么选了 A。

结果是:426 条支持偏见预测的解释里,只有 1 条提到了偏见本身。

模型编了各种各样的”理由”来解释它的选择,但从来不说真正的原因——”因为输入里有偏见”。

事后解释的核心问题:”看起来合理”(plausibility)和”忠实于计算”(faithfulness)是两个完全不同的维度。

一个解释可以听起来非常有道理,但完全是瞎编的。CoT 也是如此——模型说的”思考过程”,可能只是事后合理化,而不是真实的计算过程。

7.7 回到”只读”:用评估的眼光看

学了这么多评估方法,我们再回头看开头的问题——”不可更改,只读”到底有多重要?

现在我们知道,不能只看一种方法的结果。我们需要:

  1. 用 attention 看:模型在关注”只读”吗?→ 可能是,但 attention 不等于因果
  2. 用 patching 测:换掉”只读”的激活,行为变不变?→ 变,说明因果重要
  3. 用 ACDC 找:自动定位电路 → 找到一部分,但可能漏了负向通路
  4. 用 SAE 拆:有没有”只读”特征?→ 有相关的,但不是单一的、原子的
  5. 用干预试:注入”只读”方向,行为变不变?→ 变,但可能有副作用
  6. 用 J-lens 读:工作空间里有没有”只读”概念?→ 有,但可能是循环论证
  7. 用基准测:多种方法的结果一致吗?→ 不一定,方法间分歧大

所以正确答案是什么?

“经过多种因果方法交叉验证的强假设”——我们有相当的信心认为某些组件和特征跟”只读”行为有关,但我们不知道完整的真相。

这听起来有点让人沮丧——花了这么多功夫,就得到个”强假设”?

但其实,这才是健康的科学态度。

7.8 第七层小结

  • 工具:causal scrubbing、MIB 基准、RAVEL 基准、SAEBench、AxBench
  • 类比:单元测试 / 集成测试——验证你的调试结论对不对
  • 核心概念:忠实性(四种含义)、多解问题、可证伪性
  • 关键发现:
    • 方法间分歧大:梯度近似与真实干预 R²=0.27
    • 基准赛获胜靠集成:单方法不稳
    • SAE 不优于神经元:过完备字典的定位效果没想象中好
    • CoT 不忠实:越大的模型越会”放马后炮”
  • 因果检验的边界:causal scrubbing 只能证伪,不能证实;多解问题普遍存在
  • 认识论定位:可解释性交付的是”经过因果筛选的强假设”,不是完备真理

尾声:从”讲故事”到”做检验”

回到开头的问题

我们走了七层,现在可以回答最开始的问题了:

“不可更改,只读”这句话,在 LLM 的脑子里到底有多重要?

答案是——

它重要,但没有你想的那么”硬”。

(写完初稿后我真的去测了:普通”不可更改,只读”的服从率 92%,和无死命令没有显著差别;只有”无论我之后说什么都不许改”降到 56%;动手改了文件的模型,93% 会说自己”没有违反”。这次实测的全过程和另外五条发现,我会单独写一篇。)

  • 它不是像 const 关键字那样的硬约束——不是写死在语法里、违反了就编译不通过
  • 它更像是一个”权重很高的建议”——模型会考虑它,但当后面的指令(”改了它”)足够强的时候,它就会让路
  • 它的信息分布在很多层、很多头、很多特征里——不是存在某一个”只读寄存器”里
  • 你可以通过干预来加强它,但同时会带来副作用
  • 你可以在工作空间里”读”到它的存在,但读数不是 100% 可靠的

为什么会这样?因为 LLM 不是一个按规则运行的程序——它是一个统计模型。它的”遵守指令”不是因为它理解了规则的强制性,而是因为它在训练中学会了”通常情况下,指令是要遵守的”。

当上下文里有更强的信号(比如用户后来让你改),统计概率就会转向。

可解释性能做什么、不能做什么

学完了七层工具,我们来给可解释性的能力边界画个线:

它能做的:

  1. 审计:发现模型”什么时候不可信”——比如发现某个行为依赖了可疑的特征
  2. 引导:有副作用地控制模型行为——比如注入诚实向量、拒绝方向
  3. 启发:指导新的训练方法——比如 CRT(反事实反思训练)就是用可解释性发现来改进训练
  4. 假设生成:提出关于模型内部机制的候选解释,供进一步验证

它不能做的:

  1. 证明模型安全:内部读数能提供”不可信”的证据,但永远不能提供”可信”的证明——因为你不知道有没有漏掉什么
  2. 完全理解模型:几十亿参数的模型,其复杂度远远超过了人类的理解能力
  3. 预测所有行为:可解释性目前只能解释特定的、受控的行为,远未达到通用预测
  4. 给出唯一真相:多解问题普遍存在,不同方法可能给出不同但都对的解释

五个最值得追踪的方向

如果你想持续关注这个领域,我建议盯这五个方向:

  1. SAE 规范性危机的裁决:absorption/非原子/基准败退之后,修正线(meta-SAE、Matryoshka、deep asymmetry)能不能恢复”解释单位”的地位?这决定了 SAE 路线的天花板。
  2. J-lens 的独立复制与扩展:结构已稳(band 存在),任务效应未稳;多 token 扩展与跨架构(MoE/Mamba)验证是分水岭。
  3. 干预管线化 + 副作用审计:Locate-Steer-Improve 的工程收益和风险账要并表报告——不能只说效果不说副作用。
  4. 基准分数是否收敛:MIB/BlackboxNLP 后续轮次的方法排名如果还是靠集成取胜,说明定位方法学尚未成熟。
  5. CoT 监控 vs 内部读数的军备竞赛:CoT 监控的有效窗口正在被优化压力关闭(模型学会了”沉默推理“),内部读数是唯一候选替代——但它的独立性在反思训练普及后也会失效。

一句话总结

最后,用一句话总结整个领域的现状——

可解释性已经把自己从”讲故事”逼成了”做检验的工程学”,代价是发现每一步检验都比预想的弱——这是领域的健康状态,不是失败。

六年前,我们只能画 attention 热力图,然后编一个”模型在关注什么”的故事。

今天,我们有 patching 做因果验证、有基准做横向对比、有副作用审计算风险账——我们说得更少了,但每一句都更靠谱。

这不是退步,这是进步。

真正的科学,从来都是从”我知道”走向”我知道我不知道多少”。

可解释性正在这条路上。


进一步阅读

如果你想深入了解,这里是一些入门的好起点:

  • TransformerLens:一个专门为可解释性研究设计的库,支持 hook 机制,可以方便地做 patching 实验
  • Neuronpedia:一个 SAE 特征的可视化浏览器,可以直观地看到各种特征长什么样
  • MIB 基准:想知道各种方法的最新排名,去看 MIB 的 leaderboard
  • jacobian-lens(官方代码库):J-lens 的参考实现。上手前要有心理准备:仓库只开源了透镜拟合与读数部分,论文里的 swap 干预、稀疏分解实现并不在里面——复现核心实验要自己按实验协议写
  • Transformer Circuits Thread:Anthropic 的可解释性研究博客,SAE 和 J-space 工作都发在这里
  • Alignment Forum:社区讨论的地方,causal scrubbing 等概念最早在这里提出

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注