feat: tier-aware diag/val split with val-power repair (design 5.1)
This commit is contained in:
@@ -13,7 +13,7 @@ from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import sqlite3
|
||||
from collections import Counter
|
||||
from collections import Counter, defaultdict
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
@@ -59,6 +59,8 @@ class SplitBuildConfig:
|
||||
select_seed: 贪心选择器预洗牌种子(打破等增益平局)。
|
||||
val_ratio: validation 占 trainval 视频组总数的比例。
|
||||
split_seed: 视频组题级切分的洗牌种子。
|
||||
val_wrong_min: validation 池最少错题数,切分时保证功效(不足则从 diag 换入
|
||||
低 T2 错题组补足,耗尽 fail-loud)。
|
||||
"""
|
||||
|
||||
n_trainval: int
|
||||
@@ -68,6 +70,7 @@ class SplitBuildConfig:
|
||||
select_seed: int
|
||||
val_ratio: float
|
||||
split_seed: int
|
||||
val_wrong_min: int
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -119,10 +122,10 @@ def build_split(
|
||||
test → 加载题库并以视频归属切三池 → 原子冻结 pools.json → 写溯源 manifest →
|
||||
六条防御断言 fail-fast 校验。
|
||||
|
||||
契约(Task 11,非疏漏):build_split 有意保持 val_wrong_min-agnostic——内部调
|
||||
split_by_video_assignment 时不传 val_wrong_min(默认 0,不校验 validation 错题
|
||||
数)。McNemar 功效护栏是切分**冻结后**的独立校验,由 CLI 的 check_mcnemar_power
|
||||
在 build_split 返回后执行;切分构造本身不因功效阈失败,二者关注点分离。
|
||||
契约(Task 11):val_wrong_min 前置到切分内保证功效——build_split 计算
|
||||
wrong_tier_by_video 并连同 config.val_wrong_min 传入 split_by_video_assignment,
|
||||
切分时若 val 错题不足即从 diag 换入低 T2 错题组补足(耗尽 fail-loud)。CLI 的
|
||||
check_mcnemar_power 作切分冻结后的冗余最终确认。
|
||||
|
||||
参数:
|
||||
db_path: harness.db 路径(只读读取 predictions,不改动)。
|
||||
@@ -181,6 +184,11 @@ def build_split(
|
||||
# Phase 3: 加载题库 + 视频归属切三池 + 原子冻结。
|
||||
questions = load_benchmark(questions_dir)
|
||||
correctness = {pred["question_id"]: pred["correct"] for pred in preds}
|
||||
tier_by_q = {row["question_id"]: row["tier"] for row in signal_rows}
|
||||
wrong_tier_by_video: dict[str, int] = defaultdict(int)
|
||||
for pred in preds:
|
||||
if not pred["correct"] and tier_by_q.get(pred["question_id"]) == "T2":
|
||||
wrong_tier_by_video[pred["video_id"]] += 1
|
||||
pools = split_by_video_assignment(
|
||||
questions,
|
||||
assignment,
|
||||
@@ -188,6 +196,8 @@ def build_split(
|
||||
config.val_ratio,
|
||||
config.split_seed,
|
||||
baseline_run_id=baseline_run_id,
|
||||
val_wrong_min=config.val_wrong_min,
|
||||
wrong_tier_by_video=dict(wrong_tier_by_video),
|
||||
)
|
||||
save_pools(pools, out_path)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user