AI/ML 详解:LLM 基础

Day 1 · 2026-05-19
面向:有编程经验的非 AI 方向工程师
工程对应 → super-individual D2: Context Engineering(Attention 在 context window 中的工程应用)

Transformer 架构Transformer Architecture

LLM理论
一句话解释

就像把"逐字读"的串行流水线换成了"全员同时开会"的并行架构 —— 每个 token 一次性看到全文,再决定自己要表达什么。

它解决什么问题

2017 年之前,处理文本主流是 RNN/LSTM,本质是个 for 循环:必须先算完第 t 个词,才能算第 t+1 个。这导致两个痛点:(1) 训练不能并行,慢;(2) 长距离依赖容易"遗忘"(梯度消失)。Transformer 用"自注意力"一次性建立任意两个位置的连接,于是 GPU 可以满负载并行,长依赖也不丢。

工作机制(直觉版)

把每个 token 想象成一个对象,它有三个属性:Query(我想找什么)、Key(我能提供什么)、Value(我实际的内容)。每一层的逻辑大致是:

# 伪代码:一层 Transformer block
for token in sequence:
    # 1. 和全文每个 token 做 Q·K 相似度匹配(像数据库 JOIN)
    scores = token.Q @ all_tokens.K.T
    weights = softmax(scores)
    # 2. 按权重把别人的 Value 取过来做加权和
    token.new = weights @ all_tokens.V
    # 3. 再过一个前馈网络(相当于一个非线性映射)
    token.out = FFN(token.new + token)  # 残差连接

这样的 block 堆 12~96 层,每层都让 token 重新"问一遍全文",表示就越来越丰富。

代码示例
# 用 transformers 库加载一个 Transformer 模型,10 行看到全貌
from transformers import AutoTokenizer, AutoModel
import torch

tok = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")

inputs = tok("Transformers changed NLP.", return_tensors="pt")
with torch.no_grad():
    out = model(**inputs)

# out.last_hidden_state 形状:[batch, seq_len, hidden_dim]
# 每个 token 都被编码成一个 768 维向量,含了它在上下文中的"含义"
print(out.last_hidden_state.shape)  # torch.Size([1, 6, 768])
常见误区
误区:"Transformer = ChatGPT"。其实 Transformer 只是骨架,原始论文是给翻译做的(Encoder-Decoder)。GPT 用的是只取 Decoder 的变体,BERT 用的是只取 Encoder 的变体。架构是地基,行为靠训练目标和数据塑造。
关键资源
实践场景

经典:所有现代 LLM(GPT、Claude、Gemini、Llama)都是 Transformer。你的场景:当你用 Claude 写每日总结,它把你贴进去的 5000 字会议笔记一次性"扫"成一个语义向量,再生成摘要 —— 这是 Transformer 的并行注意力在帮你省时间。

