MINI-TABPFN COURSE · LESSON 05

第 5 课讲义:Row-Level In-Context Learning——query 怎样读取 context?

这是一节可直接阅读、实现和验收的课程单元。页面正文由 canonical Markdown lesson source 投影生成。

第 05 / 08 课course-v0.5 / owner-review完整讲义 + 动手验收包
课程讲义 · 基础知识层canonical source: course/lectures/05-row-icl.md · 先建立概念、符号、公式与边界,再进入工程实现。

讲义定位

前四课把 scalar 变成 cell/row token。本课对应 TabPFN-3 Stage 3: In-context learning

核心直觉:Query 可读 context 证据,绝不可读 query 答案。关键问题是:标签从哪进入序列、四块 可见性如何写、如何用实验证明无泄漏?

与 TabPFN-3 Stage 3 对齐 / Mini 省略:官方叙述为 train↔train、test→train;ICL 对 test 侧可用 multi-query(icl_num_kv_heads_test=1);可有正交 label embedding 与 QASSMax。Mini 可先实现对称 MHA + 保守四块 mask,须标注。

1. 学习目标与先修知识

学完后你应该能够:

  1. 用 row token、context label、unknown label 组织统一 sequence;
  2. 解释为何 context label injection 合法,而 \(Y_{\mathrm{query}}\) 只能用于 loss;
  3. 写出 \(C\to C\)、\(Q\to C\)、\(C\to Q\)、\(Q\to Q\) 四块可见性;
  4. 0-based 切片写出 \(H_{\mathrm{context}}\) / \(H_{\mathrm{query}}\);
  5. 用 intervention、mask graph、permutation 排除泄漏;
  6. 区分「能读 context」与「学会了正确算法」。

符号:\(N_c,N_q\) context/query 行数,\(T=N_c+N_q\),\(D\)(本课常取 \(D_{\mathrm{row}}\))。

2. 条件预测与 ICL

\[p\!\left(Y_{\mathrm{query}}\mid X_{\mathrm{query}},X_{\mathrm{context}},Y_{\mathrm{context}}\right)\]

ICL 把该条件关系交给共享参数的 sequence model:不在测试时更新参数,而在 forward 中读 context。 Memory 是当前 episode 可见的 context rows 与 labels,不是永久 table。

3. 统一 sequence 与 label injection(canon §3.5)

\[R_{\mathrm{context}}\in\mathbb{R}^{B\times N_c\times D},\qquad R_{\mathrm{query}}\in\mathbb{R}^{B\times N_q\times D}\]
\[\begin{aligned} Z_{\mathrm{context}}&=R_{\mathrm{context}}+\operatorname{LabelEncoder}(Y_{\mathrm{context}}),\\ Z_{\mathrm{query}}&=R_{\mathrm{query}}+\operatorname{UnknownLabelEmbedding}(),\\ R&=\operatorname{concat}(R_{\mathrm{context}},R_{\mathrm{query}})\in\mathbb{R}^{B\times T\times D},\quad T=N_c+N_q. \end{aligned}\]

Query slice 不得使用真实 \(Y_{\mathrm{query}}\)。分类可用 task-local class embedding;回归可用连续 MLP。官方可对 train 侧使用正交初始化的 label embedding——Mini 可简化,须一句对齐。

4. 切片索引(0-based,与代码一致)

设 \(H=\operatorname{Transformer}(Z,\mathrm{mask})\in\mathbb{R}^{B\times T\times D}\)。推荐:

\[H_{\mathrm{context}}=H_{[:,\,0:N_c]},\qquad H_{\mathrm{query}}=H_{[:,\,N_c:T]}\]

等价代码:H[:, :N_c]H[:, N_c:T]

禁止混写 H[:, 1:N_c]H[:, N_c+1:T](会丢掉第 0 个 context、错切 query)。若坚持数学 1-based,须全文声明并与代码分开写,二者勿混。

5. 四块可见性(默认保守)

