第二模型交叉验证
在 B1→B18 的能力曲线上,今天是 B14「外部 ground-truth」段给裁判本身去偏的一跳。前两天(Day 136-137)已经用 deepseek-v4-flash 当 judge,在真标签 balanced_300 上出了混淆矩阵 + 带 CI 的三指标。但单一裁判有系统性偏差——prompt 敏感、家族偏好——它的「真召回率」里掺着裁判自己的脾气。今天接着学第二模型交叉验证:用
阶段: B14 · 外部 ground-truth AML eval(Day 131-140) 标签: #cross-validation #judge-debias #qwen3 #provider-agnostic
今日导引(由浅入深)
在 B1→B18 的能力曲线上,今天是 B14「外部 ground-truth」段给裁判本身去偏的一跳。前两天(Day 136-137)已经用 deepseek-v4-flash 当 judge,在真标签 balanced_300 上出了混淆矩阵 + 带 CI 的三指标。但单一裁判有系统性偏差——prompt 敏感、家族偏好——它的「真召回率」里掺着裁判自己的脾气。今天接着学第二模型交叉验证:用 NAMED Qwen3(经 OpenRouter)复跑同一子集,比两套指标的 delta 与 per-case agreement %。一致率低说明标注信号不稳,得回看 rubric。今天的最小可判定产出是:双模型对比表(两套 recall/FPR + 模型间 agreement %)——其中 runner 已支持 provider 切换,但真实两套数字仍待跑(需 key)+待数据。
定位本日:Day 137 的 CI 控住了方差(同分布换样本指标抖多少),今天的交叉验证补上 CI 控不到的另一维——偏差(裁判有没有系统性偏置)。方差靠重采样、偏差靠换裁判,两条腿齐了,Day 140 的 leaderboard 才站得稳。 本日的诚信边界要先讲在前面:今天只落地 raw per-case agreement %,更严谨的 chance-corrected κ(judge-human κ,≥50 hand labels)仍是 gated 的待办,不在本日产出,不得描述成已完成。
1. 机理精读
单模型 judge 的系统性偏差从哪来。 用一个 LLM 当裁判判 Is_Laundering,它的判定不是中立的真值,而是「这个模型在这套 prompt 下的倾向」。三类偏差最常见:(1) prompt 敏感——同样的 rubric 换个措辞,判定就漂移;(2) 家族偏好——模型对自家风格的输出/某类表述更宽容;(3) 校准偏差——某模型系统性地偏严或偏松。这些偏差是系统性的,不会被 bootstrap CI 消掉(CI 只刻画抽样噪声,不刻画裁判偏置)。所以再漂亮的 CI 也无法证明「这个召回率不是裁判幻觉」。
交叉验证为什么能暴露偏差。 换一个跨家族的独立模型(Qwen3,与 DeepSeek 是不同训练血统)跑同一批样本,如果两个裁判在大多数 case 上判定一致(agreement % 高),说明这批标注信号是稳的、不依赖单一裁判的脾气;如果一致率低,说明判定高度依赖裁判选择——此时任何单裁判的指标都不可信,必须回看 rubric(多半是 rubric 留了语义模糊空间,让两个模型各自脑补)。agreement % 是「标注信号稳定性」的体温计。
怎么读 agreement 数字(粗略经验阈)。 给一个工程上的粗略判读梯度(针对二元、平衡集的 raw agreement):≥0.90 说明 rubric 清晰、信号很稳,可放心用单裁判指标;0.800.90 可用但分歧样本值得回看;<0.80 警告——rubric 有明显模糊,单裁判指标不可信,应先迭代 rubric 再复跑。注意这是 raw agreement 的经验阈,换成 chance-corrected 的 κ 阈值不同(κ≥0.8 算 almost perfect、0.60.8 substantial)。本仓先用 raw 口径,κ 待落地后再换更严的标尺。
两个层面的比较:指标 delta vs per-case agreement。 这两者不能混。指标 delta 是聚合层——DeepSeek 的 recall 减 Qwen3 的 recall,回答「两个裁判对总体严松的差异」;per-case agreement % 是逐条层——两个裁判在每一条样本上判定是否一致的占比,回答「裁判信号有多稳」。两个裁判可能 recall 几乎相等(聚合 delta≈0)却在大量个案上互相矛盾(per-case agreement 低)——因为它们各漏各的、各误各的,聚合上抵消了。所以必须两个都看:delta 看总体偏置,agreement 看个案稳定。
raw agreement vs chance-corrected(Cohen's κ)的边界。 本日 seed 要的是 raw per-case agreement %(直接的一致条数占比),但要清醒它的局限:raw agreement 没扣除「碰巧一致」。在 balanced_300(约 50/50)上两个乱判的裁判也有约 50% 的偶然一致;若类别极不平衡,偶然一致率更高。更严谨的指标是 Cohen's κ(chance-corrected),它扣掉随机一致后再看「超出偶然多少」——κ=0 表示和瞎猜一样,κ=1 表示完全一致。本仓的 judge-human κ(≥50 hand labels)仍是 gated 的待办(见 MEMORY),所以今天先落地 raw agreement,κ 作为已知的下一步升级方向,诚实标注「未到」。
Qwen3 是「裁判去偏的第二意见」,不是「真值」。 两个 LLM 一致不等于一致就对——它们可能一起错(共同偏差)。真正的 ground truth 仍是 AMLworld 的 Is_Laundering 标签,两个 judge 都是在向它逼近。交叉验证的价值是「降低单裁判方差 + 暴露 rubric 模糊」,而不是「用两个裁判投票产生新真值」。这条边界在写对比表时必须诚实标注,否则会把「双裁判一致」错当成「判定正确」。
为什么选 Qwen3 而非 DeepSeek 的另一个版本。 去偏的关键是「跨家族」——同家族不同版本(如 V4-Flash vs V4-Pro)共享训练血统、tokenizer、对齐配方,它们的偏差高度相关,互相验证不出系统性偏置(一起偏、一起错)。Qwen3 是独立机构、独立数据、独立对齐的模型,与 DeepSeek 的偏差相关性低,才能当真正的「第二意见」。这条选型逻辑直接决定交叉验证有没有去偏效力——拿同家族模型互验等于自欺。
与相邻概念的边界。 今天 ≠ Day 135(那是单裁判对真标签的校准一致率,今天是两裁判之间的一致率);今天 ≠ Day 137(那是单裁判的 bootstrap CI,今天是换裁判看 delta);今天 ≠ Day 140(那是规则基线 vs 两 LLM 的三方 leaderboard,今天只做两 LLM 互比)。今天只回答:换一个跨家族裁判,指标变了多少、个案判定多大程度一致。
2. 手算 + 代码走读
2.1 手算:raw agreement 与「为什么 delta 小却 agreement 低」
先用 10 条手算把两个层面的差异看清。设两个裁判 DeepSeek(D)与 Qwen3(Q)在 10 条样本上的判定(P=可疑、N=正常),真标签放一起对照:
| # | 真标签 | D | Q | D对? | Q对? | D=Q? |
|---|---|---|---|---|---|---|
| 1 | P | P | P | ✓ | ✓ | ✓ |
| 2 | P | P | N | ✓ | ✗ | ✗ |
| 3 | P | N | P | ✗ | ✓ | ✗ |
| 4 | P | P | P | ✓ | ✓ | ✓ |
| 5 | N | N | N | ✓ | ✓ | ✓ |
| 6 | N | P | N | ✗ | ✓ | ✗ |
| 7 | N | N | P | ✓ | ✗ | ✗ |
| 8 | P | P | P | ✓ | ✓ | ✓ |
| 9 | N | N | N | ✓ | ✓ | ✓ |
| 10 | P | P | P | ✓ | ✓ | ✓ |
- D 的 recall:真 P 有 6 条(#1,2,3,4,8,10),D 抓对 5 条(#3 漏)→ 5/6≈0.833。
- Q 的 recall:Q 抓对 5 条(#2 漏)→ 5/6≈0.833。两者 recall delta = 0。
- 但 per-case agreement:D=Q 的有 #1,4,5,8,9,10 共 6 条 → agreement = 6/10 = 0.60。
结论一目了然:两裁判 recall 完全相等(聚合 delta=0),却在 40% 的个案上互相矛盾(#2,3,6,7 各漏各的、各误各的,聚合上抵消了)。只看 delta 会误判成「两裁判等价」,per-case agreement 才暴露出标注信号不稳。这就是为什么两个层面必须都看。以上为手算演示,非真实跑分。
2.2 代码走读:provider-agnostic runner 如何换裁判
今天换裁判走的是既有的 provider-agnostic 机制,核心是「只换 model id / baseURL,evaluation 逻辑一行不改」。Read 了 src/aml/groundTruthEval.ts,相关走读:
binaryEval(items, normalLabel)是 prediction-source-agnostic 的——它只吃{label, predicted}对,不关心predicted是 DeepSeek 还是 Qwen3 产生的。所以换裁判后,把 Qwen3 的判定映射成{label, predicted}再喂同一个binaryEval,就得到第二套tp/fp/tn/fn与三指标。评分函数零改动是交叉验证的工程支点(与 B12 「只换 model id、锁死 harness」同源纪律)。- per-case agreement 需要新写一小段比对:seed 说「另写 per-case 比对计算 DeepSeek-V4 vs Qwen3 的 agreement %」。它不在
groundTruthEval.ts里——逻辑很简单:对齐两套预测的同一 caseId,逐条比predictedA === predictedB,agreement % = 一致条数 / 总条数。这是本日要补的薄薄一层,复用不到现成函数,要诚实写成「新增比对」而非引用已有符号。 - 命令侧:seed 指明仍走
pnpm eval:agent框架,runner 默认 deepseek、可切 Qwen3 endpoint(经 OpenRouter 的 OpenAI 兼容路由,换 baseURL + model id)。这与 B12 的buildModel/buildOpenRouterModel是同一套 provider-agnostic 构造路径。 - per-case agreement 的实现要点:要按 caseId 对齐两套预测(不能假设两次跑批输出顺序一致),构
Map<caseId, predicted>再逐条比对。这与 B12abCompare按 taskId 对齐 base/tuned 是同一套「按 id 配对」的思路——顺序对齐会因任一裁判跳过/失败某条而错位。 - 成本口径要两侧一致:DeepSeek 与 Qwen3 的单次成本要么都算(
MODEL_PRICES命中 + usage 完整)、要么都标 undefined,不能一个真值一个假 0——这与 B12 的成本诚实纪律一致,跨裁判比较时尤其要守。
走读结论:评分侧(binaryEval)已 built+tested、对换裁判透明;per-case agreement 比对是本日待补的小逻辑;真实两套指标 + agreement % 需两次模型跑产生(待跑(需 key)+待数据)。
把「换裁判零改评分逻辑」这件事说透:它之所以可能,是因为评分函数只依赖 {label, predicted} 这个最小契约,而 predicted 怎么来的(哪个模型、哪个 provider、哪条 prompt)被完全隔离在 runner 层。这种「评分与生成解耦」是整个 B14 能反复换裁判、换数据源而不重写评分代码的根本原因,也是 prediction-source-agnostic 设计的最大红利——明天 Day 139 换的是 predicted 的来源(LLM→规则 assessCase),同一个 binaryEval 照样吃,正是同一红利的又一次兑现。
3. 今日实战
- 复用 provider-agnostic runner(默认 deepseek,可切 Qwen3 endpoint),对 day134 的
balanced_300跑 Qwen3(经 OpenRouter,传当周可用 model id)。 - 把 Qwen3 的判定映射成
{label, predicted},再过src/aml/groundTruthEval.ts的binaryEval,拿第二套 recall/precision/FPR(可叠binaryEvalWithCI加区间)。 - 新写 per-case 比对:对齐两套预测的同 caseId,逐条比
predictedDeepseek === predictedQwen3,算 agreement %。 - 汇成双模型对比表:两套 recall/FPR + 模型间 agreement %;命令侧仍走
pnpm eval:agent。 - 对两裁判分歧的个案(D≠Q 的那批)单独拉一张明细表——这是回看 rubric 的金矿:分歧集中在哪类样本(贴线结构化?复杂分层?),往往直指 rubric 哪条留了语义模糊。把分歧样本喂回 rubric 迭代,比盲调 prompt 高效得多。
- 若 agreement 偏低(如 <0.8),不要急着选裁判,先改 rubric 再复跑——agreement 是 rubric 质量的反馈信号,不是裁判优劣的裁决。
4. 今日实测 / 产出
- 产出物:双模型对比表(两套 recall/FPR + 模型间 agreement %)。
- 状态:runner 已支持 provider 切换(provider-agnostic,换 baseURL + model id 即切 Qwen3);评分函数
binaryEval/binaryEvalWithCI已 built+tested;per-case agreement 比对逻辑为本日待补(薄薄一层 caseId 配对)。 - 真实两套指标 + 一致率 = 待跑(需 key 跑)+待数据:需两次模型跑(DeepSeek + Qwen3)在 N=300 真子集上产生,per-case agreement 比对逻辑为本日新增,不预填数字。
- κ 仍 gated(诚实标注):本日只落地 raw per-case agreement %;chance-corrected 的 judge-human κ(≥50 hand labels)仍是 gated 的待办,不在本日产出内,不得描述成已完成。
- 可参照锚点:同 harness 已落地的真实数字 V4-Flash completion 79.3% / V4-Pro 89.7%(judge=pass)是 agent 任务 completion、非本日 AML 两裁判指标,仅作量级参照。
5. 常见误区 / 陷阱
- 把「两裁判一致」当成「判定正确」:两个 LLM 可能一起错(共同偏差)。真值仍是 AMLworld 标签,agreement 高只说明信号稳,不说明对。
- 只看指标 delta 不看 per-case agreement:两裁判 recall 可能近似相等却在大量个案上互相矛盾(各漏各的抵消了)。必须两个层面都报。
- 换裁判时顺手改了 rubric/prompt:那就不是交叉验证而是换了两套实验,agreement 失去意义。换裁判只换 model id,rubric/prompt 锁死。
- 用已停服或单一闭源裁判下定论:跨家族第二意见才有去偏价值。Qwen3 当周具体版本/endpoint 需执行当周复核(见 SOTA 段)。
- 把 raw agreement 当 κ:raw agreement 没扣偶然一致,平衡集上约 50% 是白送的。要严谨度量「超出偶然多少」得用 Cohen's κ;本仓 κ 仍 gated,别把 raw agreement 数字描述成 κ。
- 两裁判用不同子集:交叉验证必须是同一 balanced_300、同 seed 抽样,否则比的是不同样本上的指标,agreement 无意义。
- 用同家族模型互验:V4-Flash vs V4-Pro 共享血统、偏差相关,互验不出系统性偏置。必须跨家族(DeepSeek vs Qwen3)才有去偏效力。
- 顺序对齐两套预测:靠输出顺序对齐会因任一裁判跳过/失败某条而错位。必须按 caseId 构 Map 配对,与 B12
abCompare按 id 配对同理。
6. 学习资源(每条带 YYYY-MM)
- Anthropic — Demystifying evals(2026-01):多裁判一致性、judge 去偏、rubric 模糊导致的标注不稳。
- Qwen3 技术报告 / 模型卡(2025 发布,执行当周复查可用 model id 与 endpoint):跨家族开源旗舰,交叉验证的第二裁判。
- OpenRouter 官方文档(2026 持续更新):provider-agnostic 路由、统一 OpenAI 兼容端点。
- Cohen, J. — A Coefficient of Agreement for Nominal Scales(Educational and Psychological Measurement, 1960;κ 的原始定义,作 chance-corrected 一致性打底)。
- Landis & Koch — The Measurement of Observer Agreement for Categorical Data(Biometrics, 1977;κ 的判读梯度 substantial/almost-perfect 阈值来源)。
- Zheng et al. — Judging LLM-as-a-Judge(MT-Bench/Chatbot Arena, 2023-06;LLM 裁判偏差与多裁判一致性的奠基性实证,作经典打底,最新进展见 2026 文献)。
- 本仓代码:
src/aml/groundTruthEval.ts(binaryEval,prediction-source-agnostic,已 built+tested)。 - 本仓既有真实锚点(MEMORY,2026-06):
judge-human κ(≥50 hand labels)仍 gated——κ 是已知的下一步,不是已落地数字。
SOTA检查 (2026-06 更新)
- 现役主线:Qwen3(2025 发布)仍为活跃开源旗舰;跨家族交叉验证是 2026 judge 去偏主流;prediction-source-agnostic 的评分解耦是工程支点。
- κ 是更严谨的进阶:raw agreement 是现役底线,但 chance-corrected 的 Cohen's κ / Fleiss κ(多裁判)是更严谨的一致性度量;本仓 judge-human κ 仍 gated,列为下一步而非过时。
- panel-of-judges 趋势:2026 越来越多 eval 用「裁判面板」(≥3 个跨家族模型投票 + 多数决/置信)替代单裁判,进一步降方差。两裁判交叉是其最小形态,可作扩展方向。
- 避免/禁用:避免用已停服或单一闭源裁判下定论;避免把双裁判一致误当判定正确;避免只报聚合 delta 不报 per-case agreement;避免把 raw agreement 当 κ。
- 下次复查点:执行当周用 WebSearch 复核 Qwen3 当周具体版本/endpoint(agent/模型领域半衰期 ~6 个月);确认 OpenRouter 上 Qwen3 路由名是否变动;复查是否有更适合 AML 裁判的新跨家族开源模型;评估是否把两裁判扩展为 ≥3 裁判面板(panel-of-judges)进一步降方差。
衔接
- 昨天:Day 137 — bootstrap 置信区间(三指标 percentile 95% CI,控方差;
binaryEvalWithCI已 built+tested)。 - 今天:用 Qwen3 交叉验证同一 balanced_300,比两套指标 delta + per-case agreement %,控偏差(runner 已支持切换,真实数字待跑/待数据)。
- 明天:Day 139 — 替换循环 baseline(把
evalBaseline.ts的自造金标换成 AMLworld 真标签,规则assessCase在外部集上重测,暴露虚高 recall 的真实掉分)。 - 一句话记忆点:CI 控方差,交叉验证控偏差;两者都不能证明「对」,只能逼近真值——真值永远是 AMLworld 标签。