English Summary
Transformers replaced recurrent loops with parallel self-attention, letting every token attend to every other token in one pass. This unlocked GPU-scale training and is the backbone of all modern LLMs (GPT, Claude, Llama).
思考题
Transformer 比 RNN 快是因为"并行"——训练时确实并行了,但推理时(自回归生成)还能并行吗?为什么?
推理时不能。生成第 N+1 个 token 必须先有第 N 个 token,本质又退化成串行循环——这就是为什么 LLM 推理慢、要靠 KV Cache 优化、要做 Speculative Decoding。但有个关键区别:训练时 N 个 token 一次性并行计算所有梯度,所以训练成本是 O(n);推理时虽然串行,但每步内部的 Attention 仍是并行的,所以仍快于 RNN。这也启发了:现代推理优化的核心不是"并行 token",而是"压缩单步开销"——比如把 KV 缓存复用、把矩阵乘法用 FlashAttention 重排。
如果 Attention 能让任意两个位置相连,为什么还需要堆 96 层?一层够吗?类比 SQL 多次 JOIN 的必要性。
一层不够。一层 Attention 只能做"一跳查询"——A 查 B,B 查 C,但 A 还没法用上 C 的信息。多层就是反复"扩散":第二层时 A 看到的 B 已经融合了 C 的信息,第三层 A 又能拿到 D 的间接关联。类似 SQL 多次 JOIN——单次 JOIN 只能连两张表,要查"朋友的朋友的朋友喜欢什么"必须递归连接。深度让模型从"匹配"升级到"推理链"。但也有边际效应:超过约 100 层收益急剧递减,因为信息已经充分混合,再深只是加噪声。这是为什么 Llama-3 405B 只 126 层,没有无限堆深。
Transformer 计算复杂度是 O(n²)——这个"原罪"决定了哪些应用边界?为什么 GPT-4 上下文做到 128K 还能用?
原罪让朴素 Transformer 难以处理长序列:序列长度翻倍,计算和显存四倍。这把它挡在了"全基因组分析、整本书一次性建模"之外。能撑到 128K 是靠工程堆叠:(1) FlashAttention 把内存搬运优化掉,让 attention 算得起;(2) GQA/MQA 共享 KV 减少内存压力;(3) RoPE 让位置编码可外推;(4) 推理时用 chunked prefill 和 KV cache 复用。但要注意:128K 能"装下"不等于"用好"——很多模型在长上下文里检索能力骤降(lost in the middle)。这告诉你架构瓶颈被工程绕过去时,常常引入新的能力陷阱。
BERT (Encoder-only)、GPT (Decoder-only)、T5 (Encoder-Decoder) 三种架构——为什么 2024 年后基本只剩 Decoder-only?
本质是任务统一带来的胜利。Decoder-only 用"下一个 token 预测"作为统一接口,几乎所有 NLP 任务(翻译、问答、摘要、分类)都能转写成"续写"——大一统之后,规模化收益最大。Encoder-only(BERT)擅长理解但不会生成,应用面窄。Encoder-Decoder(T5)参数翻倍但收益有限。还有个工程因素:Decoder-only 的 KV Cache 友好、自回归推理基础设施成熟。但 2024 年后小型化、专用模型(embedding、reranker)又重新拥抱了 Encoder——架构选择仍是任务驱动,"赢者通吃"并不是终局。延伸:Hyung Won Chung 的"Decoder-only is all you need"演讲。
残差连接 + LayerNorm 看似工程细节,但去掉就训不动——这揭示了"深度学习能 scale"的关键前提是什么?
这俩是"梯度高速公路"。残差让梯度可以跨层直接回传不被乘性衰减,LayerNorm 让每层输入分布稳定不爆炸。没它们,96 层网络的梯度要么消失要么爆炸——根本没法收敛。深层洞察:深度学习能 scale 不是因为"更深的网络更强",而是因为"我们能稳定地训练更深的网络"。这是个微妙的转折——模型架构(Transformer)的成功一半归功于辅助机制(Norm + Residual)。类比软件工程:分布式系统能 scale 不是因为"机器多",而是因为有共识协议、心跳、故障转移这些"看不见的基础设施"。

Attention 机制Attention Mechanism

LLM核心
一句话解释

就像 SQL 的 JOIN —— 每个词都拿着自己的"查询条件"去全文里匹配,找出最相关的词,然后把它们的内容加权拷过来一份。

它解决什么问题

"The cat sat on the mat because it was warm." 这里的 it 指 mat 还是 cat?传统模型只能按距离猜,而 Attention 让 it 这个位置主动去问全文:"谁和我最相关?" 然后把 mat 的向量按高权重拿过来,自己的表示里就编码了"它指 mat"。本质:解决长距离指代和上下文聚焦。

工作机制(直觉版)

核心公式 Attention(Q,K,V) = softmax(Q·Kᵀ / √d) · V。白话翻译:"拿查询 Q 和所有 Key 做点积算相似度,归一化成权重,再去加权求和所有 Value。" 就是带权查表。

