上一章 长任务与失败恢复 跑着跑着模型不吐字了、上下文满了、进程被关了——这些才是 Harness 工程师每天面对的东西,也是"工程问题"与"研究问题"的分水岭。 II · Harness 工程 · 第 08 章 · 进阶 · 约 36 分钟
Agent 工程学习站 做棵大树 出品 主站 beatree.cn 免费 · 无需登录 · 进度存本机
III 版 · 评测工程 ◆ 第 01 章 ◆ How Do You Know It Got Better
III · 评测工程 01 / 22 入门

评测的第一性问题

How Do You Know It Got Better
预计阅读 24 分钟
难度 入门
关键词 评测设计 · 基线
本机状态 未读

「感觉这次好多了」不是工程结论。评测要回答三个问题:好在哪个维度、好了多少、这个差异是真的还是噪声。这三个问题分别对应维度定义、量化口径、显著性判断——缺任何一个,迭代方向就是凭直觉。

编辑部注 · 本章建立评测的判断框架。后面四章都是它的展开:评测集(怎么取样)、指标(怎么量化)、评审(怎么让机器打分可信)、闭环(怎么让评测真正影响决策)。

先承认一件不太体面的事实:大多数 Agent 团队的第一次迭代都是「改提示词 → 手动试几条 → 感觉好了 → 上线」。这条路偶尔能走通,但它不可持续——因为你不知道这次变好是不是运气好,也不知道下一条改动会不会把之前修好的问题重新弄坏。

一、评测的三个第一性问题

问题要回答什么典型错误正确做法
哪个维度「好」具体指什么?拆成可独立判断的几个维度用「效果」这个模糊词,导致改进无法归因拆成可分别评估的维度(如方向相关性 / 证据充分性 / 可执行性)
好了多少用什么数字衡量?分母是什么?口径不清,同一个指标两个人算出两个数指标定义要写到「能被别人复现」的程度
是真的吗这个差异超出噪声了吗?拿 5 条样本的差异当结论扩大样本、看置信区间、做 A/B 对照

这三个问题看起来朴素,但它们对应了三种最常见的评测失败:维度混在一起导致改对了也不知道、口径(Metric Definition)不清导致数字无法比较、样本太小导致追噪声,而「差异是不是真的」要靠显著性(Significance)判断。

二、维度怎么拆:正交是唯一标准

拆维度的唯一要求是正交——两个维度不能相互包含,否则你无法判断是哪一项在变化。正交维度(Orthogonal Dimension)就是「互不包舍、可分别判断」的维度:能构造出「A 维度满分而 B 维度零分」的样本,两维才真正正交可用。

