anhtld commited on
Commit
5223b41
·
verified ·
1 Parent(s): 6df3978

Report pairwise calibration ECE for nonlinear selector

Browse files
workspace/scripts/eval_nonlinear_dominance_selector.py CHANGED
@@ -36,10 +36,13 @@ from scripts.eval_learned_dominance_selector import ( # noqa: E402
36
  _evaluate_predictions,
37
  _feature_names,
38
  _group_means,
 
 
39
  _resolve_index_path,
40
  _selector_chart_map,
41
  _simple_summary,
42
  _source_evidence_map,
 
43
  _uses_chart_compat,
44
  _uses_source_evidence,
45
  )
@@ -197,11 +200,32 @@ def main(argv: list[str] | None = None) -> int:
197
  seed=args.seed,
198
  )
199
  eval_predictions = _predict(best["model"], eval_dataset, model_type=best["model_type"])
200
- eval_cases = _evaluate_predictions(eval_dataset, eval_predictions, tau=best["tau"])
201
  fit_predictions = _predict(best["model"], fit_dataset, model_type=best["model_type"])
202
  select_predictions = _predict(best["model"], select_dataset, model_type=best["model_type"])
203
- fit_cases = _evaluate_predictions(fit_dataset, fit_predictions, tau=best["tau"])
204
- select_cases = _evaluate_predictions(select_dataset, select_predictions, tau=best["tau"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
 
206
  metric_names = sorted(
207
  {
@@ -264,9 +288,14 @@ def main(argv: list[str] | None = None) -> int:
264
  "num_selection_candidates": len(select_dataset["samples"]),
265
  "num_eval_candidates": len(eval_dataset["samples"]),
266
  "model_selection": best["selection"],
267
- "fit_summary": _simple_summary(fit_cases),
268
- "selection_summary": _simple_summary(select_cases),
269
- "eval_summary": _simple_summary(eval_cases),
 
 
 
 
 
270
  "summary": summary,
271
  "rows": eval_cases,
272
  }
@@ -512,15 +541,16 @@ def _table(metrics: dict[str, Any]) -> str:
512
  summary = metrics["eval_summary"]
513
  lines = [
514
  "% Auto-generated by scripts/eval_nonlinear_dominance_selector.py",
515
- "\\begin{tabular}{lrrrrrrrr}",
516
  "\\toprule",
517
- "Rows & Coverage & Fallback & Base succ. & Selected succ. & Oracle succ. & OutcomePTR & Succ. support gap & Succ. selector gap \\\\",
518
  "\\midrule",
519
  f"{metrics['num_eval_rows']} & {_fmt(summary.get('coverage'))} & "
520
  f"{_fmt(summary.get('fallback_rate'))} & {_fmt(summary.get('base_success'))} & "
521
  f"{_fmt(summary.get('selected_success'))} & {_fmt(summary.get('proposal_oracle_success'))} & "
522
  f"{_fmt(summary.get('outcome_ptr'))} & {_fmt(summary.get('success_support_gap'))} & "
523
- f"{_fmt(summary.get('success_selector_gap'))} \\\\",
 
524
  "\\bottomrule",
525
  "\\end{tabular}",
526
  ]
@@ -546,20 +576,23 @@ def _report(metrics: dict[str, Any]) -> str:
546
  "",
547
  "The model is fit on calibration-fit rows, and model/tau are selected on held-out calibration-selection rows only. Eval outcomes are used only for reporting.",
548
  "",
549
- "| Split | Coverage | Fallback | Base success | Selected success | Proposal oracle | OutcomePTR | Success support gap | Success selector gap |",
550
- "| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |",
551
  f"| fit | {_fmt(fit.get('coverage'))} | {_fmt(fit.get('fallback_rate'))} | "
552
  f"{_fmt(fit.get('base_success'))} | {_fmt(fit.get('selected_success'))} | "
553
  f"{_fmt(fit.get('proposal_oracle_success'))} | {_fmt(fit.get('outcome_ptr'))} | "
554
- f"{_fmt(fit.get('success_support_gap'))} | {_fmt(fit.get('success_selector_gap'))} |",
 
555
  f"| selection | {_fmt(selection.get('coverage'))} | {_fmt(selection.get('fallback_rate'))} | "
556
  f"{_fmt(selection.get('base_success'))} | {_fmt(selection.get('selected_success'))} | "
557
  f"{_fmt(selection.get('proposal_oracle_success'))} | {_fmt(selection.get('outcome_ptr'))} | "
558
- f"{_fmt(selection.get('success_support_gap'))} | {_fmt(selection.get('success_selector_gap'))} |",
 
559
  f"| eval | {_fmt(eval_summary.get('coverage'))} | {_fmt(eval_summary.get('fallback_rate'))} | "
560
  f"{_fmt(eval_summary.get('base_success'))} | {_fmt(eval_summary.get('selected_success'))} | "
561
  f"{_fmt(eval_summary.get('proposal_oracle_success'))} | {_fmt(eval_summary.get('outcome_ptr'))} | "
562
- f"{_fmt(eval_summary.get('success_support_gap'))} | {_fmt(eval_summary.get('success_selector_gap'))} |",
 
563
  "",
564
  "This is a train-calibrated selector diagnostic over already measured candidates, not a new rollout.",
565
  ]
 
36
  _evaluate_predictions,
37
  _feature_names,
38
  _group_means,
39
+ _pairwise_calibration_global,
40
+ _pairwise_calibration_summary,
41
  _resolve_index_path,
42
  _selector_chart_map,
43
  _simple_summary,
44
  _source_evidence_map,
45
+ _summary_with_pairwise,
46
  _uses_chart_compat,
47
  _uses_source_evidence,
48
  )
 
200
  seed=args.seed,
201
  )