# 4 行 numpy 看懂 attention
import numpy as np
def attention(Q, K, V):
    scores = Q @ K.T / np.sqrt(K.shape[-1])  # 相似度
    weights = np.exp(scores) / np.exp(scores).sum(axis=-1, keepdims=True)
    return weights @ V                        # 加权求和

Multi-Head Attention = 同时开多个"独立查询通道",每个 head 关注不同维度(句法/语义/指代…)的关系。

代码示例
# 看看 GPT-2 实际在"关注"哪些词
from transformers import GPT2Tokenizer, GPT2Model
tok = GPT2Tokenizer.from_pretrained("gpt2")
model = GPT2Model.from_pretrained("gpt2", output_attentions=True)

inputs = tok("The cat sat on the mat", return_tensors="pt")
out = model(**inputs)
# out.attentions[layer][batch, head, query_pos, key_pos]
attn = out.attentions[-1][0, 0]   # 最后一层第 0 个 head
print(attn.shape)  # [6, 6],每个词对其他词的注意力权重矩阵
常见误区
误区:"Attention 就是加权平均"。区别是权重由输入动态算出来的,不是固定参数。每来一句新话,权重就重新分配 —— 这才是它能"理解上下文"的根本。
实践场景

经典:机器翻译时,目标语每个词都通过 attention 去"看"源语对应的词。你的场景:给孩子讲故事时,Claude 之所以能记住第一段提到的"小狐狸"在第三段还是同一只狐狸,靠的就是 attention 跨段建立指代连接。

English Summary
Attention computes a weighted sum of values, where weights come from query-key similarity. It lets each token dynamically pull context from any position, replacing fixed locality with content-based routing.
思考题
把 Attention 类比成 SQL JOIN——这个类比在哪里破?KV Cache 在这个类比里对应什么?
类比破在三处:(1) SQL JOIN 是离散等值/范围匹配,Attention 是连续相似度加权——所有 Key 都参与,只是权重不同;(2) JOIN 结果是表,Attention 结果是加权向量,已经做了"聚合";(3) JOIN 一次完成,Attention 要堆很多层反复"重新 JOIN"。KV Cache 在类比里对应"物化视图(materialized view)"——把已经算过的 K、V 缓存下来,新 token 进来只需"增量更新"而不必重算整张表。这个类比的价值不在精确,而在让你建立"内容路由"的直觉:和 grep/JOIN 一样,都是"按内容查找相关项",只是粒度和数学形式不同。
Q、K、V 三个矩阵都是 token embedding 的线性变换——为什么不直接用 embedding 自己跟自己做 attention?分开训三套矩阵的本质收益是什么?
核心收益是"角色分离":同一个词在"查找时"想要的特征和"被查找时"提供的特征往往不同。比如"它"作为 Q 时关心"我要指代谁",作为 K 时关心"我是不是一个被指代候选"。如果共用一套向量,模型只能在"提问能力"和"应答能力"之间妥协。分开训三套就让模型有自由度学到"非对称关系"——A 关注 B 不代表 B 关注 A。这和数据库设计里"主键 vs 外键 vs 业务字段分离"是一回事:物理上可以合并,但分开能让索引、查询、修改各自优化。延伸:后来的 MQA/GQA 又把 K、V 共享了一部分换内存,是工程上的反向妥协。
为什么要除以 √d?取消这个除法会发生什么?这和"归一化"在数据库索引设计中的作用有何相似?
不除会让点积数值随维度 d 增长(高维向量内积期望值正比于 √d),结果 softmax 的输入过大 → 输出退化成 one-hot → 梯度消失 → 训不动。除以 √d 把 score 的方差归一化到 1 附近,softmax 才能保持有意义的"软"分布。类比:数据库索引按 hash 分桶时也要"归一化"分布,否则某个桶过载(softmax 退化成 one-hot 就是"所有查询都打到一个桶")。深层教训:深度学习里大量"看似偶然"的细节(除以 √d、LayerNorm 的 ε、Adam 的 β1=0.9)都是在管理"数值分布"——这是一门工程艺术,不是数学必然。
Multi-Head 用 8 个头比 1 个大头强,参数量基本一样——凭什么效果更好?这和"集成学习"有何关系?
本质是"强制多样性"。一个大头在训练中只能学到一种最优注意力模式;8 个小头被切分了,每个头看不同子空间,倾向自然学到不同关系(语法/语义/指代/位置近邻)。这和集成学习(bagging、ensemble)思路同源:用结构约束逼出多样性,再合并。但区别在于 Multi-Head 是端到端训练的,"多样性"是自然涌现的副产品,不像 ensemble 是人为构造的。Mechanistic Interpretability 研究确实发现:不同 head 学到了 induction head、name mover、duplicate token detector 等不同"电路"——所以"多头"不是噱头,是真实的功能分工。
Linear/Sparse Attention 试图把 O(n²) 降到 O(n)——为什么至今没取代标准 Attention?它们牺牲了什么?
核心牺牲是"全局精确匹配"。标准 Attention 让每个 token 看到所有 token 的精确权重;Linear Attention 用核技巧近似(牺牲精度),Sparse Attention 只看局部窗口或定模式(牺牲全局)。在中短上下文(<32K)下精度损失会让能力明显下降,工业界宁愿用 FlashAttention 把常数项压到极致也不切换。但在超长上下文(1M+)下,O(n²) 已经不可行,Mamba/SSM 等线性方法重新成为活跃赛道。这告诉你"算法复杂度"不是孤立指标——常数项、精度损失、硬件适配都参与博弈。延伸:可能未来是"混合架构"——前几层 Attention 抓全局,后几层 Linear/SSM 处理细节。