key: contextkey: query
query: context\(C\to C\) 允许\(C\to Q\) 禁止
query: query\(Q\to C\) 允许\(Q\to Q\) 默认禁止
  • \(C\to C\):context 互读,建模训练集内关系;
  • \(Q\to C\):主 adaptation 路径;
  • \(C\to Q\):禁止,避免 context 依赖未知 query;
  • \(Q\to Q\):默认禁止,避免 query 间标签通信。

官方:train↔train;test→train。Mini 简化:可用同一套 MHA 实现上述 mask。其他 mask 可研究,但须画图 声明。

Mask 在 softmax 之前对 blocked 位置填 \(-\infty\)。不要用下三角 causal mask 替代:row 顺序与 context/query 可见性是不同问题。

6. 为何不能填 query label

若训练时把真实 \(Y_{\mathrm{query}}\) 嵌入 \(Z_{\mathrm{query}}\),模型可读答案,但与部署不一致。 最强检查是 intervention:固定 prediction 输入,只改 evaluation 用的 \(Y_{\mathrm{query}}\), logits/hidden 须逐元素不变。须覆盖 dataloader、injection、mask、normalization、cache。

7. 两类常见错误

A. 把 label 当 feature 列拼接:难区分 supervision 与特征,且 column encoder 可能误用。 B. query 用真实 class index lookup:未知标签须用 unknown token / 零向量 / 显式 mask。

8. Mask 极性与玩具矩阵

例:\(N_c=3,N_q=2\),允许读取示意:

       C0 C1 C2 Q0 Q1
C0     1  1  1  0  0
C1     1  1  1  0  0
C2     1  1  1  0  0
Q0     1  1  1  0  0
Q1     1  1  1  0  0

再转为框架的 blocked=Trueallowed=True。必须打印最终送入 attention 的 mask,并用被禁 key 检查权重是否为零。

9. 与普通 sequence modeling 的区别

语言模型常用 causal mask:位置 \(t\) 只能看过去。Row-level ICL 的边界按 context/query 角色 划分,而不是按行号顺序。直接套 causal mask 可能造成:

  • 后面的 context 看不到前面的 context;
  • query 只能看到「排在前面」的 context,而不是全部 context;
  • \(Q\to Q\) 信息流与标签可见性不符合任务定义。

因此 mask 必须从 task semantics 推导。官方进一步对 test→train 使用 multi-query attention 以缩小 KV cache;Mini 可先用标准 MHA 实现同一可见性表,再在报告中注明工程差异。

10. 数据流边界

\[\text{cell}\to\text{column}\to\text{row tokens} \to\text{label injection}\to\text{masked ICL}\to\text{head}\]

分开两件事:

  • feature-value encoding:\(X\) 如何成为 cell/row representation;
  • context-label injection:已观察的 \(Y_{\mathrm{context}}\) 如何进入 task adaptation。

二者都影响预测,但不能写成同一步「表格 tokenization」。论文在更早阶段也可对 training rows 加入 target-aware embeddings(TabICLv2);课程本课焦点是 ICL 阶段的 label injection,前置若省略须标注。

11. 模块接口建议

class ICLTransformer(nn.Module):
    def forward(
        self,
        context_rows: Tensor,   # [B, Nc, D]
        context_labels: Tensor, # [B, Nc] or [B, Nc, ...]
        query_rows: Tensor,     # [B, Nq, D]
        context_mask: Tensor | None = None,  # [B, Nc]
        query_mask: Tensor | None = None,    # [B, Nq]
    ) -> tuple[Tensor, Tensor]:
        # returns H_context [B,Nc,D], H_query [B,Nq,D]
        # 内部:Z, mask, H = Transformer(...); 再按 0:Nc / Nc:T 切片
        ...

切片与 mask 构造应有单元测试;不要把「能跑完 forward」当成边界正确。

12. 训练 loss 不破坏输入边界(canon §3.1)

