结果评估器


文档摘要

结果评估器 本节摘要:运行器产了数字。评估器决定这些数字是改进、回归、还是噪声。构建把指标转成一行结论的判定路径。单一数字不说变化是否真实——同配置不同种子给不同困惑度,变化可能是噪声。对比较是配对的:同种子同数据,候选与基线各跑一次,每种子贡献一差,差均值是效应,差标准误是噪声底。本节从零实现配对 t 检验(无 ,数学小到一屏读完),用方向感知改进(指标有「高更好」或「低更好」)+ 固定阈值(2%)判定。困惑度这类对数尺度指标先取对数再比,使下游报告可与线性指标混合。每步纯函数,同输入永远产同判定。 对应原课程:Phase 19 · Lesson 53 · (原英文 )。本节属「AI Scientist」赛道第四节。

结果评估器

本节摘要:运行器产了数字。评估器决定这些数字是改进、回归、还是噪声。构建把指标转成一行结论的判定路径。单一数字不说变化是否真实——同配置不同种子给不同困惑度,变化可能是噪声。对比较是配对的:同种子同数据,候选与基线各跑一次,每种子贡献一差,差均值是效应,差标准误是噪声底。本节从零实现配对 t 检验(无 scipy.stats,数学小到一屏读完),用方向感知改进(指标有「高更好」或「低更好」)+ 固定阈值(2%)判定。困惑度这类对数尺度指标先取对数再比,使下游报告可与线性指标混合。每步纯函数,同输入永远产同判定。

对应原课程:Phase 19 · Lesson 53 · result-evaluator(原英文 phases/19-capstone-projects/53-result-evaluator/docs/en.md)。本节属「AI Scientist」赛道第四节。

学习目标

阅读完本节,你应当能够:

  1. 用方向感知改进与固定阈值把候选运行与基线比。
  2. 从零跑每种子指标的配对 t 检验,读出 p 值。
  3. 归一化对数尺度指标,使下游报告可与线性指标混合。
  4. 发编排器可附到第 48 节队列的每假设判定。
  5. 每步纯函数,同输入永远产同判定。

一、问题与直觉

为什么配对检验

运行器的单一数字不说变化是否真实。同配置不同种子给不同困惑度,变化可能是噪声。对比较是配对的:同种子同数据,候选与基线各跑一次。每种子贡献一差,差均值是效应,差标准误是噪声底。本节从零实现检验,无 scipy.stats,数学小到一屏读完:

diffs = [a_i - b_i for i in seeds] mean = sum(diffs) / n variance = sum((d - mean) ** 2 for d in diffs) / (n - 1) t_stat = mean / sqrt(variance / n) df = n - 1 p_value = two_sided_p(t_stat, df)

双侧 p 值用正则化不完全贝塔函数,本节发用 Lentz 连分式的小实现,共 60 行 stdlib math。

方向感知改进

有些指标升更好(准确率、吞吐),有些降更好(损失、困惑度、墙时)。评估器每指标带 direction 字段:

if direction == "higher_is_better": improvement = (candidate - baseline) / abs(baseline) elif direction == "lower_is_better": improvement = (baseline - candidate) / abs(baseline)

改进有符号。高更好指标上负改进意味候选更差。判定路径同读符号与量级。平阈值(improvement_threshold=0.02,2%)决定变化是否够大可叫。低于此判定是「噪声」,不论 p 值——循环对用户测不出的变化不感兴趣。

对数归一化

困惑度是损失的指数。损失降 0.1 对应困惑度大得多的降。直接跨两配置比困惑度行,但在单一报告里与线性指标混合需归一化。本节对 scale 字段为 "log" 的指标取自然对数再算改进,阈值在对数空间施加。困惑度从 32 降到 28 是 log(28)-log(32)=-0.133(低更好),远超 2% 阈值。

if scale == "log": a = log(candidate); b = log(baseline) else: a = candidate; b = baseline

scale="linear"(默认)跳过变换,同代码路径处理两者。

每种子配对检验

第 50 节运行器每运行发一个终指标 blob。配对检验需候选与基线每种子各一 blob。编排器在两配置下跨种子列表跑同实验,递评估器两列 ExperimentResult。评估器按种子配对(种子在 result.metrics["seed"]),走请求指标。种子跨两列不匹配则抛 PairingError,编排器应重跑。

评估器跑三个独立计算,在判定路径合。每计算是无共享状态的纯函数。

二、从零实现

Verdict 的形状

