注意力关联
Attention relationship
模型预测每个 Token 时,都会将上下文中的所有其他 Token 纳入考量——有些权重很高,有些几乎没有影响。两个 Token 之间的配对称为注意力关系;有意义的配对(例如“她”和“Sarah”,或 getUser() 调用与 getUser 函数定义)会比无关配对产生更强的相互影响。包含 N 个 Token 的上下文,大约有 N² 个关系。
模型表面上的理解能力就存在于这些配对关系中。当它正确解析一个代词时,是因为“她”与“Sarah”之间的注意力关系很强。当它用正确参数调用函数时,发挥作用的是调用位置与之前读过的函数定义之间的关系。这些关系都不是查询出来的——每次模型请求都会针对每一对 Token 重新计算。
N² 这个数字值得仔细体会,因为它的增长速度比直觉想象得更快:
| 上下文大小 | 配对数量(约 N²) |
|---|---|
| 1,000 个 Token | 约 100 万 |
| 10,000 个 Token | 约 1 亿 |
| 100,000 个 Token | 约 100 亿 |
每个配对关系还会被计算不止一次。模型包含多个注意力头——前沿模型的确切数量尚未公开,但估计在五十到一百之间较为合理——每个注意力头都会计算自己版本的所有关系。因此,上表中的每个配对都会在每个注意力头上重复计算。配对数量极其庞大。
对于任何具体任务,真正重要的关系只有少数几个。你的指令与受它约束的代码之间的配对,就是少数关键关系之一;关系池中的其他内容几乎全是噪声。而二者的增长速度并不相同:关键关系的数量大致保持不变,关系总数却随上下文大小呈平方增长。在 1,000 个 Token 时,你关心的配对只是百万分之一;到 100,000 个 Token 时,它变成百亿分之一。这就是注意力预算背后的算术,而当关键关系分到的份额过于稀薄时,人的感受就是注意力退化。
用法:
“它总是把 diff 里的两个 user 符号混在一起——听起来我们进入低效区间了。”
“对,每个调用位置与其声明之间的注意力关系都在和另一个符号竞争——Token 形式相同,绑定关系却不同。给其中一个重命名,配对就会更清晰。”