Tokenization 分词Tokenization

LLM工程
一句话解释

就像编译器把源码切成 token —— LLM 处理文本前必须先把字符流切成"词块",每个词块映射成一个整数 ID,模型其实只看 ID 不看字。

它解决什么问题

词表不能太大(每个词单独编号 → 几百万词表 → 矩阵爆炸),也不能太小(按字母切 → 序列太长,模型记不住语义)。解决方案:BPE / WordPiece / SentencePiece —— 按"高频字节组合"自动学习一个 5 万左右的子词表。常见词整词留下,生僻词拆成几片。

工作机制(直觉版)

BPE 训练过程像"贪心压缩":从单字符开始,反复把出现频率最高的相邻字符对合并成一个新 token,直到词表达到目标大小。

# BPE 直觉
# 初始: ['l','o','w','e','r']
# 发现 'l'+'o' 频次最高 → 合并 → ['lo','w','e','r']
# 再发现 'lo'+'w' 频次最高 → 合并 → ['low','e','r']
# 最终高频整词留下,低频词被拆成子词片段
# "tokenization" 可能被切成 ["token", "ization"]

结果:英文 1 token ≈ 4 字符 ≈ 0.75 词;中文 1 个汉字常占 2-3 个 token。这直接影响你的账单和上下文长度。

代码示例
import tiktoken  # OpenAI 官方分词器

enc = tiktoken.get_encoding("cl100k_base")  # GPT-4 用的

text_en = "Tokenization is fun!"
text_zh = "分词其实很有意思!"

print(enc.encode(text_en))         # [3404, 2065, 374, 2523, 0]
print(len(enc.encode(text_en)))    # 5 tokens
print(len(enc.encode(text_zh)))    # 11 tokens(中文更贵!)

# 解码回去
print(enc.decode([3404, 2065]))   # "Tokeniz"  ← 不是完整词
常见误区
误区:"1 token = 1 个词"。错。"strawberry" 在 GPT 里被切成 ["straw","berry"] 三段,这也是为什么早期 GPT 数不清 "strawberry 里有几个 r" —— 它根本看不到字母 r,只看到 token 块。
实践场景

