fix: guard floor phase against n_trainval budget + assert epsilon on output
Codex Task 8 审查修复: - Important 1: _satisfy_floors 每步移入前检查预算,floor 需求超 n_trainval 时 抛 InfeasibleSplitError(fail loud),保证 trainval 永不超额挤占 test;补预算超限测试。 - Important 2: 确定性测试末尾用 _epsilon_ok 断言产出 test 真满足 ε(两维偏差回归护栏), 并断言 trainval <= n_trainval。 - Minor: fixture docstring 注明结构真实 / signal 二次构造,正式运行由真实诊断替换。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -409,6 +409,9 @@ def _satisfy_floors(
|
||||
每轮取未达标类型的缺口,候选 = 能填 ≥1 槽 且 移入后 test 仍满足 ε 的视频;候选为空即
|
||||
死锁抛 InfeasibleSplitError;否则选填槽最多者(等槽数按预洗牌顺序取首个,确定性)。
|
||||
|
||||
n_trainval 是硬预算:floor 需求超出预算(尚有缺口却已达 n_trainval)也判不可行 fail loud,
|
||||
保证返回的 trainval 永不超过 n_trainval(不因硬约束悄悄超额、挤占 test)。
|
||||
|
||||
参数:
|
||||
selected: 当前 trainval(就地追加)。
|
||||
pool: 当前剩余池 = test 补集(就地移除)。
|
||||
@@ -416,12 +419,17 @@ def _satisfy_floors(
|
||||
config: 选择配置。
|
||||
|
||||
异常:
|
||||
InfeasibleSplitError: 存在未达标类型但无候选可在不破 ε 下填补。
|
||||
InfeasibleSplitError: 存在未达标类型但无候选可在不破 ε 下填补,
|
||||
或 floor 需求超过 n_trainval 预算。
|
||||
"""
|
||||
while True:
|
||||
deficits = _unmet_floors(selected, config.floor_k)
|
||||
if not deficits:
|
||||
return
|
||||
if len(selected) >= config.n_trainval:
|
||||
raise InfeasibleSplitError(
|
||||
f"floor 需求超过 n_trainval={config.n_trainval} 预算,剩余缺口: {dict(deficits)}"
|
||||
)
|
||||
candidates = [
|
||||
video
|
||||
for video in pool
|
||||
@@ -501,7 +509,8 @@ def select_split(videos: list[VideoRecord], *, config: SelectConfig) -> SplitAss
|
||||
SplitAssignment,trainval 按选择顺序、test 按 videos 原始顺序。
|
||||
|
||||
异常:
|
||||
InfeasibleSplitError: videos 为空,或 floor 与 ε 死锁无法满足。
|
||||
InfeasibleSplitError: videos 为空、floor 与 ε 死锁无法满足、
|
||||
或 floor 需求超过 n_trainval 预算。
|
||||
"""
|
||||
if not videos:
|
||||
raise InfeasibleSplitError("videos 为空,无法执行切分")
|
||||
|
||||
Reference in New Issue
Block a user