从「效果好」到可评估维度 不要这样拆 效果好 准确 有用 「准确」与「有用」互相包含: 不准确的东西谈不上有用 → 不可归因 办事型:四个正交维度 ① 可执行率(能不能跑) ② 参数准确率(填对没) ③ 任务完成率(做完没) ④ 交互轮数 / 成本 可分别独立判断,改动可归因 洞察型:四个正交维度 ① 方向相关性 ② 证据充分性 ③ 可操作性 ④ 表达清晰度 「有洞察」不是维度,是四项的合成 正交性检验(三句话就能测出来) ① 能不能构造一个样本,A 维度满分而 B 维度零分?不能 → 两者高度相关,需要合并。 ② 改动 X 只影响 A 不影响 B 吗?如果我改任何一处都同时动两个维度,拆分就没意义。 第三个问题:差异是真的还是噪声 样本量:30 条以内的差异不要下结论。8/20 与 9/20 的差别(45% vs 40%)在统计上等同于「没区别」。 对照组:改动前后必须用同一套评测集、同一版本模型、同一温度设置,否则差异无法归因。 多次运行:Agent 有随机性。同一配置跑 3 次取均值与方差,方差大的指标要谨慎解读。 区分「回归」与「波动」:跌幅小于历史波动区间的,不要当成回归去修。
图 1 维度拆解的正反例与正交性检验。核心判据:能否构造出一个「A 好 B 差」的样本——能构造,说明两维正交可用;构造不出,说明它们其实是一件事。
多轮得分的均值与波动带 方差界定噪声:跌幅小于历史波动区间,不应判为回归 0 50 100 A 均值 72 B 均值 75 差距 3 分 差距 3 分远小于各自 ±8~9 分的波动带 → 视为噪声,不下结论;多次运行方向一致且超出波动带才算回归。
图 2 Agent 有随机性,同一配置多次运行得分是一条带。两版本均值差 3 分,但各自的波动带就有 ±8~9 分——差距落在波动带内,不能判为回归。这也是为什么必须跑多次取方差。
整体提升 ≠ 真的变好 防刷分:整体指标上升,可能掩盖某个分层指标的退化 整体完成率 78% → 82% +4 看起来赢了 单一数字,看不出结构。 容易被「平均」误导。 → 对外汇报常用口径 分层「对抗集」 90% → 81% −9 悄悄退化 安全类退步最危险。 被整体 4 分掩盖了。 → 必须单列、必须告警 判据:任何分层指标回落超过 5 个百分点,必须显式告警 只看整体指标,等于放弃了对「局部退化」的感知。防刷分要求分层指标与整体指标一起看——否则刷分行为会系统性地抬高总分。 尤其警惕对抗集、边界集这类「不常发生但一发生就很严重」的分层。
图 3 整体完成率 +4 看似进步,但分层「对抗集」−9 才是真问题。平均会掩盖结构——防刷分的核心就是不让总分盖住局部退化。

三、指标口径:必须写到能被复现

这是最容易出问题的地方。以「可执行率」为例,下面三种口径会给出三个完全不同的数字——同一个系统,分母(Denominator)的定义不同,算出的数能差 20 个百分点:

口径定义问题
A · 宽松模型输出的 DSL 能被解析器解析成功解析成功 ≠ 能执行。语法对但字段名错的情况被算作成功
B · 适中解析成功且查询引擎接受(不报错)引擎不报错 ≠ 结果正确。查了错的条件也算通过
C · 严格解析成功、引擎接受、且返回结果与人工标注的期望结果一致标准最严,人工标注成本最高

三种口径都不是错的,但混用是错的。 关键是:口径一旦定了,要写进评测代码的注释里、要能被别人复现(Reproducibility),并且在对比两个版本时保持同一口径。

口径定义的三条硬要求
  • 写分母:分母是「全部样本」还是「成功进入该环节的样本」?两者差异巨大(后者会系统性高估)。
  • 写边界:超时算不算失败?用户主动中断算不算?空结果算成功还是失败?
  • 写例子:至少给一个「算通过」和一个「不算通过」的具体样本。

满足这三条的口径,任何同事接手都能算出同一个数。不满足的口径,等于没有口径。

四、动手:一个可复现的评测骨架

eval_framework.pypython
from dataclasses import dataclass, field
from typing import Callable, Any
import statistics, json
@dataclass
class Sample:
    id: str
    input: str
    expected: Any = None        # 有标准答案的样本才有
    tags: list[str] = field(default_factory=list)   # 分层标签:冒烟/回归/边界/对抗
@dataclass
class Metric:
    """
    指标必须自带口径说明。没有口径的指标不可能被复现,
    因此在数据结构层面就强制要求写清楚。
    """
    name: str
    numerator_desc: str         # 分子是什么
    denominator_desc: str       # 分母是什么
    boundary: str               # 边界情况怎么算(超时/中断/空结果)
    fn: Callable[[dict], bool]
    def describe(self) -> str:
        return (f"{self.name}\n"
                f"  分子:{self.numerator_desc}\n"
                f"  分母:{self.denominator_desc}\n"
                f"  边界:{self.boundary}")
@dataclass
class EvalReport:
    metrics: dict[str, float]
    n: int
    failures: list[dict]        # 必须保留失败样本,否则无法归因
    by_tag: dict[str, float]
