符号主义、贝叶斯网络、深度学习:三种 AI 范式的对比学习
符号主义、贝叶斯网络、深度学习:三种 AI 范式的对比学习
一个非常自然的直觉是这样的:"GPT 不就是把一堆自然语言数据当成可执行的符号代码,然后在这些海量规则下做回答吗?"
这个类比有 70% 是对的,30% 错得很关键。要把这 30% 讲清楚,需要把符号主义 AI、贝叶斯网络、深度学习放在同一张桌子上对照——它们三者都在解同一个问题 $P(y \mid x)$,只是参数化方式根本不同。本文从这个共同问题出发,把三种范式的相同点、差异、各自擅长的边界,一条条钉到
model.py/tokenizer.py的具体行号上。读完这篇,你会知道为什么"训练数据 = 可执行符号代码"是一个有用的近似,但不能当结论——以及为什么贝叶斯网络是介于两者之间的"半符号半概率"中间态。
目录
- 三个范式的一句话总结
- 都在解同一个问题:$P(y \mid x)$
- 符号主义 AI:人写规则,机器搜索
- 贝叶斯网络:图是符号的,参数是概率的
- 深度学习大模型:人写架构,梯度下降写参数
- 可解释性:深度学习最大的软肋,以及它现在进展到哪一步
- "训练数据 = 一堆可执行的符号代码"——这个类比对在哪、错在哪
- 三种范式的对照表
- 在 CodeGPT 里看见三个范式的影子
- 神经-符号混合:现代系统都不是纯种
- 给用户原问题的最终回答
1. 三个范式的一句话总结
| 范式 | 知识形式 | 谁写 | 谁执行 | 代表系统 |
|---|---|---|---|---|
| 符号主义 | 离散规则 (if A then B) |
人 | 推理引擎搜索 | Lisp、Prolog、专家系统、CYC |
| 贝叶斯网络 | DAG + 条件概率表 | 人画图 + 数据估参数 | 概率推断 (变量消去 / MCMC) | 医疗诊断、垃圾邮件 (Naive Bayes)、HMM |
| 深度学习 | 连续权重矩阵 $W$ | 梯度下降写 | 前向传播 | GPT、Transformer、CodeGPT |
注意"谁写"这一列的演变:人写得越来越少,数据写得越来越多。这是从 1956 Dartmouth 会议到 2026 的一条主线。
2. 都在解同一个问题:$P(y \mid x)$
不管哪个范式,AI 系统本质都在做条件概率:给定输入 $x$,预测输出 $y$。
- 在符号系统里,$P(y \mid x) \in {0, 1}$——要么 $x \Rightarrow y$ 是规则的逻辑蕴含,要么不是。
- 在贝叶斯网络里,$P(y \mid x)$ 是图上一系列条件概率表 (CPT) 的乘积。
- 在深度学习里,$P(y \mid x)$ 是一段可微分程序的输出,比如:
# model.py:301
probs = F.softmax(logits, dim=-1) # P(next_token | context)
差别只在于这个分布是怎么参数化、怎么写入系统的。讲清楚这一点,三种范式的关系立刻变得简单:它们是同一个数学问题的三种工程实现。
3. 符号主义 AI:人写规则,机器搜索
3.1 它长什么样
最经典的形式是 Prolog:
parent(tom, bob).
parent(bob, ann).
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
加上一个推理引擎(unification + 深度优先搜索 + 回溯),系统就能回答 ?- grandparent(tom, ann). → true。
它的等价 Python 描述:
facts = {("parent", "tom", "bob"), ("parent", "bob", "ann")}
def grandparent(x, z):
for y in all_entities:
if ("parent", x, y) in facts and ("parent", y, z) in facts:
return True
return False
特征:
- 知识是离散的、可枚举的、可读的——你能逐条审计每一条规则。
- 推理是确定性的——同样的输入永远得到同样的输出,且可证明(每一步都对应一个推理规则)。
- 没有"训练" 这一步,知识是人直接写进去的。
3.2 它的死穴:知识获取瓶颈
写 100 条规则容易,写 100 万条规则比这难 10 万倍——因为规则之间会冲突、嵌套、上下文敏感。1980 年代的专家系统(MYCIN、CYC)就是死在这里:
- 自然语言里"苹果"是水果还是公司?需要规则。
- "我打开冰箱"——"打开"对冰箱、对文件、对人,三种语义。需要规则。
- 代码里
x = []后面的x类型是什么?需要规则 + 类型推断 + 上下文……
写规则的人在某一刻会发现:"规则的规则"是无穷无尽的。这就是 Hubert Dreyfus 1972 年 What Computers Can't Do 里的核心论证,也是 1980s "AI 寒冬" 的直接原因。
3.3 但它没死
形式化推理、定理证明、SQL 优化器、编译器、AST 重写、合规规则引擎——这些强约束、低歧义、可枚举的领域,符号 AI 至今无可替代。Lean、Coq、Z3 都是符号系统的最新代表。
4. 贝叶斯网络:图是符号的,参数是概率的
4.1 它长什么样
经典的 "Sprinkler / Rain / WetGrass" 图:
Rain ──┐
├──→ WetGrass
Sprinkler ┘
P(Rain) = 0.2
P(Sprinkler|Rain=T) = 0.01
P(Sprinkler|Rain=F) = 0.4
P(WetGrass | Rain, Sprinkler) = ... # 4 项的 CPT
联合分布由图结构因式分解:
P(R, S, W) = P(R) · P(S | R) · P(W | R, S)
这个因式分解就是贝叶斯网络的核心——它不是从原始 $2^n$ 大小的联合分布里硬学,而是用图结构(条件独立性假设)把它压缩到几个小的 CPT。
4.2 它处于符号和神经的中间
| 组件 | 谁定 | 性质 |
|---|---|---|
| 节点 (变量) | 人定 | 符号 |
| 有向边 (依赖结构) | 人画 / 结构学习 | 符号 |
| CPT (条件概率) | 数据估计 | 概率 |
| 推理 | 算法 (变量消去 / MCMC) | 数值 |
这是它比符号 AI 强的地方:CPT 可以从数据学,不用人手填。
也是它比深度学习弱的地方:图结构必须人画。10 个变量你能画,10 万个 token、12 层、768 维,没人能画出图。
4.3 在代码里看一眼
# 一个最小贝叶斯网络的 PyTorch 实现 (示意)
import torch
# CPT 是一个查找表 —— 这就是为什么它是 "半符号"
P_R = torch.tensor([0.8, 0.2]) # P(R=F), P(R=T)
P_S_R = torch.tensor([[0.6, 0.4], # P(S | R=F)
[0.99, 0.01]]) # P(S | R=T)
# 推断 P(R=T | W=T): 枚举 + 归一化
def infer(R, S, W, evidence):
... # 变量消去 / 精确推断
关键:CPT 是离散的、可解释的查找表——和神经网络里 $W \in \mathbb{R}^{768 \times 768}$ 的稠密矩阵完全不同。
4.4 它和深度学习的连接点
- Naive Bayes 是最简单的贝叶斯网络(所有特征条件独立给定类别),等价于一个单层 + softmax 的判别模型。
- HMM(隐马尔可夫模型)在语音识别上统治了 30 年,本质是一条链状的贝叶斯网络。
- 变分自编码器 (VAE)、扩散模型 都是把贝叶斯推断和深度学习"焊"在一起——前者用神经网络近似 $q(z \mid x)$,后者用神经网络近似每一步去噪的条件分布。
- 深度学习的 cross-entropy loss 本身就是 MLE 估计——贝叶斯派给个先验就成 MAP,再边缘化就成完整贝叶斯。
所以贝叶斯没有死,它变成了深度学习的损失函数和正则化项。
5. 深度学习大模型:人写架构,梯度下降写参数
5.1 关键的视角转换
CodeGPT 的 forward 实际上是一段普通 Python:
# model.py:177-198
def forward(self, idx, targets=None):
pos = torch.arange(0, t, dtype=torch.long, device=device)
tok_emb = self.transformer.wte(idx)
pos_emb = self.transformer.wpe(pos)
x = self.transformer.drop(tok_emb + pos_emb)
for block in self.transformer.h:
x = block(x)
x = self.transformer.ln_f(x)
if targets is not None:
logits = self.lm_head(x)
loss = F.cross_entropy(logits.view(-1, logits.size(-1)),
targets.view(-1), ignore_index=-1)
...
这段代码就是一段"程序"——但里面所有矩阵 (wte.weight, wpe.weight, 每个 Block 里的 Q/K/V/MLP/LayerNorm 权重) 都是待填的空格,由 loss.backward() 配 AdamW 一格一格填出来。
5.2 知识在哪里
知识压在权重里。 不是 100 万条 if-else,而是 ~$1.2 \times 10^8$ 个浮点数(CodeGPT-base 124M 参数)。每个浮点数都不是一条单独的规则,而是许多规则的微小贡献叠加。
这种压缩方式有三个革命性后果:
- 泛化——训练时没见过的输入也能合理回答,因为权重学到的是模式的统计结构,而非样本的查找表。
- 不可解释——你不能指着某个权重说"这是关于 Python 缩进的规则",它弥散在整个矩阵里。这是深度学习最被诟病的一点,值得单独一节,见 §6。
- 不可枚举——你不能审计每条规则,因为规则数量是连续的、无穷的。
详细推导见 docs/COMPRESSION_IS_INTELLIGENCE.md 和 docs/DIFFERENTIABLE_PROGRAMMING.md。
6. 可解释性:深度学习最大的软肋,以及它现在进展到哪一步
"大模型是黑盒、不可解释" 是深度学习被诟病最多的一句话,从 Gary Marcus 到 Yann LeCun 早期言论、到 Bender 的 "stochastic parrots"、到欧盟 AI Act 把高风险场景的可解释性写进法规——这是一个技术问题、监管问题、信任问题三位一体的批评。
但这句话本身需要拆开看。"不可解释" 包含三个完全不同层次的诉求,深度学习在三个层次上的现状差别极大;而过去三年(2022-2025)机制可解释性 (mechanistic interpretability) 这个新方向的进展,已经把"完全黑盒"的判决推翻了一大半。这一节把现状钉到具体的工具和论文上。
6.1 "不可解释" 具体指什么——三个层次
| 层次 | 问的是什么 | 深度学习现状 |
|---|---|---|
| 行为层 (functional) | 给定输入,能不能预测/审计输出? | 中等。可 benchmark、可写测试,但长尾分布无法穷举 |
| 机制层 (mechanistic) | 模型内部是怎么算出这个输出的? | 弱→改善中。SAE、circuits 已能局部还原 |
| 概念层 (semantic) | 模型"懂"了什么概念? | 弱→改善中。SAE 找到了百万级单义特征 |
这三层在符号 AI 里都是默认完整的(每一步都对应一条规则);在深度学习里都需要额外工具来逆向工程。这不是因为深度学习"原理不清楚"——forward 的每一行 PyTorch 都摆在你面前——而是因为权重里压了什么概念这件事,没法从 model.py 的代码读出来。
6.2 为什么神经网络天生难解释——四个根源
根源 ①:分布式表征 (Distributed representation)
一个概念不对应一个神经元,而是对应一个方向 / 一个子空间。
# h: torch.Tensor of shape (768,) —— 某层的 hidden state
# "这段是 Python 函数定义" 这个概念
# ≈ h 在某个方向 d_func ∈ R^768 上的投影:
# concept_score = h @ d_func
#
# 这个 d_func 不是任何一个 weight,是 W 的列向量的某种线性组合
你拿放大镜看 wte.weight[100] 这一个浮点数,它什么都不"代表"——它是 50304×768 矩阵里的一格,只在和其他 76799 格协同的时候才有意义。
根源 ②:多义性 (Polysemanticity)
同一个神经元在不同输入下响应完全不相关的概念——可能既响应 "Python 缩进" 又响应 "JavaScript 大括号" 又响应 "第三人称代词"。这不是 bug,是 SGD 找到的最优解:用 768 维空间装下远超 768 个特征。
根源 ③:叠加 (Superposition)
Anthropic 2022 Toy Models of Superposition 论文是关键:模型在 $d$ 维空间里编码了远超 $d$ 个特征,用近似正交(而非严格正交)的方向。这就是为什么单看一个神经元/单个权重看不出意义——意义被刻意打散了。
理想 (one-hot) 现实 (superposition)
n features in n dims n features in d<<n dims
单义,可读 多义,需要 SAE 解码
根源 ④:12 层非线性组合
# model.py:103-104 —— 残差 + 非线性
x = x + self.attn(self.ln_1(x))
x = x + self.mlp(self.ln_2(x))
每个 Block 都把信号加进残差流(residual stream),早期层的信息一路 "广播" 到末端。要追溯 "答案 X 是因为第 3 层第 5 个 head 在 token Y 上做了什么" ——这是一条跨 12 层的因果链,而中间每层都有 12 个 head 同时在写。组合爆炸是机制层不可解释的直接来源。
6.3 我们目前到底能解释什么——五条具体进展
机制可解释性不是一个抽象口号,它在过去三年有具体可复现的成果。从弱到强:
进展 ①:注意力可视化 (Attention visualization)
最早、最简单。把 model.py:68 的 att = F.softmax(att, dim=-1) 这个权重矩阵 hook 出来画热图,能看到代码块边界、变量引用、括号匹配等模式。
陷阱:Bibal et al. 2022 Is Attention Explanation? 证明 attention weights 不等于 "解释"——在很多任务上你能找到完全不同的 attention 分布给出同样的预测。所以 attention map 可看,但单独不可信。
进展 ②:线性探测 (Probing)
在某层的 hidden state 上训一个轻量线性分类器,看它能不能预测某个概念。
# 思路 (CodeGPT 上可立刻做):
# 1. 跑一段验证集,在第 N 层 hook 出 hidden states H ∈ R^{N_tokens × 768}
# 2. 给每个 token 标 "在 docstring 内 / 函数体内 / 注释内"
# 3. 训 logistic regression: f(h) → label
# 4. 准确率 90%+ 说明这一层"知道"这个概念
Hewitt & Manning 2019 用这套方法证明 BERT 中层学到了句法树。局限:这是相关性不是机制——分类器读得出,不代表模型内部用得上。
进展 ③:Logit lens / Tuned lens
把每一层的 hidden state 直接乘 lm_head 看 next-token 预测。
# CodeGPT 上,基于 model.py:177-198 的 forward,加几行就能跑:
preds_per_layer = []
for block in self.transformer.h:
x = block(x)
# 用最终的 ln_f + lm_head 直接 "翻译" 这一层
logits_here = self.lm_head(self.transformer.ln_f(x))
preds_per_layer.append(logits_here.argmax(-1))
# 看预测是从哪一层稳定下来的
经验上,事实回忆通常在中后层定型,语法/格式在早层定型。这给了模型内部计算流程一个粗粒度的"沙漏图"。
进展 ④:Circuit 分析 (Anthropic / Olah 流派)
不再问"这层学了什么",而是问 "完成任务 T 用到了哪些 head 的协作?"——直接画出电路图。已找到的具体电路:
- Induction heads (Olsson et al. 2022):两个 head 协同实现 "看到
[A][B] ... [A]就预测[B]" 的模式补全。这是 in-context learning 的最小机械原型——现在大家相信 GPT 的 ICL 能力,从这个 head 开始 - IOI circuit (Wang et al. 2022):GPT-2 small 里负责 "Mary and John went to the store, John gave a drink to ___" 这类间接宾语任务的 26 个 head 的精确协作图
- ROME / MEMIT (Meng et al. 2022/2023):证明 "巴黎是法国首都" 这个事实储存在某个具体 MLP 层的某几行权重里,可以单独编辑——把 "巴黎" 改成 "罗马",模型就开始坚信法国首都是罗马
这把"知识在权重里"从模糊比喻变成了可定位、可编辑的工程操作。
进展 ⑤:稀疏自编码器 (SAE) —— 2023 年突破
最近三年最大的进展。思路:把多义神经元解耦成单义特征。
# 在某层 hidden state h ∈ R^{768} 上训一个 SAE:
# encoder: h -> features ∈ R^{65536} (大词典,但稀疏)
# decoder: features -> h_hat
# loss = ||h - h_hat||^2 + λ * ||features||_1 # L1 强制稀疏
# 训完后,每个 feature 几乎单义化:
# feature[42] 只在 "Python 装饰器" 上激活
# feature[1337] 只在 "金门大桥" 上激活
# feature[8888] 只在 "周二" 上激活
Anthropic 2023 Towards Monosemanticity 在小模型上跑通,2024 Scaling Monosemanticity 推到 Claude 3 Sonnet,找到约 3400 万个单义特征,并演示了通过把某个 feature 的激活值人为放大/抑制来直接操控行为(著名的 "金门大桥 Claude" ——把 Golden Gate Bridge feature 锁住,模型在任何对话里都自我认同为金门大桥)。
这是从 "我们看不懂权重" 到 "我们可以扫出百万级别可读的概念清单" 的根本性突破。
6.4 一张精确的可解释性对照表
| 维度 | 符号 AI | 贝叶斯网络 | 深度学习 (2026) |
|---|---|---|---|
| 行为层可解释 | ✅ 完全 | ✅ 完全 | 🟡 中(可 benchmark) |
| 机制层可解释 | ✅ 每条规则可读 | ✅ D-separation + 变量消去步骤 | 🟡 SAE / circuits 部分还原 |
| 概念层可解释 | ✅ 符号即概念 | ✅ 节点即变量 | 🟡 SAE 已找到百万级单义 feature |
| 反事实推理 | 🟡 改规则即反事实 | ✅ 强 (do-calculus) | 🟡 activation patching 局部能做 |
| 因果归因 | ✅ 推理链是因果链 | ✅ Pearl 因果阶梯三层全覆盖 | 🟡 ROME 证明可定位+编辑 |
| 法律可审计性 | ✅ 强 | ✅ 强 | ❌→🟡 (合规性正在快速改善) |
| 用户层解释 | ✅ 规则即解释 | 🟡 概率链需要训练才看得懂 | 🟡 chain-of-thought (但可能不忠实) |
| 解释成本 | 几乎零 | 中(图大了就难) | 高(需要 SAE 训练 + 分析工具) |
注意两件事:
- 贝叶斯网络在因果反事实上比符号还强——Pearl 的 do-calculus 是贝叶斯派给可解释 AI 的最大贡献。如果你的需求是 "改了 X 会怎样",贝叶斯网络至今领先
- 深度学习这一列在 2022 年还几乎全是 ❌,现在大半已经变成 🟡。这条改善曲线还在快速往下走
6.5 在 CodeGPT 上能做什么——五个立刻能上手的实战
虽然这个 repo 没集成 SAE,但已有架构上今天就能跑这五件事:
| # | 工具 | 在哪挂钩 | 能看到什么 |
|---|---|---|---|
| 1 | 注意力可视化 | model.py:66-68 的非 flash 路径,把 att hook 出来 |
缩进对齐、变量引用、括号配对 |
| 2 | Logit lens | model.py:177-198 的 for block in ... 循环里每层接一个 lm_head(ln_f(x)) |
预测从哪一层稳定下来 |
| 3 | 线性探测 | 取 hidden state,训 LR 分类器 | "在 docstring 内"、"嵌套深度"、"是否在字符串内" 等可读概念 |
| 4 | Head ablation | 在 Block.attn 里把某个 head 的输出置零,看 val loss 变化 |
哪些 head 对代码补全任务关键 |
| 5 | ROME 风格编辑 | lm_head.weight 是 tied 的 wte.weight(model.py:158-159),定位到某 token embedding 直接改 |
观察生成漂移,证明知识在哪 |
这些都不是研究前沿,是 2026 年任何团队都能上手 的入门项目——也是 "可解释性正在工程化" 的直接体现。
6.6 哲学层面——"不可解释" 这个标签被夸大了多少
三个反问把这个批评放回正确尺度:
反问 ①:人类自己可解释吗?
你能解释你刚才为什么用 "诟病" 而不是 "批评" 吗?为什么这一段话先讲反问 ① 再讲反问 ②?神经科学到现在还没真正搞清楚一个具体想法是怎么在大脑里形成的。我们对 "人是可解释的" 的信念,主要靠事后合理化 (post-hoc rationalization)——这和 LLM 的 chain-of-thought 在性质上几乎一样。CoT 甚至可能不忠实 (Turpin et al. 2023):模型给出的理由可能不是它实际计算的路径。人类的 CoT 同样不忠实,这一点心理学研究了几十年(Nisbett & Wilson 1977 经典论文)。
反问 ②:"可解释" 是二值还是连续?
没有任何系统是 100% 可解释的(连 Linux 内核都没有人完整懂——它有 3000 万行代码,十几个子系统的交互边界没人能全握在脑子里)。也没有任何系统是 100% 不可解释的——CodeGPT 的 forward 每一行 PyTorch 都印在屏幕上。差别是程度,不是二值。
反问 ③:解释给谁看?
| 受众 | 想要的解释 |
|---|---|
| 监管机构 | 决策依据、可审计、可申诉 |
| 模型开发者 | 哪个 head/feature 在什么时候激活 |
| 终端用户 | 自然语言为什么这样回答 |
| 安全研究员 | 越狱路径、对抗样本来源 |
SAE 的 feature 给开发者看是金矿,给用户看就是天书。"可解释性" 不是一个统一目标,是四个不同问题。
6.7 一句话总结
可解释性不是深度学习的死罪,而是它当前最值得投入的研究方向之一。 符号 AI 的 "完全可解释" 是因为它表达力有限(规则就那么多);深度学习的 "难解释" 是因为它表达力近乎无限(连续函数空间稠密)——两者其实是同一枚硬币的两面。
把符号 AI 的可解释性当 baseline 去要求深度学习,是用一个范式的标准评判另一个范式。更合理的姿势是:用符号/贝叶斯的工具去逆向工程深度网络 ——这正是 SAE / circuits / ROME / probing 在做的事——以"神经-符号混合解释" 把深度学习从黑盒往灰盒推。
这条曲线已经走了三年,远未到尽头。
7. "训练数据 = 一堆可执行的符号代码"——这个类比对在哪、错在哪
现在回到你的原问题。让我们逐条拆。
6.1 对的部分(70%)
类比的核心直觉是正确的:训练数据确实定义了系统的行为,正如代码定义了程序的行为。
- 改训练数据 → 改模型行为,等价于"改代码 → 改程序行为"。
- LLM 的 in-context learning 让人觉得它在"执行"prompt 里的指令——这确实有几分像把 prompt 当代码。
- "Compression is intelligence" 的视角下,权重 $W$ 是训练数据的有损压缩——你也可以反向理解为"训练数据 = 解压后展开的所有规则"。
6.2 错的部分(30%,但很关键)
错位 ①:硬规则 vs 软统计
符号代码:
if x > 0:
return "positive"
——只要 x > 0,100% 返回 "positive"。
训练数据隐含的"规则":
# 这其实是 P(token | context) 的一行样本
context: "def fibonacci(n):\n "
next_token: "if" # 出现在训练集 60% 的时间
next_token: "return" # 25%
next_token: "n =" # 5%
...
模型不是从这些样本里抽取出确定性的 if-then 规则,而是插值出一个连续的概率分布。这就是为什么同样的 prompt 每次生成不一样——这在符号系统里是不可能的。
错位 ②:执行什么
| 符号系统执行 | LLM 执行 | |
|---|---|---|
| 输入 | 用户写的代码 | 用户的 prompt |
| 执行什么 | 用户写的代码 | 从数据中统计提取的隐式分布 |
| 谁写规则 | 用户 | 梯度下降 (用户只写架构) |
这是关键:符号系统执行的是"用户的意图";LLM 执行的是"训练集的平均意图"。这就是为什么 LLM 会幻觉、会偏向训练数据的偏见、会拒绝训练时学过的"敏感"内容——它执行的根本不是你的 prompt,是它对"在这种 prompt 下,训练分布会怎么响应"的估计。
错位 ③:可枚举 vs 不可枚举
100 万条 Prolog 规则你理论上能逐条读完。124M 个浮点数你不能逐个理解——它们之间存在大量的非线性叠加。你无法把权重"反编译"成一组 if-else(这个研究方向叫机制可解释性 / mechanistic interpretability,目前能解释的只是个别 head 的功能,远未做到整体反编译)。
错位 ④:训练数据本身不是规则集
训练数据是例子,不是规则。规则在哪里?规则是梯度下降从例子里"归纳"出来的,存在权重里。这是从亚里士多德到 Hume 都在讨论的"归纳问题"——例子和规则不是同一种东西。
6.3 一个更精确的类比
如果一定要用编程类比,更准确的版本是:
训练数据是规约 (specification),权重是编译产物 (compiled binary),前向传播是执行。SGD 就是编译器。
这就和 docs/DIFFERENTIABLE_PROGRAMMING.md 里 LeCun 的"可微分编程"视角接上了:训练 = 编译,推理 = 执行。
但即使这个类比也有局限:传统编译器是确定性的,同样的源码编译出同样的二进制;SGD 是随机的,不同的初始化、不同的 batch 顺序会编译出不同的权重——但所有这些权重在训练分布上的行为大致等价。这是符号编程里没有的现象。
7. 三种范式的对照表
| 维度 | 符号主义 AI | 贝叶斯网络 | 深度学习大模型 |
|---|---|---|---|
| 知识载体 | 离散规则 / 事实 | DAG + CPT | 连续权重矩阵 |
| 知识来源 | 人手写 | 人画图 + 数据估参数 | 数据 (+ 人定架构) |
| 推理形式 | 符号搜索 / 归结 | 概率推断 | 矩阵乘法 + 非线性 |
| 可解释性 | 强 (每步可追溯) | 中 (节点+CPT 可读) | 弱 (权重弥散) |
| 数据效率 | 0 例样本即可 (但需大量人工) | 中等 | 极差 (需海量数据) |
| 泛化能力 | 弱 (规则边界硬) | 中 (受图结构约束) | 强 (连续插值) |
| 计算复杂度 | 推理可能 NP-hard | 精确推断 NP-hard | 推理 $O(n)$ 一次前向 |
| 不确定性 | 没有 (二值) | 一等公民 | 隐式 (在 logits 分布里) |
| 可组合性 | 强 (规则即模块) | 中 (子图可拼接) | 弱 (权重不可拆) |
| 知识更新 | 编辑规则即可 | 重新估 CPT | 重新训练或 fine-tune |
| 典型失败模式 | 知识获取瓶颈 | 图结构错 → 全错 | 幻觉 / 训练分布偏移 |
| 形式保证 | 可证明正确 | 概率边界 | 几乎没有 |
| CodeGPT 例子 | <|fim_prefix|> 等特殊 token 的硬模板 |
(无显式贝叶斯网络) | forward 里所有 nn.Linear |
注意一件事:没有任何一行说"X 是赢家"。三个范式各自在自己擅长的边界内是无可替代的。
8. 在 CodeGPT 里看见三个范式的影子
虽然 CodeGPT 是一个纯神经模型,但它的代码里仍然能找到三种范式的痕迹:
8.1 符号成分
tokenizer.py 里硬编码的特殊 token——这是纯符号:
# tokenizer.py:148-198 的 apply_fim_transform
prefix_id = SPECIAL_TOKENS["<|fim_prefix|>"] # 50257
middle_id = SPECIAL_TOKENS["<|fim_middle|>"] # 50258
suffix_id = SPECIAL_TOKENS["<|fim_suffix|>"] # 50259
# PSM 模板:<|fim_prefix|> P <|fim_suffix|> S <|fim_middle|> M
new_tokens = [prefix_id] + prefix + [suffix_id] + suffix + [middle_id] + middle
这是人写的、确定性的、离散的格式协议——和 Prolog 里的 parent(X, Y) :- ... 在性质上是一样的。模型学不出"PSM 模板"——这个模板是由人作为不可学习的协议强加给模型的。stop_tokens、lang:python 等也都是同类——它们是架构里的符号骨架。
8.2 概率成分
# model.py:301-302
probs = F.softmax(logits, dim=-1)
idx_next = torch.multinomial(probs, num_samples=1)
这是一个条件概率分布的采样——和贝叶斯网络的边缘 / 条件推断在数学上是同一类操作。CodeGPT 没有显式的图结构,但它每个 token 上的 next-token 分布就是一个超大规模的隐式贝叶斯模型——只是这个 CPT 是 50304 个值、由神经网络给出,不再是查表。
8.3 神经成分
12 层 Block × (注意力 + MLP) × 12 个 head = 124M 参数:
# model.py:102-105
def forward(self, x):
x = x + self.attn(self.ln_1(x))
x = x + self.mlp(self.ln_2(x))
return x
这里的所有"知识"都在 self.attn、self.mlp 的权重矩阵里,由 train.py 的 F.cross_entropy 通过梯度下降一格一格填进去。这部分完全不可枚举、不可解释、连续可微——这是纯深度学习的部分。
8.4 三层夹心结构
┌──────────────────────────────────────┐
│ 符号层 特殊 token / chat template │ ← 人写的协议骨架
│ stop_tokens / FIM 模板 │
├──────────────────────────────────────┤
│ 概率层 softmax → multinomial │ ← 把 logits 解释为分布
├──────────────────────────────────────┤
│ 神经层 12×Block, 124M 权重 │ ← 梯度下降学习的部分
└──────────────────────────────────────┘
任何能跑的大模型系统都是这种"三明治"——纯神经的核心,外面包一层概率解释,最外面是符号协议。 这不是历史遗留,是必然——纯神经模型没法决定"什么时候停止生成"(这是符号问题)、没法决定"采样还是 argmax"(这是概率问题)。
9. 神经-符号混合:现代系统都不是纯种
回顾一下产业现状:
- Tool calling / function calling:模型生成的不是答案,是符号化的函数调用,由外部代码(解释器、计算器、搜索引擎)执行——纯神经搞不定算术。
- Verifier-based RL (OpenAI o1 / DeepSeek R1):用符号验证器(单元测试通过 / 数学题答案匹配)做 reward,再用 RL 把验证信号反向传到神经权重。
- RAG:从向量库(神经检索)+ 知识库(符号文档)拼出 prompt,再让模型生成——本质是把"事实查询"留给符号、"语言生成"留给神经。
- Lean / Coq + LLM:LLM 提议证明步骤,符号系统验证。神经做"想法",符号做"裁判"。
- CodeGPT 的 FIM:特殊 token (
<|fim_*|>) 是符号协议,模型在协议骨架上学连续分布——这就是一个最小的 neural-symbolic 设计。
为什么混合?因为三种范式的强项和弱项几乎完美互补:
| 任务 | 最适合的范式 | 原因 |
|---|---|---|
| 自然语言理解 / 生成 | 神经 | 高维感知、模糊匹配 |
| 数学推理、定理证明 | 符号 | 需要可证明性、零容错 |
| 因果推断、不确定性量化 | 贝叶斯 | 概率原语是一等公民 |
| 长程规划、多步推理 | 神经主导 + 符号兜底 | 神经做候选,符号验证 |
| AST 操作、编译 | 符号 | 离散结构、严格类型 |
| 代码生成 | 神经 + 执行反馈 | 神经写代码,解释器是验证器 |
未来 AI 不是某一派胜出,而是三派各自占据自己的层。 这也是 docs/SYNTHETIC_DATA.md 里讨论的"执行反馈是最诚实的 reward"——那个反馈天然是符号的(解释器要么报错要么不报错)。
10. 给用户原问题的最终回答
回到一开始的问题——"GPT 是不是把训练数据当成一堆可执行的符号代码来执行?"
答案分三层:
第一层(直觉是对的):
是的。训练数据塑造了模型行为,正如代码塑造了程序行为。改数据可以改模型,这点和"改代码改程序"同构。
第二层(更精确):
训练数据不是被"执行"的,而是被"编译"成权重。SGD 是编译器,权重是编译产物,前向传播是执行。和符号代码的关键区别是:编译是统计性、有损、不可逆的——你不能从权重反推出训练数据,正如不能从二进制反推出源码。
第三层(彻底澄清):
训练数据和"规则"不是同一种东西。训练数据是例子;权重里的"规则"是 SGD 从这些例子归纳出来的、连续的、概率性的、不可枚举的隐式模式。这一步归纳——从离散例子到连续分布——是符号 AI 永远做不到的、深度学习的核心贡献。
而贝叶斯网络正好是介于两者之间的中间形态:图结构是符号的(可读、可枚举),CPT 是概率的(从数据学)。它在小数据 + 强先验 + 需要因果解释的场景下,至今好用。
所以正确的心智模型不是"二选一",而是:
知识由人写 ←─────────────────────→ 知识由数据写
↑ ↑
符号 AI → 贝叶斯网络 → 深度学习
Prolog 因果图 Transformer
专家系统 HMM/Naive Bayes CodeGPT
Lean/Coq VAE (混合)
当前 (2026) 的工业级 AI 系统几乎全部是混合体:神经做核心、贝叶斯做不确定性建模、符号做协议骨架和验证。CodeGPT 自身就是这种三明治结构的一个最小样本——forward 是神经,F.softmax + multinomial 是概率,<|fim_*|> 模板和 stop_tokens 是符号。三个范式不是替代关系,而是栈关系。
读这篇文档的最大收获,应该是:以后看任何 AI 系统,都能下意识地把它拆成"哪一层是符号、哪一层是概率、哪一层是神经"——这是分析、调试、设计 AI 系统的基本功。