Verdict hypothesis_id : int metric : str direction : "higher_is_better" | "lower_is_better" scale : "linear" | "log" candidate_mean : float baseline_mean : float improvement : float (有符号, 分数; 见方向规则) p_value : float | None (n < 2 时 None) significance_threshold : float improvement_threshold : float verdict : "improved" | "regressed" | "noise" | "failed" rationale : str

判定路径是小决策表:

1. 若任何候选结果 terminal != "ok": verdict = "failed" 2. 否则若 |improvement| < improvement_threshold: verdict = "noise" 3. 否则若 p_value is None 或 > significance: verdict = "noise" 4. 否则若 improvement > 0: verdict = "improved" 5. 否则: verdict = "regressed"

rationale 是编排器可对假设 id 日志的一行人话句。

code/main.py 定义 MetricSpecVerdictEvaluator、t 统计与不完全贝塔助手、确定性 demo。t 检验纯 stdlib math,numpy 仅读指标列与算均值方差。

def evaluate(candidate_runs, baseline_runs, metric_spec): cand = [normalise(r.metrics[metric_spec.name], metric_spec.scale) for r in candidate_runs] base = [normalise(r.metrics[metric_spec.name], metric_spec.scale) for r in baseline_runs] if any(r.terminal != "ok" for r in candidate_runs): return Verdict(..., verdict="failed", rationale="某候选运行非 ok") improvement = direction_aware_improvement(mean(cand), mean(base), metric_spec.direction) p = paired_t_test(cand, base) if len(cand) >= 2 else None if abs(improvement) < metric_spec.improvement_threshold: v = "noise" elif p is None or p > metric_spec.significance_threshold: v = "noise" elif improvement > 0: v = "improved" else: v = "regressed" return Verdict(..., verdict=v, p_value=p, improvement=improvement, rationale=...)

设计要点:三计算独立纯函数(归一化、改进、t 检验),判定路径在合,每步可单测。2% 阈值防「统计显著但实际无感」的噪声判定——循环对用户测不出的变化不感兴趣。对数归一化使困惑度可与准确率混合报告。配对设计控种子,使差是效应而非随机初始化噪声。

三、框架对比

统计检验库(scipy.stats.ttest_relstatsmodels)提供配对 t 检验一行调用,但黑盒后你不清楚自由度、p 值算法、边界处理。本节从零写 Lentz 连分式的不完全贝塔,让你读清双侧 p 值怎么来。ML 研究的标准是多种子(3~5)配对检验 + 报告均值±标准差,p < 0.05 作显著。WandB/MLflow 的 runs 对比、HuggingFace 的模型对比用同统计,常加 Bonferroni 校正(多次比较)。贝叶斯 A/B 测试是频率派 t 检验的替代,给「改进概率」而非 p 值。本节的判定决策表是这些方法的共同输出形状。

四、可复用产物

code/main.py:Evaluator.evaluate(...) 是编排器入口,产 Verdict 附到假设队列。paired_t_testdirection_aware_improvementnormalise 是纯函数可独立复用——任何「候选 vs 基线」统计比较场景。判定决策表使「改进/回归/噪声/失败」四态明确,编排器按态决定弹下一假设或收尾。

五、练习

  1. 种子不配:故意让候选与基线种子集不匹配,确认抛 PairingError
  2. n=1 边界:单种子跑,确认 p_value=None、判定退化为只看改进阈值。
  3. 对数 vs 线性:同一指标分别设 scale=loglinear,对比改进值与判定。
  4. 阈值扫描:扫 improvement_threshold 从 0.01 到 0.1,观察改进判为噪声的比例。
  5. Bonferroni:多假设并行评估时,给 p 值阈值乘假设数,讨论对假阳的控制。

本节要点回顾

  1. 配对检验控种子:同种子候选 vs 基线,差均值是效应,标准误是噪声底。
  2. 从零 t 检验:60 行 stdlib,Lentz 连分式的不完全贝塔算双侧 p 值。
  3. 方向感知:指标有「高更好/低更好」,改进有符号,判定读符号与量级。
  4. 2% 阈值:统计显著但实际无感判噪声,循环对用户测不出的变化不感兴趣。
  5. 对数归一化:困惑度这类取对数再比,可与线性指标混合报告。
  6. 四态判定:改进/回归/噪声/失败,编排器按态决定后续。

下一节,我们做「论文写作器」——把研究论文当结构化工件,先生成 LaTeX 骨架声明摘要/节/图位/参考文献键,再填散文。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U