返回 AICAP-180
B14 · Day 131外部 ground-truth AML eval

循环自评为何无效

B13(Day 121-130)我们用合成金标 + 规则/LLM 双裁判,把类型学 recall、Cohen's κ、混淆矩阵这一整套度量工具铸好了;但 Day 130 收口时已埋下一颗雷:那套规则基线的高召回,是自己给自己打分打出来的。

阶段: B14 · 外部 ground-truth AML eval(Day 131-140) 标签: #circular-eval #external-validity #aml-baseline #reward-hacking

今日导引(由浅入深)

B13(Day 121-130)我们用合成金标 + 规则/LLM 双裁判,把类型学 recall、Cohen's κ、混淆矩阵这一整套度量工具铸好了;但 Day 130 收口时已埋下一颗雷:那套规则基线的高召回,是自己给自己打分打出来的

B14 这十天的整条主线就是「把循环自评杀掉、换成外部 ground-truth」。今天是 B14 的第一天,做的是诊断而非治疗——把循环自评(circular self-eval)这个反模式讲透、用真实代码量化它的虚高,并给这张表盖上「作弊基线、不可外推」的钢印。

放到 B1→B18 整条能力曲线上看:B1-B12 在打造 agent / eval 的工程地基,B13 把 AML 类型学度量工具补齐,B14 是第一次把「外部效度」这条硬约束真正落到 AML 评测上——它决定了这套作品集的数字到底能不能对外当效果。今天的最小可判定产出:一份 docs/aipa/day131-circular-baseline.md,含 3 类 typology recall + normalFPR 的真实数字,且每个数字旁边都标着「自评」。

1. 机理精读

什么是循环自评。 循环自评指同一套规则既当预测器(predictor)又被它自己生成的金标(gold label)审判。在我们的仓库里,这条循环非常具体:

  • src/aml/generator.tsgetGoldenDataset() 由作者写的合成器,按类型学定义造案件并打上 label
  • src/aml/evalBaseline.tsevalRuleBaseline 又用 assessCase(同一套类型学规则)去预测同一批案件的类别。

生成器埋的「结构化拆分」特征,正是判别器要找的特征——召回率高是定义上的同义反复,不是能力的证据。

为什么这必然虚高。 外部效度(external validity)的核心问题是:在这批数据上测出的数字,能不能外推到没见过的真实分布?循环自评的答案是「不能」,因为预测器和标签共享同一组生成规则——它们之间的互信息被人为拉满了。

换句话说,评测集没有提供任何预测器在设计时未曾编码的信息。这等价于「让出题人去考自己出的题」:满分不代表懂,只代表出题和答题是同一个人。任何在这种条件下产生的 recall,本质上度量的是「生成器和判别器是否用了同一套类型学定义」,而我们已经知道答案是「用了」——所以高分是预设的,不是发现的。

为什么 2026 把这件事看得很重。 Anthropic《Demystifying evals》(2026-01) 明确要求:eval 的标签必须来自独立于被测系统的外部来源。这条要求在 LLM 时代格外尖锐,因为:

  • LLM-as-judge 的自评(让模型给自己的输出打分)在 2026 已被普遍归类为 reward-hacking 风险源——一旦优化信号来自系统自身,系统会学会「讨好裁判」而非「解决问题」;
  • 规则系统版的循环自评是同一个病的非神经网络版本:没有梯度、没有训练,但同样没有外部效度。问题不在「是不是神经网络」,而在「标签来源是否独立于预测来源」。

关键权衡:循环基线还有没有用? 有,但只能当对照(control),不能当效果(result)。它的合法用途有二:

  1. 烟雾测试(smoke test)——确认评测管线、混淆矩阵、recall 计算本身无 bug。如果连自己生成的数据都召不全,那一定是规则引擎或度量代码有 bug。
  2. 上界参考(upper bound)——一个连自己生成的数据都召回不全的规则引擎,在外部数据上只会更差。所以循环基线给出的是「乐观上界」。

因此我们保留它,但给它盖钢印:标「作弊基线」,永不对外当能力数字。真正的外部 ground-truth(AMLworld / Elliptic 的 recall/precision/FPR)从 Day 132 起逐步落地,数据下载 gated。