def run_eval(samples: list[Sample], run_once: Callable[[Sample], dict],
             metrics: list[Metric], repeats: int = 1) -> EvalReport:
    """
    repeats > 1 用于估计方差 —— Agent 有随机性,
    只跑一遍得到的差异无法与噪声区分。
    """
    per_metric: dict[str, list[float]] = {m.name: [] for m in metrics}
    failures: list[dict] = []
    tag_scores: dict[str, list[float]] = {}
    for run_i in range(repeats):
        for s in samples:
            try:
                out = run_once(s)
            except Exception as e:
                # 异常也算一次「未通过」,不能让异常样本静默消失,
                # 否则分母被人为缩小,指标会虚高。
                out = {"error": f"{type(e).__name__}: {e}"}
            for m in metrics:
                per_metric[m.name].append(1.0 if m.fn(out) else 0.0)
            # 记录失败样本:这是最有价值的产出,而不是那个百分比
            main = metrics[0]
            if not main.fn(out):
                failures.append({"sample": s.id, "tags": s.tags, "output": out,
                                 "run": run_i})
                for t in s.tags:
                    tag_scores.setdefault(t, []).append(0.0)
            else:
                for t in s.tags:
                    tag_scores.setdefault(t, []).append(1.0)
    report = EvalReport(
        metrics={m.name: statistics.fmean(v) for m, v in
                 ((m, per_metric[m.name]) for m in metrics)},
        n=len(samples) * repeats,
        failures=failures,
        by_tag={t: statistics.fmean(v) for t, v in tag_scores.items()},
    )
    # 顺带输出方差:方差大的指标在决策时要更保守
    for m in metrics:
        v = per_metric[m.name]
        if len(v) > 1:
            report.metrics[f"{m.name}__stdev"] = statistics.pstdev(v)
    return report
# --- 指标定义示例(注意每一条都把口径写全了) ---
m_parse_ok = Metric(
    name="解析成功率",
    numerator_desc="输出能被 JSON 解析器成功解析的样本数",
    denominator_desc="全部参评样本数(含超时、异常、中断)",
    boundary="超时与异常一律计入分母且计为不通过;空输出计为不通过",
    fn=lambda out: "parsed" in out and out["parsed"] is not None,
)
m_tool_ok = Metric(
    name="工具调用成功率",
    numerator_desc="工具调用返回状态为 ok 或 empty 的样本数(empty 视为成功)",
    denominator_desc="全部参评样本数(含超时、异常、中断)",
    boundary="超时/异常计为不通过;empty 计为通过(查询成功但无数据)",
    fn=lambda out: out.get("tool_status") in ("ok", "empty"),
)
def compare(baseline: EvalReport, candidate: EvalReport) -> str:
    """
    对比报告。原则:
      · 差异小于历史波动(stdev)的不下结论
      · 主指标提升但分层指标恶化,必须显式提示(防刷分)
    """
    lines = [f"样本数:baseline {baseline.n} → candidate {candidate.n}"]
    for k, v_new in candidate.metrics.items():
        if k.endswith("__stdev"):
            continue
        v_old = baseline.metrics.get(k)
        if v_old is None:
            continue
        delta = v_new - v_old
        noise = max(candidate.metrics.get(f"{k}__stdev", 0),
                    baseline.metrics.get(f"{k}__stdev", 0))
        verdict = "差异不显著" if abs(delta) <= noise else ("提升" if delta > 0 else "回归")
        lines.append(f"{k}: {v_old:.1%} → {v_new:.1%}(Δ{delta:+.1%}){verdict}")
    # 防刷分:整体提升但某个分层恶化
    for tag, v_new in candidate.by_tag.items():
        v_old = baseline.by_tag.get(tag)
        if v_old is not None and v_new < v_old - 0.05:
            lines.append(f"⚠ 分层「{tag}」出现回落:{v_old:.1%} → {v_new:.1%},"
                         f"整体指标可能掩盖了局部退化,请检查")
    return "\n".join(lines)