\[\mathcal{L} =\operatorname{loss\_fn}\!\bigl( f_\theta(X_{\mathrm{context}},Y_{\mathrm{context}},X_{\mathrm{query}},\mathrm{masks}),\, Y_{\mathrm{query}}\bigr)\]

\(Y_{\mathrm{query}}\) 只在 prediction 之后作 target;forward 签名不接收它。Data object 可以 同时持有 target,但不得流入 model 输入图。

13. 四个不可省略的审计

  • A leakage:改 \(Y_{\mathrm{query}}\) 的 evaluation copy,预测与 hidden 不变。
  • B context ablation:context label→unknown,预测可变但不得引入 query 答案。
  • C query permute:对齐后,在禁止 \(Q\to Q\) 时预测保持。
  • D mask graph:\([T,T]\) 四块图与代码 tensor 对照;对被禁 key 断言权重为 0。

任一 leakage 失败,后续 accuracy / RMSE 只能标 not-yet-verified

14. 知识检查

  1. 为何 context label 可进序列,query label 只能留在 loss?
  2. 四块可见性各表达什么?官方 train↔train / test→train 如何对应?
  3. 正确的 0-based 切片是什么?错写成 1:N_cN_c+1:T 会丢/错什么?
  4. 为何 causal mask 不一定适用于 task-level ICL?
  5. 强于静态读代码的 leakage test 怎么做?
  6. 若允许 \(Q\to Q\),哪些 invariance 要重定义?

15. 本课的硬结论

Row-level ICL 的核心是受任务语义约束的信息流:query 可读 context,不可读 query 答案。切片索引、 mask 极性与 label injection 未经可视化与 intervention audit,就不能声称实现了合法的 in-context prediction。

HAND-ON LAB · 工程实现与验收包

第 5 课:Row-Level In-Context Learning

项目问题

已有 context/query row tokens,但尚未让 query 合法读取 context;同时 query label 必须不可见。 对应讲义:lectures/05-row-icl.md(Stage 3;canon §3.5)。核心直觉:Query 可读 context 证据, 绝不可读 query 答案。

计算约束

\[\begin{aligned} Z_{\mathrm{context}}&=R_{\mathrm{context}}+\operatorname{LabelEncoder}(Y_{\mathrm{context}}),\\ Z_{\mathrm{query}}&=R_{\mathrm{query}}+\operatorname{UnknownLabelEmbedding}(),\\ R&=\operatorname{concat}(R_{\mathrm{context}},R_{\mathrm{query}})\in\mathbb{R}^{B\times T\times D},\quad T=N_c+N_q. \end{aligned}\]

默认保守可见性:\(C\to C\)、\(Q\to C\) 允许;\(C\to Q\)、\(Q\to Q\) 禁止

Mini 简化:对称 MHA + 上述 mask。官方:train↔train、test→train;test 侧可 multi-query (icl_num_kv_heads_test=1)——本课可不实现,须在报告一句对齐。

实现任务

  • models/icl_transformer.py
  • context / unknown label embedding;
  • context/query block mask;
  • 多 query batch forward。

验证实验

  1. 改 query label,预测与 hidden 不变;
  2. 屏蔽 context label,观察变化;
  3. 打乱 query 顺序并对齐;
  4. 打印 \([T,T]\) mask 四块图。

硬门

query-label leakage 失败则本课不通过;后续分类/回归结果视为无效。

交付

icl_transformer.py、mask 可视化、leakage regression test。

本课的具体教学包

时间内容证据
00:00–00:25sequence 组织写出 \([B,T,D]\)
00:25–00:55label injection 边界标出唯一 label 来源
00:55–01:35block mask打印 \([T,T]\)
01:35–01:50故意泄漏版让 leakage 失败一次
01:50–02:25Transformer forward多 query、padding
02:25–02:50四审计leakage / order / ablation / mask
02:50–03:00硬门评审通过才进第 6 课

1. Sequence contract(切片必须 0-based)