与相邻概念的边界。 三组概念必须分清:

  • 循环自评 ≠ 过拟合:过拟合是「在训练集上拟合了噪声」,至少训练集和测试集是两批数据;循环自评更严重,是「训练集 = 测试集 = 同一生成规则」,连「两批数据」都不成立。
  • 循环自评 ≠ data leakage(数据泄漏):泄漏是测试信息意外混进训练,是个意外;循环自评是架构上就把两者焊死了,是个设计选择。
  • 循环自评 ≠ 单纯的合成数据问题:合成数据本身不必然无效(见 Day 132 的 AMLworld),无效的是「合成器和预测器同源」。

2. 推导 / 手算 / 代码走读

evalRuleBaseline 是纯函数、已 tested,逐条走读 src/aml/evalBaseline.ts

  1. 签名与返回evalRuleBaseline(ds: AmlDataset): BaselineEval,返回 { perTypology, normalFalsePositiveRate, confusion }perTypologyRecord<TypologyId, {recall, n}>,三类是 'structuring' | 'layering' | 'mule_network'(见 ALL_TYPOLOGIES,第 17 行)。
  2. 预测来源:第 27 行 const predicted = assessCase(c).topTypology ?? 'normal'——预测器就是 src/aml/typology.tsassessCasetopTypology 为 null(最高分低于 threshold)时回落到 'normal'。这正是循环的「判别器」一端。
  3. 混淆矩阵 key:第 28 行 const key = \${c.label}->${predicted}`,以 label->predicted 为键累加(第 29 行)。c.label` 来自合成器,是循环的「金标」一端——金标和预测都在同一个 for 循环里同源产生。
  4. recall 计算:阳性类(非 normal)累加 total[c.label]++,预测对则 correct[c.label]++(第 35-37 行);最终 recall = total===0 ? 0 : correct/total(第 42 行)。注意 recall 分母用真实正例数,所以这是 per-class recall 的标准定义——算法本身没错,错的是数据和预测器同源。
  5. normalFPR:第 31-33 行,normal 案件若被预测成任一 typology 即计 fp,normalFalsePositiveRate = normalFp/normalN(第 47 行)。
  6. 确定性:纯函数 + getGoldenDataset() 模块级 memoize(aml.test.ts 第 17-18 行断言同一引用),所以这张表是确定性可复现的——这恰恰是它最大的反讽:可复现的虚高,仍然是虚高。

测试侧已固化的结构事实src/aml/__tests__/aml.test.ts 第 70-95 行,aml rule baseline — eval 门槛):

typologyn(真实正例数)recall 门槛(断言下界)
structuring18≥ 0.85
layering15≥ 0.80
mule_network15≥ 0.80
normal(FPR)≤ 0.15

并断言混淆矩阵计数总和 === 66(18 + 15 + 15 + 18 normal = 66)。

关键提醒:上表是测试断言的下界/计数,不是某次外部测量。读真实点值(如 structuring 实际 recall 是 0.89 还是 1.00)要执行下面的命令,把 evalRuleBaseline(getGoldenDataset()) 的返回值打出来。无论点值是多少,它们都属于「作弊基线」,不得对外报告为能力。

循环 vs 外部的对照框架(这张表后面 Day 136-140 会被真实外部数字打脸,今天先立标):