4.1 「差 3 个点」到底算不算提升

上面的 compare() 用了一个极简判据——「差值是否超过 stdev」——它适合随手扫一眼,但不够严谨。真正的面试必答题是:两个版本在同一个样本集上差 3 个百分点,这 3 个点到底是真提升,还是随机波动? 这需要显式的显著性检验。

先说清为什么「3 个点」不可直接比较。Agent 评测有两个随机源:一是模型采样本身的随机性,二是评测集只是「全量线上流量」的一个抽样。两者都意味着:换一批样本、或重跑一遍,那个 3 个点可能就没了。 显著性检验要回答的是「如果两个版本其实没有差别,观察到这么大(或更大)差异的概率有多低」。

对「同一批样本、两个版本各跑一遍」的配对场景,最贴切的工具是 McNemar 检验:它只看那些「两个版本结论不一致」的样本——A 对 B 错、或 A 错 B 对——而把「都对」「都错」的样本丢掉。逻辑是:如果两个版本真的没有差别,那么「A 对 B 错」与「A 错 B 对」的样本数应该差不多,差异只是抛硬币。

mcnemar_test.pypython
from math import comb
def mcnemar(a_only: int, b_only: int) -> float:
    """
    配对 McNemar 检验(双尾),返回 p 值。
    a_only: 版本 A 判对、版本 B 判错的样本数
    b_only: 版本 A 判错、版本 B 判对的样本数
    两者是「结论不一致」的样本;「都对」「都错」的样本不参与。
    """
    n = a_only + b_only
    if n == 0:
        return 1.0          # 没有任何不一致样本,无法判断孰优孰劣
    # 原假设:A、B 没有差别 → 每个不一致样本落入 a_only 或 b_only 的概率各 1/2
    # 双尾 p = 2 × 单尾;单尾 = P(X ≥ max(a_only, b_only)),X ~ Binomial(n, 1/2)
    m = max(a_only, b_only)
    tail = sum(comb(n, k) * (0.5 ** n) for k in range(m, n + 1))
    return min(1.0, 2 * tail)
def compare_versions(baseline_ok, candidate_ok):
    """
    baseline_ok / candidate_ok:两个版本在每个样本上的 0/1 结果,顺序对齐。
    """
    a_only = sum(1 for b, c in zip(baseline_ok, candidate_ok) if b and not c)
    b_only = sum(1 for b, c in zip(baseline_ok, candidate_ok) if not b and c)
    p = mcnemar(a_only, b_only)
    verdict = "差异不显著(不能下「提升」的结论)" if p >= 0.05 else "差异显著"
    return a_only, b_only, p, verdict

三个要点,面试时能把它们讲清,基本可以确认你真的做过、而不是背过:

  • 配对 vs 独立:两个版本跑在同一批样本上才是配对,用 McNemar;两批不同的样本(比如线上流量分桶)是独立的,要用两样本比例检验。选错检验比不检验更糟,因为结论是建立在错误假设上的。
  • p 值不是「效果大小」。p < 0.05 只能说明「差异不太可能是噪声」,不说明「差异够大、值得上线」。3 个点的显著提升,配上「上线要改的工程量 / 回归风险」,可能仍不值当;反过来 0.5 个点若稳定且零成本,也可能值得。
  • 多次比较会骗人。同时看 10 个分层指标,纯随机也会有一个「p < 0.05」。所以分层指标要预先声明(预注册),事后到处找显著的分层属于「数据抓鱼」(p-hacking),得到的显著性不可信。
线上怎么落地

日常不必每次都手算 p 值——大多数时候看不一致样本数就够:如果「A 对 B 错」与「A 错 B 对」的数量级接近(比如 12 vs 9),那个 3 个点的差异大概率是噪声。真正要下「版本 A 明显更好」的结论时,再上 McNemar / bootstrap 给出 p 值,写进评测报告里。