经典:评估 API 成本(OpenAI 按 token 收费)。你的场景:同样一段会议笔记,用中文写比用英文写贵 2-3 倍。如果是高频自动化任务(如每天总结新闻),用英文 prompt + 中文输出能省钱。

English Summary
Tokenization splits text into subword units (via BPE/WordPiece) so the vocabulary stays manageable while rare words remain encodable. Token counts drive both context limits and API pricing.
思考题
GPT 数不清 strawberry 里有几个 r——除了 tokenization 这个根因,有什么 prompt 工程能绕过?这教你什么"系统性 bug"思维?
绕过方法:(1) 让模型先"把每个字母列出来"(一旦字符被显式拆开就能数);(2) 用 code interpreter 调用 Python;(3) 让模型先把字母用空格分隔再处理。系统性 bug 的思维:根因常在"低层抽象"——这里是 token 表示——但在"高层接口"看不到。修复策略是"绕过抽象层"而非"在抽象内修复"。类比软件:你不能在 ORM 层修复 SQL 注入,必须下到 SQL 层;同样不能在文本层修复 token 限制,必须把任务转换成 token 友好形式。这就是为什么 prompt 工程本质是"理解模型的认知盲区,再绕路"。
中文 tokenization 比英文贵 2-3 倍——这是技术问题还是商业策略?如果让你设计中英文同样高效的 tokenizer 会怎么做?
主要是技术问题:BPE 训练数据中英文比例失衡(GPT-4 训练语料英文占 90%+),所以英文常用 1 token 一词,中文常 2-3 字节合成一个汉字。也有商业惯性——OpenAI 没动力为中文优化。设计方法:(1) 在训练语料里强制中英文均衡;(2) 用 SentencePiece + Unigram LM 而非 BPE,能更好处理无空格语言;(3) 给中文设大型基础词表(比如直接收 8000 常用汉字单独建 token)。DeepSeek 和 Qwen 的 tokenizer 处理中文就比 GPT 高效。延伸思考:这暴露了"看似中立的技术决策"背后的语言不平等——和"UTF-8 对 ASCII 友好、对 CJK 不友好"是同一类问题。
词表太小(256)和太大(500K)分别什么问题?类比 hash 表 bucket 大小的取舍。
太小(256,等于按字节):每个字符一个 token,序列变得非常长,模型要花更多算力建立"字母→词"的关联,长依赖更难学;优点是几乎不会有 OOV(未登录词)。太大(500K):每个常见词独立编号,序列变短,但 embedding 矩阵巨大(500K×4096 ≈ 2B 参数都用来记词表),训练效率低、低频词学不好。最优在 32K~128K 之间。类比 hash bucket:太多 bucket 内存浪费、cache miss 多;太少冲突严重,每次查找退化成 O(n)。词表大小本质是"频率分布的离散化粒度"——和 hash 一样要匹配数据分布。
不同厂家 tokenizer 不统一——这和"字符集编码大战"(UTF-8 vs UTF-16) 有何相似?
相似在四点:(1) 都缺乏强制标准,各家按训练数据/工程偏好自选;(2) 都形成"高切换成本"——一旦选定,整个模型权重就绑死,换 tokenizer 等于重训;(3) 都有"先发优势固化"——GPT-2 的 BPE 被沿用多年,UTF-8 因 ASCII 兼容统治了 Web;(4) 都引入"看不见的成本"——你按 token 付费但不同模型 token 量不同,类似存储同样的中文 UTF-8 比 UTF-16 多 50%。不同在:字符集后来统一到 Unicode,tokenizer 大概不会统一——因为它和模型权重耦合。这告诉你:标准化的前提是"接口可独立演进",tokenizer 缺这个前提。
如果未来出现 byte-level tokenization(每字节就是一个 token),在哪些场景会赢?又会牺牲什么?
会赢的场景:(1) 多语言/小语种——不再需要为每种语言调 tokenizer;(2) 代码/二进制数据——字符级处理更精确;(3) 字母级任务(拼写、计数 r)——不会再有 strawberry 问题;(4) 鲁棒性——对错别字、不规范输入更宽容。牺牲:(1) 序列长度暴增 4-8 倍,O(n²) 复杂度直接炸;(2) 长依赖更难学(模型要先重建"词"概念);(3) 训练数据效率下降。Meta 的 BLT (Byte Latent Transformer, 2024) 用"动态 patching"——熵高的地方细分、熵低的地方合并——试图鱼与熊掌兼得。如果硬件继续解决 O(n²) 瓶颈(线性 attention、Mamba),byte-level 完全可能成为下一代默认。

