有个现象非常神奇:
苹果 -> apple
香蕉 -> banana
猫 -> ?
大模型会答:
cat
再换一种:
苹果 -> 🍎
香蕉 -> 🍌
猫 -> ?
它又会答:
🐱
同一个模型,同一组权重,没有重新训练,只是 prompt 里的例子变了,它就临时换了任务。
这叫 In-Context Learning,上下文学习。
问题是:
模型权重明明没变,它到底“学”了什么?
一个很有解释力的答案是:
它不是现场学习新技能,而是在猜“我现在被放进了哪种任务模式”。
这就是 “In-Context Learning as Bayesian Inference”,把上下文学习理解成临时做贝叶斯推断。
先把贝叶斯讲成人话
贝叶斯听起来很数学,但最核心的想法很简单:
你本来对世界有一个猜测,看到新证据后,更新这个猜测。
比如你听到厨房里有声音。
你心里可能有几个候选解释:
| 猜测 | 一开始的可信度 |
|---|---|
| 家人在做饭 | 50% |
| 外卖到了 | 30% |
| 东西掉了 | 20% |
这叫先验,prior。它是你在看到更多证据前的初始判断。
然后你又闻到了炒菜味。
这个证据对“家人在做饭”很友好,对“外卖到了”也有点可能,对“东西掉了”就不太友好。
于是你的判断更新成:
| 猜测 | 看到证据后的可信度 |
|---|---|
| 家人在做饭 | 85% |
| 外卖到了 | 12% |
| 东西掉了 | 3% |
这叫后验,posterior。它是看完证据后的新判断。
中间还有一个词叫似然,likelihood。它问的是:
如果某个猜测是真的,那我看到这个证据的可能性有多大?
贝叶斯推断就是把这三件事连起来:
- 先验:我原来觉得哪些解释可能。
- 证据:我现在看到了什么。
- 后验:看完证据后,我该更相信哪个解释。
公式长这样:
这里的符号不用怕。
| 符号 | 人话 |
|---|---|
h | 一个候选解释,也可以理解成一种任务 |
D | 已经看到的数据,也就是 prompt 里的例子 |
P(h) | 先验,我一开始多相信这个解释 |
P(D \mid h) | 似然,如果这个解释是真的,看到这些例子有多合理 |
P(h \mid D) | 后验,看完例子后,我现在多相信这个解释 |
整句话翻译成人话就是:
一个解释最后有多可信,取决于它一开始多可信,以及它能不能解释眼前这些证据。
上下文学习里的“隐变量”:当前任务是什么
现在回到大模型。
prompt 里给了几个例子:
苹果 -> apple
香蕉 -> banana
猫 -> ?
这几个例子本身不是最终答案。它们更像证据。
模型真正要猜的是隐藏在背后的任务:
| 候选任务 | 能不能解释这些例子 |
|---|---|
| 中文翻译成英文 | 很能解释 |
| 中文变成 emoji | 解释不了 |
| 输出拼音 | 解释不了 |
| 输出水果类别 | 只能解释一部分 |
“当前任务是什么”没有直接写出来,所以它是一个隐变量。
所谓隐变量,就是:
它很重要,但你不能直接看见,只能通过现象反推。
大模型在 prompt 里看到几个输入输出对,就像侦探看到几条线索。它不是重新训练自己,而是在内部提高某个任务假设的可信度。
一个极小数字例子
假设模型脑子里只有两个候选任务:
T1:中文转英文。T2:中文转 emoji。
一开始,它不知道你想干嘛,所以先验各占一半:
| 任务 | 先验 |
|---|---|
T1 中文转英文 | 50% |
T2 中文转 emoji | 50% |
现在看到一个例子:
苹果 -> apple
如果当前任务真是中文转英文,看到这个例子很合理。我们给它一个似然 0.9。
如果当前任务真是中文转 emoji,看到 apple 而不是 🍎 就不太合理。我们给它一个似然 0.1。
贝叶斯更新前,可以把它想成“可信票数”:
| 任务 | 先验 | 似然 | 相乘后的分数 |
|---|---|---|---|
T1 中文转英文 | 0.5 | 0.9 | 0.45 |
T2 中文转 emoji | 0.5 | 0.1 | 0.05 |
把分数归一化,让它们加起来等于 1:
| 任务 | 后验 |
|---|---|
T1 中文转英文 | 90% |
T2 中文转 emoji | 10% |
只看一个例子,模型已经明显更相信“中文转英文”。
再看到第二个例子:
香蕉 -> banana
如果继续用同样的直觉,T1 再乘 0.9,T2 再乘 0.1:
| 任务 | 上一步分数 | 新似然 | 新分数 |
|---|---|---|---|
T1 中文转英文 | 0.45 | 0.9 | 0.405 |
T2 中文转 emoji | 0.05 | 0.1 | 0.005 |
归一化后:
| 任务 | 后验 |
|---|---|
T1 中文转英文 | 98.8% |
T2 中文转 emoji | 1.2% |
所以当你问:
猫 -> ?
模型最合理的输出就是:
cat
注意,这里没有任何权重更新。
变的是模型在当前上下文里对“任务是什么”的判断。
所以 ICL 到底学了什么
上下文学习里的“学习”,不是传统训练意义上的学习。
传统训练是:
看数据 -> 算 loss -> 反向传播 -> 改权重
上下文学习是:
看 prompt 里的例子 -> 在前向传播中形成当前任务判断 -> 按这个判断输出答案
权重没有变,变的是这一次推理过程里的内部状态。
可以把它想成:
模型长期训练得到很多“任务模式”的经验,prompt 里的例子帮助它临时选中其中一种模式。
这就像你去参加一个不说明规则的小测验。
题目给你:
2 -> 4
3 -> 9
5 -> 25
6 -> ?
你很快猜到规则是平方,所以答 36。
你不是刚刚才学会平方。你早就会。你只是通过前几个例子推断出“这次考的是平方规则”。
大模型的 ICL 也可以这样理解:
它不是从零学新技能,而是在上下文里识别并调用一个可能的任务结构。
更一般的公式:先猜任务,再预测答案
刚才只看了两个任务。真实情况里,候选任务可能非常多。
用数学写,就是:
h是一个候选任务。D是 prompt 里的示例。x_*是新输入。y_*是要预测的新输出。
模型可以先根据 D 更新对任务的判断:
然后预测答案:
这句话的人话版是:
对每一种可能任务,都想一下它会给什么答案;再按“我有多相信这个任务”加权平均。
如果模型 99% 相信这是中文转英文,那 猫 -> cat 的概率就高。
如果模型 99% 相信这是中文转 emoji,那 猫 -> 🐱 的概率就高。
如果证据不够明确,模型就会摇摆。
比如:
苹果 -> apple
橘子 -> orange
牛奶 -> ?
这可能是中文转英文,也可能是“食物名转英文”。两个任务在这个输入上刚好都输出 milk,所以你看不出冲突。
但如果接着问:
跑步 -> ?
“中文转英文”会输出 running,而“食物名转英文”会觉得任务范围不对。上下文里的任务判断会影响模型如何处理边界情况。
线性回归小例子:不背答案,而是猜一条线
研究 ICL 时,很多论文会用线性回归做玩具实验。
例如,prompt 里给模型几个点:
x = 1, y = 3
x = 2, y = 5
x = 3, y = 7
x = 4, y = ?
人会猜:
y = 2x + 1
所以 x = 4 时,y = 9。
从贝叶斯角度看,隐藏任务不是“中文转英文”这种离散任务,而是一条隐藏函数:
y = ax + b
这里的 a 和 b 不知道,需要从例子里反推。
prompt 里的点越多,可能的直线越少;证据越强,模型对某条线的信心越高。
这就是为什么线性回归经常被用来研究 ICL:它足够简单,可以精确讨论“模型是不是在上下文里学了一个函数”。
相关研究发现,Transformer 在某些受控任务上确实能表现得像在上下文里执行某种学习算法。这个算法有时接近最小二乘,有时接近梯度下降,有时又能被贝叶斯视角解释。
参考入口:What Can Transformers Learn In-Context?,以及 Transformers Learn In-Context by Gradient Descent。
为什么预训练会让模型拥有这种能力
大模型预训练时看的不是孤立句子,而是大量连续文本。
连续文本里天然有隐藏规律:
- 一篇文章有主题。
- 一段代码有风格。
- 一个表格有列含义。
- 一组问答有固定格式。
- 一个对话有角色关系。
模型训练目标是预测下一个 token。
要预测得好,它不能只看前一个词,还要推断更大的上下文状态:
这是什么文体?
现在是谁在说话?
用户想要什么格式?
前面几个例子暗示了什么规则?
当前文本属于哪种任务模式?
所以,预训练可能迫使模型学会一种能力:
从上下文里反推隐藏结构。
这正好像贝叶斯推断。
Xie 等人的解释是,如果预训练数据本身有长程一致性,比如同一篇文档里共享主题或隐含概念,那么为了预测下一个 token,模型就需要根据已经看到的上下文推断这个隐藏概念。于是,在下游 prompt 里,几个示例也能被当成证据,用来推断当前任务。
参考入口:An Explanation of In-context Learning as Implicit Bayesian Inference。
这和“模型记住了模板”有什么区别
有人会说:
这不就是记住了很多模板吗?
一部分确实可能是模板。大模型肯定见过大量 输入 -> 输出 的格式。
但 ICL 更有意思的地方在于,它不只复读固定模板,而是能根据例子临时适配:
blit -> A
dax -> B
wug -> A
zorp -> ?
如果前面例子暗示了某个抽象规则,模型可能会尝试跟随这个规则,即使这些词没有真实含义。
贝叶斯视角会说:
模板只是候选任务的一种。模型真正做的是在许多候选解释之间重新分配可信度。
这也解释了为什么示例顺序、数量、格式会影响结果。
因为这些都会改变模型对当前任务的判断。
贝叶斯视角和梯度下降视角冲突吗
不一定冲突。
研究 ICL 有两种常见解释:
- 贝叶斯视角:模型在上下文里推断隐藏任务。
- 梯度下降视角:Transformer 的前向传播可以模拟一种学习算法,像是在内部做几步梯度更新。
这两种解释听起来不同,但可能是在不同层面看同一件事。
比如你做线性回归,有两种说法:
- 贝叶斯说:我根据数据更新对斜率和截距的分布。
- 优化说:我用算法找到让误差最小的斜率和截距。
在某些条件下,这两种方法会给出接近的答案。
所以更稳妥的说法是:
ICL 不是只能用一种理论解释。贝叶斯解释强调“任务不确定性”,梯度下降解释强调“模型在前向传播中实现了学习算法”。
对小型受控模型,我们可以比较精确地验证这些说法。对真实前沿 LLM,它们更像有用的透镜,还不能说已经完全解释。
参考入口:In-Context Learning through the Bayesian Prism、Can Transformers Learn Full Bayesian Inference in Context?、Transformers Implement Functional Gradient Descent to Learn Non-Linear Functions In Context,以及持怀疑态度的讨论:Do Pretrained Transformers Learn In-Context by Gradient Descent?。
一个完整的人话模型
现在可以把整件事串起来。
当你写:
红 -> red
蓝 -> blue
绿 -> ?
模型内部可能发生的是:
- 它读到
红 -> red,开始猜:也许是翻译任务。 - 它读到
蓝 -> blue,翻译任务的可信度继续升高。 - 它看到
绿 -> ?,把绿放进“中文转英文”这个任务模式里。 - 它输出
green。
如果你写:
红 -> #ff0000
蓝 -> #0000ff
绿 -> ?
模型会换成另一个任务模式:
- 颜色中文名转十六进制色值。
绿对应#00ff00或类似答案。
它不是刚刚学会颜色,也不是修改了权重。
它是在上下文里做了任务识别。
用一句话总结:
Prompt 里的例子不是训练数据,而是证据;模型不是更新权重,而是更新对当前任务的判断。
这能解释哪些现象
贝叶斯视角可以解释很多你日常使用大模型时遇到的现象。
1. 为什么 few-shot 有用
几个例子能快速缩小候选任务范围。
没有例子时,模型只能靠指令猜;有例子时,模型能从输入输出关系里推断任务。
2. 为什么格式很重要
格式本身也是证据。
Q: ...
A: ...
和
输入:
输出:
会让模型进入不同的任务模式。
3. 为什么坏例子会带偏模型
如果示例里有错误,模型可能会把错误也当成规则的一部分。
比如你给它:
1 + 1 = 3
2 + 2 = 5
3 + 3 = ?
它可能会猜这是“正确答案加 1”的任务,而不是普通加法。
4. 为什么指令和例子冲突时会混乱
如果你写:
请把中文翻译成英文。
苹果 -> 🍎
香蕉 -> 🍌
猫 -> ?
指令说翻译,例子说 emoji。
这时模型要在两个证据之间权衡。不同模型、不同 prompt、不同采样参数,结果都可能变化。
5. 为什么模型会过度模仿
如果示例里的答案很啰嗦,模型可能也变啰嗦。
因为它不只在猜“语义任务”,也在猜“输出风格任务”。
它不能解释什么
贝叶斯视角很好用,但不要过度神化。
它不能保证:
- 模型真的严格按贝叶斯公式计算。
- 模型一定能从少数例子学到正确规则。
- 模型不会受表面格式、位置偏差、训练语料记忆影响。
- 模型能处理训练分布外的全新任务。
- 模型的每个 ICL 行为都来自同一种机制。
真实大模型很复杂。它可能同时使用:
- 模板匹配。
- 语义理解。
- 上下文里的任务推断。
- 内部模拟的优化算法。
- 训练时记下的常见格式和答案。
所以,最准确的说法不是:
ICL 就是贝叶斯。
而是:
ICL 可以被很好地理解成一种近似的、隐式的贝叶斯任务推断。
怎么把这个视角用到 prompt 里
理解这个视角后,写 prompt 会更清楚。
如果你想让模型稳定跟随任务,不要只写抽象要求。要给它足够清晰的证据。
1. 示例要代表真实任务
不要给太简单、太单一的例子。
如果真实任务里有边界情况,示例里最好放一个边界情况。
2. 示例格式要一致
模型会把格式也当成任务的一部分。
前两个例子用短答案,第三个例子突然长解释,模型就会犹豫。
3. 指令和示例不要互相打架
指令是一种证据,示例也是一种证据。
两者冲突时,模型不一定知道该信谁。
4. 先给规则,再给例子
规则给先验,例子给证据。
两者配合,比只给其中一个更稳定。
5. 对复杂任务,给反例
如果某些输出不应该出现,反例能帮模型排除错误任务。
这在分类、抽取、审核类任务里尤其有用。
最后用一句话收束
上下文学习最迷人的地方在于:
模型看起来像是在 prompt 里现场学习,但它更可能是在用已有能力,对“当前任务是什么”做快速推断。
这就是贝叶斯视角的价值。
它把一个神秘现象翻译成了更朴素的流程:
看到例子
-> 猜隐藏任务
-> 更新任务可信度
-> 按最可能的任务生成答案
所以,大模型的 ICL 不是魔法。
它更像一种临时的模式识别:
这几个例子告诉我,我现在应该扮演哪种函数。