一句话判据:没有显著性检验的对比,等于没有对比。

实操任务
  • 给你手上的一个 Agent 定义三个正交维度,并各写一句「口径说明」(分子 / 分母 / 边界);
  • 构造一个「总体指标上升但某个分层指标下降」的例子,验证 compare() 能发出警告;
  • 把 repeats 从 1 改成 3,观察各指标的方差——哪个指标最不稳定?为什么?

五、常见误区与追问

5.1 误区:维度越多越全面(其实越容易不正交)

很多人以为把「准确性、鲁棒性、安全性、易用性」都列上就是严谨。错。维度必须正交——能构造「A 好 B 差」的样本才算两个独立维度。列一堆高度相关的维度,最终只是把同一个信号重复计了好几遍,出了问题还是归因不了。判据:每加一个维度前先问「我能构造一个该维度满分、另一个零分的样本吗」,构造不出就合并。

5.2 误区:显著差异就等于真的变好(其实可能是噪声)

看到两个版本差 5 个百分点就急着下结论,是评测里最常见的错误。Agent 有随机性,同一配置跑 3 次得分本身就能波动 ±8 分。方差(Variance)大于差异时,那个差异在数学上等同于「没区别」。判据:样本量 ≥ 30、同一配置跑 ≥ 3 次取均值与方差,差异落在波动带内(或置信区间重叠)就当噪声处理,不要去「修」它。

5.3 误区:口径差不多就行(其实能差 20 个百分点)

「可执行率 89%」和「67%」可能描述的是同一个系统——差别只在分母用的是「成功产出的样本」还是「全部样本」。口径不清会让两个团队为「谁更强」吵半天,其实只是分母不同。判据:拿到任何指标先问三件事——分子是什么、分母是什么、边界怎么算;报数时必须连带口径一起报。

5.4 误区:整体指标提升就赢了(其实是刷分)

整体完成率从 78% 涨到 82%,但分层「对抗集」从 90% 跌到 81%,这种情况比整体下降更危险——它隐藏了安全能力的退化。防刷分(Anti-gaming)要求把分层指标(Stratified Metric)单列并设阈值告警。判据:任何分层指标回落 > 5 个百分点必须显式告警;对抗集、边界集这类「低频高危害」分层尤其不能因总分上升被容忍。

5.5 误区:回归就是「统计回归」(其实是变差)

评测里说的「回归」和机器学习课的「回归模型」毫无关系。这里指的是「指标相对基线变差了」,而波动只是随机抖动。回归与波动(Regression vs. Noise)的区分是:把一次正常的波动当成回归去修,反而会引入特判、加剧过拟合。判据:先算该指标的历史波动区间,跌幅落在区间内就标为噪声,只有稳定、方向一致的恶化才进回归清单。

5.6 误区:失败样本没用,只要那个百分比(其实它是唯一产出)

团队常把「通过率 85%」当评测结果,把失败样本当垃圾丢掉。错。百分比只回答「变没变好」,失败样本才回答「为什么没做好、该改哪」。失败样本(Failure Samples)是下一步改动的唯一依据,也是 badcase 回流的原料。判据:每次评测必须保留并归因失败样本列表;只报百分比的评测等于没做评测。

六、自测

本章自测第 2 题为高频考点
Q1评测要回答的三个第一性问题不包括下面哪一个?
C。三个第一性问题是:维度(哪个方向)、量化(多少)、显著性(真的吗)。代码好不好看属于工程规范,不属于评测要回答的问题——把这两类事混起来会导致评测报告里出现无法量化的主观判断。
Q2判断两个维度是否正交,最实用的检验方法是什么?
B。这是最实用的一条判据。例如「准确」与「有用」——你能构造出「准确但无用」的样本吗?很难,说明它们高度相关,应该合并或重新拆分。能构造出反例,才是真正正交的两个维度。
Q3为什么评测里必须保留「失败样本列表」而不只是那个百分比?
D。这是评测从「考核指标」变成「研发工具」的关键一步。只报百分比,团队会陷入「刷分」;保留失败样本并做归因,才能把评测结果转化为具体的改动清单。这也是下一章「badcase 回流」的起点。