位置编码Positional Encoding

LLM理论
一句话解释

Attention 本身是"无序集合"操作(像 Python 的 set),不知道谁在前谁在后。位置编码就像给每个 token 戳上一个"位置 ID",让模型分得清"狗咬人"和"人咬狗"。

它解决什么问题

self-attention 计算 Q·Kᵀ 时,词的顺序完全没参与运算 —— 把句子打乱再算,结果不变。这显然不行。解决方案:在 token 的 embedding 里"注入"位置信息,让位置 0 和位置 5 有不同的初始向量。

工作机制(直觉版)

三代演进:

  • Sinusoidal(原版 Transformer):用不同频率的 sin/cos 给每个位置生成一个独特向量,加到 token embedding 上。优点:能外推到训练时没见过的长度。
  • Learned(GPT-2/BERT):直接学一个 [max_len, dim] 的查表矩阵,简单但不能外推。
  • RoPE 旋转位置编码(Llama/Qwen/现代主流):把位置变成"旋转角度",token 在高维空间里按位置转一定角度。两个 token 做 Q·K 点积时,自然就编码了"相对距离"。这是当下长上下文模型的标配。
# 直觉伪代码:RoPE 给位置 m 的向量旋转 m·θ 角度
def rope(x, pos):
    # x 是 token 的 Q 或 K 向量,按对划分
    for i, (a, b) in enumerate(pairs(x)):
        theta = pos / 10000 ** (2*i / dim)
        a_new = a * cos(theta) - b * sin(theta)
        b_new = a * sin(theta) + b * cos(theta)
    return rotated_x
代码示例
# 观察位置编码对结果的影响
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

tok = AutoTokenizer.from_pretrained("gpt2")
model = AutoModelForCausalLM.from_pretrained("gpt2")

# 同样的 token,不同位置 → 不同的隐藏状态
ids_a = tok("dog bites man", return_tensors="pt").input_ids
ids_b = tok("man bites dog", return_tensors="pt").input_ids

with torch.no_grad():
    h_a = model.transformer(ids_a).last_hidden_state
    h_b = model.transformer(ids_b).last_hidden_state

# 即使是同样的 3 个 token,因为位置不同,最后表征完全不一样
print(torch.allclose(h_a, h_b))   # False
常见误区
误区:"位置编码就是把 1, 2, 3 加到 embedding 上"。这样会让位置数值压倒语义。真实做法是用高维度的周期函数或旋转,让"相对距离"在向量空间里有几何意义 —— 这是 RoPE 能支持 128K 长上下文的关键。
实践场景

经典:所有需要顺序敏感的任务(翻译、代码生成、推理链)。你的场景:当你让 Claude 做"分析这 50 页 PDF 报告",模型必须分得清第 3 页和第 47 页的内容 —— 这就靠位置编码(RoPE)在长上下文中保持位置感。