\[\begin{aligned} R&=\operatorname{concat}(R_{\mathrm{context}},R_{\mathrm{query}}) \in\mathbb{R}^{B\times T\times D},\qquad T=N_c+N_q,\\ Z&=R+\operatorname{concat}\!\bigl( \operatorname{LabelEncoder}(Y_{\mathrm{context}}), \operatorname{UnknownLabelEmbedding}()\bigr),\\ H&=\operatorname{Transformer}(Z,\operatorname{mask}),\\ H_{\mathrm{context}}&=H_{[:,\,0:N_c]},\qquad H_{\mathrm{query}}=H_{[:,\,N_c:T]}. \end{aligned}\]

等价代码:H[:, :N_c]H[:, N_c:T]

禁止 H[:, 1:N_c]H[:, N_c+1:T](会丢掉 index-0 的 context,并错切 query)。

Y_query 不属于 contract:

def forward(self, context_rows, context_labels, query_rows,
            context_mask=None, query_mask=None):
    ...

evaluation label 只在外部算 loss。

训练目标(canon §3.1):

\[\mathcal{L} =\operatorname{loss\_fn}\!\bigl( f_\theta(X_{\mathrm{context}},Y_{\mathrm{context}},X_{\mathrm{query}},\mathrm{masks}),\, Y_{\mathrm{query}}\bigr)\]

2. Label injection 失败方式

A:query 填真实 label → 即使 mask 对也已泄漏。用 unknown / 零向量。 B:无 role 区分时,unknown 可能与某 class embedding 重合。建议 context_role / query_role

3. 构造 block mask

def build_icl_mask(n_context: int, n_query: int, device=None):
    t = n_context + n_query
    mask = torch.full((t, t), float("-inf"), device=device)
    mask[:n_context, :n_context] = 0.0   # C -> C
    mask[n_context:, :n_context] = 0.0   # Q -> C
    return mask  # C->Q and Q->Q remain -inf

Padding 版本还要从 key 侧屏蔽无效 row。不要用下三角 causal mask 代替。Bool 极性必须打印核对。

4. Guided lab:四个实验

A:query label leakage

prediction_a = model(context_x, context_y, query_x)
# 外部改 Y_query 的 evaluation copy 后再跑同一 forward 输入
prediction_b = model(context_x, context_y, query_x)
assert torch.allclose(prediction_a, prediction_b)

更强:dataloader 内随机改 query label;output 与 hidden 不变。失败则停课。

B:context-label ablation

context labels → unknown;预测可变,但不得引入 query 答案。

C:query permutation

交换 query 顺序,inverse permute 对齐;在禁止 \(Q\to Q\) 时对齐后应一致。

D:mask graph

2 context + 2 query 的 heatmap,逐格核对四块。

5. 失败定位顺序

  1. collate 是否把 Y_query 并入 unified labels;
  2. injection 是否对 query slice 用了真实 label;
  3. mask 是否把 query key 置 \(-\infty\);
  4. bool mask 极性是否反;
  5. dropout / 随机输入是否不同;
  6. 残差/缓存是否残留 query label。

不要先调学习率。

6. 常见失败与评分

  • causal mask 冒充 context/query mask;
  • 只禁 \(C\to Q\) 却放行 \(Q\to Q\);
  • unknown 仍按真实 class index lookup;
  • 用 query labels 做 batch norm 统计;
  • 切片写成 1:N_c / N_c+1:T
  • 只测最终 logits,不测 injection 前 input 与 mask。

通过条件:

  1. 两套 query label → 预测/hidden 逐元素相同;
  2. context ablation 改变信息但不引入 query 答案;
  3. query permute 对齐后保持;
  4. toy mask 四块一致;
  5. 多 query + 至少一个 padded row。

评分:contract 20%,mask 35%,leakage 30%,解释与图 15%。leakage 失败 → not-yet-verified

课后作业

context row / label dropout;保持 query label 永不进入 forward。