循环自评为何无效
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.ts的getGoldenDataset()由作者写的合成器,按类型学定义造案件并打上label;src/aml/evalBaseline.ts的evalRuleBaseline又用assessCase(同一套类型学规则)去预测同一批案件的类别。
生成器埋的「结构化拆分」特征,正是判别器要找的特征——召回率高是定义上的同义反复,不是能力的证据。
为什么这必然虚高。 外部效度(external validity)的核心问题是:在这批数据上测出的数字,能不能外推到没见过的真实分布?循环自评的答案是「不能」,因为预测器和标签共享同一组生成规则——它们之间的互信息被人为拉满了。
换句话说,评测集没有提供任何预测器在设计时未曾编码的信息。这等价于「让出题人去考自己出的题」:满分不代表懂,只代表出题和答题是同一个人。任何在这种条件下产生的 recall,本质上度量的是「生成器和判别器是否用了同一套类型学定义」,而我们已经知道答案是「用了」——所以高分是预设的,不是发现的。
为什么 2026 把这件事看得很重。 Anthropic《Demystifying evals》(2026-01) 明确要求:eval 的标签必须来自独立于被测系统的外部来源。这条要求在 LLM 时代格外尖锐,因为:
- LLM-as-judge 的自评(让模型给自己的输出打分)在 2026 已被普遍归类为 reward-hacking 风险源——一旦优化信号来自系统自身,系统会学会「讨好裁判」而非「解决问题」;
- 规则系统版的循环自评是同一个病的非神经网络版本:没有梯度、没有训练,但同样没有外部效度。问题不在「是不是神经网络」,而在「标签来源是否独立于预测来源」。
关键权衡:循环基线还有没有用? 有,但只能当对照(control),不能当效果(result)。它的合法用途有二:
- 烟雾测试(smoke test)——确认评测管线、混淆矩阵、recall 计算本身无 bug。如果连自己生成的数据都召不全,那一定是规则引擎或度量代码有 bug。
- 上界参考(upper bound)——一个连自己生成的数据都召回不全的规则引擎,在外部数据上只会更差。所以循环基线给出的是「乐观上界」。
因此我们保留它,但给它盖钢印:标「作弊基线」,永不对外当能力数字。真正的外部 ground-truth(AMLworld / Elliptic 的 recall/precision/FPR)从 Day 132 起逐步落地,数据下载 gated。
与相邻概念的边界。 三组概念必须分清:
- 循环自评 ≠ 过拟合:过拟合是「在训练集上拟合了噪声」,至少训练集和测试集是两批数据;循环自评更严重,是「训练集 = 测试集 = 同一生成规则」,连「两批数据」都不成立。
- 循环自评 ≠ data leakage(数据泄漏):泄漏是测试信息意外混进训练,是个意外;循环自评是架构上就把两者焊死了,是个设计选择。
- 循环自评 ≠ 单纯的合成数据问题:合成数据本身不必然无效(见 Day 132 的 AMLworld),无效的是「合成器和预测器同源」。
2. 推导 / 手算 / 代码走读
evalRuleBaseline 是纯函数、已 tested,逐条走读 src/aml/evalBaseline.ts:
- 签名与返回:
evalRuleBaseline(ds: AmlDataset): BaselineEval,返回{ perTypology, normalFalsePositiveRate, confusion }。perTypology是Record<TypologyId, {recall, n}>,三类是'structuring' | 'layering' | 'mule_network'(见ALL_TYPOLOGIES,第 17 行)。 - 预测来源:第 27 行
const predicted = assessCase(c).topTypology ?? 'normal'——预测器就是src/aml/typology.ts的assessCase,topTypology为 null(最高分低于 threshold)时回落到'normal'。这正是循环的「判别器」一端。 - 混淆矩阵 key:第 28 行
const key = \${c.label}->${predicted}`,以label->predicted为键累加(第 29 行)。c.label` 来自合成器,是循环的「金标」一端——金标和预测都在同一个 for 循环里同源产生。 - recall 计算:阳性类(非 normal)累加
total[c.label]++,预测对则correct[c.label]++(第 35-37 行);最终recall = total===0 ? 0 : correct/total(第 42 行)。注意 recall 分母用真实正例数,所以这是 per-class recall 的标准定义——算法本身没错,错的是数据和预测器同源。 - normalFPR:第 31-33 行,normal 案件若被预测成任一 typology 即计 fp,
normalFalsePositiveRate = normalFp/normalN(第 47 行)。 - 确定性:纯函数 +
getGoldenDataset()模块级 memoize(aml.test.ts第 17-18 行断言同一引用),所以这张表是确定性可复现的——这恰恰是它最大的反讽:可复现的虚高,仍然是虚高。
测试侧已固化的结构事实(src/aml/__tests__/aml.test.ts 第 70-95 行,aml rule baseline — eval 门槛):
| typology | n(真实正例数) | recall 门槛(断言下界) |
|---|---|---|
| structuring | 18 | ≥ 0.85 |
| layering | 15 | ≥ 0.80 |
| mule_network | 15 | ≥ 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. 今日实战
把规则基线当「作弊基线」对照跑出来:
- 在仓库根执行
pnpm vitest run src/aml/__tests__/aml.test.ts,确认aml rule baseline — eval 门槛这一 describe 全绿(证明管线无 bug、混淆矩阵计数 = 66)。 - 写一段一次性脚本或在 REPL 调用
evalRuleBaseline(getGoldenDataset()),读出perTypology.structuring.recall、perTypology.layering.recall、perTypology.mule_network.recall三个真实点值,以及normalFalsePositiveRate。 - 整理成一张「虚高基线表」,列为:typology / n / recall / 备注,备注一律写「自评、不可外推」。
- 落盘
docs/aipa/day131-circular-baseline.md,开篇第一句必须是「以下数字为循环自评的作弊基线,不得对外当效果,仅用于验证评测管线与作为 B14 外部 eval 的对照下界」。 - 在文末写一句承接:「真实外部 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.ts、src/aml/typology.ts、src/aml/generator.ts、src/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)。