English Summary
Self-attention is permutation-invariant, so positional encodings inject order information into token embeddings. Modern LLMs use Rotary Position Embedding (RoPE), which encodes relative positions via rotation, enabling long-context extrapolation.
思考题
RoPE 能外推到训练长度之外——但超过 2-4 倍就性能崩——为什么?这暴露了"位置外推"的什么本质难题?
崩溃的根因是"频率覆盖盲区":RoPE 把不同维度配不同周期的正弦,训练时模型只见过某频率范围内的相位组合,外推时高频维度旋转到"训练分布之外"的相位区,模型从没见过这种 Q·K 模式。本质难题是:位置编码是"先验注入",但模型学到的是"先验上的特定行为",没法对未见的先验泛化。解决方向:(1) YaRN/NTK Scaling 通过插值压缩相位让外推像内插;(2) 训练时刻意混入超长样本(continual pretraining)。深层教训:神经网络外推泛化能力极弱,"理论上能外推"和"实际能外推"是两回事——这也是为什么"长上下文"是个工程而非算法问题。
三代位置编码(Sinusoidal/Learned/RoPE)演进逻辑是什么?为什么"相对位置"比"绝对位置"更好?类比 git 相对路径 vs 绝对路径。
演进逻辑:从"显式标位置"(Sinusoidal、Learned 给绝对编号)→"隐式编距离"(RoPE 让点积自然反映相对位置)。相对位置更好的原因:(1) 语言规律是相对的——"主语和谓语之间的距离"比"主语在第几个词"更重要;(2) 同一句话在不同上下文里整体偏移时,绝对位置变了但语义不变,相对位置编码能内在不变;(3) 更易外推。类比 git:commit hash 是绝对引用(精确但僵硬),HEAD~3 是相对引用(语义清晰、可移植)。同理代码里用 `../config` 比写死 `/Users/cissy/...` 更鲁棒。这是个反复出现的设计哲学:用"关系"代替"标识"。
位置编码加在 embedding 上会不会污染语义?模型如何把"位置"和"语义"分离学习?
会有干扰,但模型能学到分离。原因有两层:(1) 高维空间足够大(768-4096 维)——位置信号和语义信号可以占用不同子空间,互不冲突;(2) 训练时模型本身就在学"哪个维度是哪种信息"——它会自然把位置信息映射到对结果有用的子空间。RoPE 更进一步:位置不是加进去,而是用旋转作用于 Q、K 的不同对——这种"乘性而非加性"的注入更不易污染。但确实有副作用:早期层往往学到"位置模式",深层才用语义——你能在 attention map 里看到第一层往往是对角线(看附近 token)。
长上下文的三个瓶颈:位置编码、Attention 复杂度、KV Cache 内存——你赌哪个最先被突破?为什么?
个人押注 KV Cache 内存——因为这是最直接的工程瓶颈,已经有大量优化路径在落地:(1) GQA/MQA 共享 KV;(2) KV quantization 把 fp16 压成 int8/int4;(3) PagedAttention(vLLM)让 KV 像虚拟内存分页;(4) Sliding Window/Recurrent 抛弃远距离 KV。Attention 复杂度需要算法突破(Mamba 类),代价是精度——不容易完全替代。位置编码外推本质是泛化问题,最难。优先级排序:内存(工程)> 复杂度(算法+硬件)> 外推(理论)。这告诉你:判断瓶颈优先级时,"是否有清晰工程路径"是关键启发——纯算法/理论问题往往最慢。
给"视频帧序列"或"代码 AST 树"设计位置编码,1D RoPE 还够用吗?这暴露"位置"概念的什么深层假设?
不够。视频是时间×空间×通道的 3D 结构,AST 是树结构——1D 位置编码假设"位置是线性可比的",在这些结构上会丢失维度信息。改造方向:(1) 视频用 2D/3D RoPE(每个维度独立旋转),如 Sora 用了时空联合编码;(2) AST/图用 Graph Positional Encoding(基于图拉普拉斯特征向量、最短路径距离)。深层假设暴露:我们说"位置"时,其实是在说"在某个度量空间里的坐标"——文本碰巧是 1D 时间序列,所以 1D 够用。一旦数据有更丰富的结构,"位置"就必须重新定义。这是为什么多模态模型的核心难点之一是"统一位置编码"——把图像 patch、视频帧、文本 token、音频片段映射到同一个可比较的空间。
← 回到首页