维度循环自评(今天,Day 131)外部 ground-truth(Day 136-140 目标)
标签来源自家合成器 getGoldenDataset()IBM AMLworld Is_Laundering(外部)
预测来源自家规则 assessCase(同源)独立 LLM judge(deepseek-v4-flash
外部效度无(同义反复)有(标签/预测解耦)
数字可对外否(标「作弊基线」)是(带 bootstrap CI)
当前状态已 tested、确定性可复现待数据 + 待跑(gated)

这张对照表是 B14 全程的「北极星」:每写一个外部数字,都要回头确认它在右列、不在左列。Day 131 的价值就是把左列钉死、永不混入右列。

3. 今日实战

把规则基线当「作弊基线」对照跑出来:

  1. 在仓库根执行 pnpm vitest run src/aml/__tests__/aml.test.ts,确认 aml rule baseline — eval 门槛 这一 describe 全绿(证明管线无 bug、混淆矩阵计数 = 66)。
  2. 写一段一次性脚本或在 REPL 调用 evalRuleBaseline(getGoldenDataset()),读出 perTypology.structuring.recallperTypology.layering.recallperTypology.mule_network.recall 三个真实点值,以及 normalFalsePositiveRate
  3. 整理成一张「虚高基线表」,列为:typology / n / recall / 备注,备注一律写「自评、不可外推」。
  4. 落盘 docs/aipa/day131-circular-baseline.md,开篇第一句必须是「以下数字为循环自评的作弊基线,不得对外当效果,仅用于验证评测管线与作为 B14 外部 eval 的对照下界」。
  5. 在文末写一句承接:「真实外部 recall/precision/FPR 见 Day 136-140,数据下载 gated」。

4. 今日实测 / 产出

  • 产出docs/aipa/day131-circular-baseline.md + 一张当前虚高指标基线表(3 typology recall + normalFPR)。
  • 数据来源:数字直接读 evalRuleBaseline(getGoldenDataset()) 的真实返回值(pure 函数、确定性、已 tested)。
  • 测试已知事实(来自断言):structuring n=18、layering n=15、mule_network n=15、normalFPR ≤ 0.15、混淆矩阵计数总和 = 66;repo 现 423 tests green
  • 诚实状态标签:关键结论是这些数字标「作弊基线」,不得对外当效果。本日为诊断 + 对照表,不引入任何新外部测量,也不升级任何状态。

5. 常见误区 / 陷阱

  • 把循环基线的高 recall 写进简历/作品集当效果——这是 B14 全程要消灭的头号反模式,盖钢印就是为了防它。
  • 误以为「确定性 + tested」= 有效:可复现只保证算得对,不保证测得有意义;循环自评是「正确地度量了一个无意义的量」。
  • 把规则基线直接删掉:删了就失去管线烟雾测试与外部 eval 的对照下界,正确做法是保留 + 降级标注。
  • 混淆 recall 公式与数据同源问题:recall 公式 TP/(TP+FN) 本身是对的,问题在 TP/FN 都来自同源数据——别去「修公式」,要换数据源。

6. 学习资源(每条带 YYYY-MM)

  • Anthropic《Demystifying evals》(2026-01)——外部金标、独立标签来源的方法论主线,本批次反复引用。
  • IBM AMLworld dataset card, Kaggle (2024-04)——Day 132 起接入的外部带标数据集(预读)。
  • Campbell & Stanley《Experimental and Quasi-Experimental Designs for Research》(1963)——external validity 概念的经典论述(仅作概念打底,不作主线)。
  • 本仓代码:src/aml/evalBaseline.tssrc/aml/typology.tssrc/aml/generator.tssrc/aml/__tests__/aml.test.ts(循环结构的真实落点)。

SOTA检查 (2026-06 更新)

  • 当前主流:《Demystifying evals》(2026-01) 仍是当前 eval 方法论主线,「标签须来自独立外部来源」的要求未变。
  • 是否仍 SOTA:是。外部 ground-truth 要求是 2026 eval-rigor 共识的硬约束,没有更新替代品取代它。
  • 过时黑名单:避免引用任何「模型自评即可」「LLM 给自己打分就能上线」的旧叙事;LLM-as-judge 自评在 2026 已被普遍视为 reward-hacking 风险源。规则系统的循环自评同理失效。
  • 下次复查点:Day 140 B14 收口时,对照外部 AMLworld 真实 recall/precision/FPR 复核——若外部数字显著低于此循环基线,正好印证「虚高」结论;若意外接近,需排查是否仍有隐性数据泄漏。

衔接

  • 昨天:Day 130 — Block 收口:grader 报告与工具固化(把双裁判结论、κ、recall delta 汇成可链接资产,但其规则基线仍是自评)。
  • 今天:循环自评无外部效度——规则自己给自己打分的高 recall 是同义反复,盖「作弊基线」钢印作对照下界。
  • 明天:Day 132 — AML 公开标注集选型(用 IBM AMLworld 的真标签把外部标签接进来,从根上杀死循环 baseline)。