七、小结

问题结论
哪个维度拆到正交为止;判据是能否构造出「A 好 B 差」的反例
好了多少口径三要素:分子、分母、边界;不写口径等于没有指标
真的吗样本量 ≥ 30、同集同配置、多次运行看方差
失败样本必须保留并归因,这是评测真正的产出
防刷分看分层指标,警惕整体提升掩盖局部退化

评测不是打分表,是研发工具。它的产出不是那个百分比,而是「下一步该改哪里」的清单。本刊编辑部

下一章讲评测集从哪来——答案可能会让你意外:它不是设计出来的,是长出来的。

八、参考与延伸

评测的坑大多不是数学,而是纪律。下面几份材料按「建立直觉 → 动手 → 对齐一手定义」排好。

先看图(建立直觉)

  • Hamel Hussain 的博客 —— 大量关于 LLM 评测方法论与防刷分的实战文章,尤其适合建立「指标为什么会骗人」的直觉。重点看他反复强调的「先定义什么是好,再谈怎么测」这一条。
  • Eugene Yan · Evaluations in LLM/LLMOps —— 从工程视角梳理评测与上线监控的关系。他关于「线上信号比离线分数更可信」的论述,正好对应本章的失败样本与用户行为信号。

再看代码(动手实现)

  • OpenAI Evals —— 官方评测框架,直接看 grading 函数怎么写、rubric 怎么表达。对比本章第四节的骨架,能立刻看出「生产级评测」多做了哪些事(版本化、回归、可复现)。

最后读论文(对齐一手定义)

  • HELM · 斯坦福 CRFM 全息评测 —— 把评测维度、场景、指标做成一套公开口径的基准。它的价值不在分数高低,而在于「口径公开、可复现」这件事本身,这正是本章反复强调的。
  • SWE-bench —— 可执行指标的一手标杆:以「能不能跑通测试」定义完成度。想理解「端到端完成率」为什么比人工评审可信,看它怎么构造可判定的任务就够了。

◇ 面试官会怎么问

共 6 条 · 其中 2 条高频 · 先自己答一遍,再展开对照

你怎么知道一版改动真的让 Agent 变好了? 高频
需要三样东西同时具备,缺一个结论就不成立:
① 固定的评测集——改动前后跑的是同一批题,否则数字不可比;
② 明确的基线——上一版的数据是什么,没有基线就没有"变好"这个概念;
③ 噪声估计——同一版本重复跑多次,看指标的波动区间。如果提升幅度落在波动区间内,那不能算改进。
实践上还要注意两点:看分布而不只看均值(平均分涨了但某些关键场景崩塌,这是净损失);区分"变好"和"变长"(轮数变多、token 变多往往能刷高完成率,但用户体验和成本都变差了,所以指标必须成组看)。

追问链

  1. 怎么估计噪声?
  2. 如果提升只有 2 个百分点,你上线吗?