202
  eval_predictions = _predict(best["model"], eval_dataset, model_type=best["model_type"])
 
203
  fit_predictions = _predict(best["model"], fit_dataset, model_type=best["model_type"])
204
  select_predictions = _predict(best["model"], select_dataset, model_type=best["model_type"])
205
+ eval_pairwise = _pairwise_calibration_summary(eval_dataset, eval_predictions)
206
+ fit_pairwise = _pairwise_calibration_summary(fit_dataset, fit_predictions)
207
+ select_pairwise = _pairwise_calibration_summary(select_dataset, select_predictions)
208
+ eval_cases = _evaluate_predictions(
209
+ eval_dataset,
210
+ eval_predictions,
211
+ tau=best["tau"],
212
+ include_pairwise_calibration=True,
213
+ pairwise_calibration=eval_pairwise,
214
+ )
215
+ fit_cases = _evaluate_predictions(
216
+ fit_dataset,
217
+ fit_predictions,
218
+ tau=best["tau"],
219
+ include_pairwise_calibration=True,
220
+ pairwise_calibration=fit_pairwise,
221
+ )
222
+ select_cases = _evaluate_predictions(
223
+ select_dataset,
224
+ select_predictions,
225
+ tau=best["tau"],
226
+ include_pairwise_calibration=True,
227
+ pairwise_calibration=select_pairwise,
228
+ )
229
 
230
  metric_names = sorted(
231
  {
 
288
  "num_selection_candidates": len(select_dataset["samples"]),
289
  "num_eval_candidates": len(eval_dataset["samples"]),
290
  "model_selection": best["selection"],
291
+ "fit_summary": _summary_with_pairwise(fit_cases, fit_pairwise),
292
+ "selection_summary": _summary_with_pairwise(select_cases, select_pairwise),
293
+ "eval_summary": _summary_with_pairwise(eval_cases, eval_pairwise),
294
+ "pairwise_causal_calibration": {
295
+ "fit": _pairwise_calibration_global(fit_pairwise),
296
+ "selection": _pairwise_calibration_global(select_pairwise),
297
+ "eval": _pairwise_calibration_global(eval_pairwise),
298
+ },
299
  "summary": summary,
300
  "rows": eval_cases,
301
  }
 
541
  summary = metrics["eval_summary"]
542
  lines = [
543
  "% Auto-generated by scripts/eval_nonlinear_dominance_selector.py",
544
+ "\\begin{tabular}{lrrrrrrrrr}",
545
  "\\toprule",
546
+ "Rows & Coverage & Fallback & Base succ. & Selected succ. & Oracle succ. & OutcomePTR & Succ. support gap & Succ. selector gap & Cal. ECE \\\\",
547
  "\\midrule",
548
  f"{metrics['num_eval_rows']} & {_fmt(summary.get('coverage'))} & "
549
  f"{_fmt(summary.get('fallback_rate'))} & {_fmt(summary.get('base_success'))} & "
550
  f"{_fmt(summary.get('selected_success'))} & {_fmt(summary.get('proposal_oracle_success'))} & "
551
  f"{_fmt(summary.get('outcome_ptr'))} & {_fmt(summary.get('success_support_gap'))} & "
552
+ f"{_fmt(summary.get('success_selector_gap'))} & "
553
+ f"{_fmt(summary.get('pairwise_causal_calibration_ece'))} \\\\",
554
  "\\bottomrule",
555
  "\\end{tabular}",
556
  ]
 
576
  "",
577
  "The model is fit on calibration-fit rows, and model/tau are selected on held-out calibration-selection rows only. Eval outcomes are used only for reporting.",
578
  "",
579
+ "| Split | Coverage | Fallback | Base success | Selected success | Proposal oracle | OutcomePTR | Success support gap | Success selector gap | Calibration ECE |",
580
+ "| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |",
581
  f"| fit | {_fmt(fit.get('coverage'))} | {_fmt(fit.get('fallback_rate'))} | "
582
  f"{_fmt(fit.get('base_success'))} | {_fmt(fit.get('selected_success'))} | "
583
  f"{_fmt(fit.get('proposal_oracle_success'))} | {_fmt(fit.get('outcome_ptr'))} | "
584
+ f"{_fmt(fit.get('success_support_gap'))} | {_fmt(fit.get('success_selector_gap'))} | "
585
+ f"{_fmt(fit.get('pairwise_causal_calibration_ece'))} |",
586
  f"| selection | {_fmt(selection.get('coverage'))} | {_fmt(selection.get('fallback_rate'))} | "
587
  f"{_fmt(selection.get('base_success'))} | {_fmt(selection.get('selected_success'))} | "
588
  f"{_fmt(selection.get('proposal_oracle_success'))} | {_fmt(selection.get('outcome_ptr'))} | "
589
+ f"{_fmt(selection.get('success_support_gap'))} | {_fmt(selection.get('success_selector_gap'))} | "
590
+ f"{_fmt(selection.get('pairwise_causal_calibration_ece'))} |",
591
  f"| eval | {_fmt(eval_summary.get('coverage'))} | {_fmt(eval_summary.get('fallback_rate'))} | "
592
  f"{_fmt(eval_summary.get('base_success'))} | {_fmt(eval_summary.get('selected_success'))} | "
593
  f"{_fmt(eval_summary.get('proposal_oracle_success'))} | {_fmt(eval_summary.get('outcome_ptr'))} | "
594
+ f"{_fmt(eval_summary.get('success_support_gap'))} | {_fmt(eval_summary.get('success_selector_gap'))} | "
595
+ f"{_fmt(eval_summary.get('pairwise_causal_calibration_ece'))} |",
596
  "",
597
  "This is a train-calibrated selector diagnostic over already measured candidates, not a new rollout.",
598
  ]