为什么说"感觉这次好多了"不能作为工程结论?
因为人的主观判断有三个系统性偏差:
① 样本偏差——你试的往往是自己熟悉的几个 case,而线上失败集中在长尾;
② 确认偏差——你刚改完,倾向于把符合预期的表现看成改进,把不符合的看成偶然;
③ 无基线——没有同时跑旧版本,等于没有对照,无法排除"这次任务本来就简单"。
不是说主观判断没价值,它的正确用途是发现"哪里不对"(产生假设),而不是判断"是否变好"(验证假设)。前者靠人,后者靠评测。
离线评测和线上指标的关系是什么?
两者回答不同的问题,不能互相替代:
离线评测回答"在受控条件下,这一版的正确性有没有退化"——可复现、可归因、能拦住回归,但它的任务分布是过去的,未必代表未来。
线上指标回答"在真实流量下,用户是否真的受益"——分布真实,但噪声大、混杂因素多(用户群变化、流量结构变化),归因困难。
正确的用法是用离线守回归底线,用线上看真实收益:离线不通过不上线;离线通过后灰度上线,用线上数据验证;线上出现新的 badcase,回流进离线评测集。离线评测集就是由线上 badcase 长出来的,这样两者才形成一个闭环而不是两套体系。
线上完成率从 78% 掉到 75%,你第一件事做什么? 高频
先判断这是回归还是波动,而不是先改代码。
① 查历史波动:把同一版本连续跑多次的分数拿出来,看这个指标的波动带有多宽;如果它历史上本来就在 ±4 分之间抖动,3 个百分点落在带内,先记为噪声。
② 查口径有没有变:分子、分母、样本集、规范化规则的版本有没有动过——口径一改,数字立刻不可比,这类「假回归」比真回归更常见。
③ 查分层:整体掉 3 分,是均匀下降还是某一层崩了?如果对抗集掉了 15 个百分点,哪怕整体只掉 3 分也必须立刻查。
顺序很重要:先排除口径与噪声,再去动代码,否则你会在噪声上改出一个特判逻辑。

追问链

  1. 如果团队没有留存历史波动数据呢?
  2. 分层指标里,哪几层的跌幅你最不能容忍?
加分点:加分点:先问「这个数是怎么算出来的」再问「为什么掉了」——说明被口径坑过一次。
评测集只有 20 条,改动后通过数从 8 条变成 10 条(40% 到 50%)。这个改动能上吗?
不能。
n=20 时比例估计的 95% 置信区间宽度在 ±22 个百分点量级:40% 的区间大致是 20% 到 60%,50% 的区间大致是 30% 到 70%,两者大面积重叠。
要稳定分辨 5 到 10 个百分点的差异,样本量通常需要几百条量级;而且要看的是分层够不够,不是总数够不够。
正确动作有两个:① 先在保留池上验证提升是否复现;② 把这次改动涉及的场景抽 50 到 100 条补进评测集,再来判断。

追问链

  1. 要多大样本量才能分辨 5 个百分点?
  2. 如果保留池上的提升更大,你会怎么解释?
加分点:加分点:能说出「20 条样本分辨不了 10 个百分点」,并且知道要去看分层配比,而不是只补总数。
怎么用一句话检验你拆出来的两个评测维度是不是正交?
问一句:我能不能构造出一个样本,让 A 维度满分而 B 维度零分?
能构造出来,说明两维可以分别变化,是独立的;构造不出来,说明它们其实是同一件事,应该合并或重新拆。
举例:把「准确」和「有用」并列就不成立——不准确的答案很难有用,构造不出干净的反例,两者高度相关。而「方向相关性」和「可操作性」可以:一份方向完全正确、证据齐全,但通篇没有下一步动作的分析,就是真实存在的「方向满分、可操作零分」样本。
这条判据的工程价值在于:它把维度设计从文字游戏变成了可以做实验的事。

追问链

  1. 如果两个维度的相关系数是 0.9,你会怎么处理?
  2. 一票否决与加权求和,分别适合什么形状的维度关系?
加分点:加分点:当场构造出反例样本,而不是只会背「要正交」。
答这类题的通用结构

结论先行(一句话给出取舍)→ 机制(为什么是这样,涉及哪条链路)→ 代价或边界(这么做放弃了什么)→ 你的实践或数字(真实场景里怎么落地)。 只讲机制不讲代价,是背题;只讲取舍没有数字,是空谈。

本章收尾 · Wrap up
掌握度自评
点一下给自己打分;低于 3 分建议加入复习队列
个人笔记 · Notes
    下一章 评测集建设与防过拟合 评测集从哪来?答案是从线上长出来。这一章讲分层设计(冒烟 / 回归 / 边界 / 对抗)、保留集机制,以及怎么避免你的系统把评测集背下来。 III · 评测工程 · 第 02 章 · 进阶 · 约 30 分钟