anhtld commited on
Commit
5a8bcb4
·
verified ·
1 Parent(s): 47db1bc

auto-sync 2026-07-04T00:30:01Z workspace (part 6)

Browse files
workspace/scripts/eval_learned_dominance_selector.py CHANGED
@@ -110,6 +110,15 @@ def main(argv: list[str] | None = None) -> int:
110
  "candidate success to prioritize the lexicographic success/progress utility."
111
  ),
112
  )
 
 
 
 
 
 
 
 
 
113
  parser.add_argument("--bootstrap-samples", type=int, default=1000)
114
  args = parser.parse_args(argv)
115
 
@@ -158,7 +167,11 @@ def main(argv: list[str] | None = None) -> int:
158
  target=args.target,
159
  source_evidence=source_evidence,
160
  )
161
- best = _fit_select_ridge(calibration_dataset, lambdas=lambdas)
 
 
 
 
162
  eval_cases = _evaluate_dataset(eval_dataset, best["weights"], best["mean"], best["std"], tau=best["tau"])
163
  calibration_cases = _evaluate_dataset(
164
  calibration_dataset,
@@ -192,6 +205,7 @@ def main(argv: list[str] | None = None) -> int:
192
  "k": args.k,
193
  "feature_set": args.feature_set,
194
  "target": args.target,
 
195
  "chart_feature_mode": chart_feature_mode,
196
  "feature_names": _feature_names(args.feature_set),
197
  "ridge_lambdas": lambdas,
@@ -235,7 +249,7 @@ def main(argv: list[str] | None = None) -> int:
235
  (out_dir / "train.log").write_text(
236
  "trained ridge dominance calibrator on calibration measured rows only\n"
237
  f"selected_lambda={best['lambda']}\n"
238
- f"tau={best['tau']:.6f}\n"
239
  f"calibration_input={args.calibration_input}\n"
240
  )
241
  (out_dir / "eval.log").write_text(
@@ -609,7 +623,12 @@ def _target_value(
609
  raise ValueError(f"unknown target: {target}")
610
 
611
 
612
- def _fit_select_ridge(dataset: dict[str, Any], *, lambdas: list[float]) -> dict[str, Any]:
 
 
 
 
 
613
  samples = dataset["samples"]
614
  if not samples:
615
  raise ValueError("cannot fit learned dominance selector without candidates")
@@ -627,7 +646,11 @@ def _fit_select_ridge(dataset: dict[str, Any], *, lambdas: list[float]) -> dict[
627
  penalty[0, 0] = 0.0
628
  weights = np.linalg.pinv(x_norm.T @ x_norm + penalty) @ (x_norm.T @ y)
629
  predictions = x_norm @ weights
630
- tau, selection = _choose_tau(dataset, predictions)
 
 
 
 
631
  key = (
632
  float(selection["selected_success"]),
633
  float(selection["selected_utility"]),
@@ -648,6 +671,27 @@ def _fit_select_ridge(dataset: dict[str, Any], *, lambdas: list[float]) -> dict[
648
  return best
649
 
650
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651
  def _choose_tau(dataset: dict[str, Any], predictions: np.ndarray) -> tuple[float, dict[str, float | None]]:
652
  candidates = sorted(float(value) for value in predictions)
653
  thresholds = [min(candidates) - 1.0, *candidates, max(candidates) + 1.0]
@@ -676,7 +720,7 @@ def _evaluate_dataset(
676
  mean: np.ndarray,
677
  std: np.ndarray,
678
  *,
679
- tau: float,
680
  ) -> list[dict[str, Any]]:
681
  x = np.stack([sample["feature"] for sample in dataset["samples"]], axis=0)
682
  x_norm = (x - mean) / std
@@ -684,14 +728,20 @@ def _evaluate_dataset(
684
  return _evaluate_predictions(dataset, x_norm @ weights, tau=tau)
685
 
686
 
687
- def _evaluate_predictions(dataset: dict[str, Any], predictions: np.ndarray, *, tau: float) -> list[dict[str, Any]]:
 
 
 
 
 
688
  samples = dataset["samples"]
689
  rows: list[dict[str, Any]] = []
690
  for row_index, sample_indices in sorted(dataset["by_row"].items()):
691
  best_index = max(sample_indices, key=lambda index: float(predictions[index]))
692
  sample = samples[best_index]
693
  predicted_margin = float(predictions[best_index])
694
- execute = predicted_margin > float(tau)
 
695
  selected_utility = (
696
  float(sample["candidate_utility"]) if execute else float(sample["base_utility"])
697
  )
@@ -708,7 +758,7 @@ def _evaluate_predictions(dataset: dict[str, Any], predictions: np.ndarray, *, t
708
  "train_seed": sample["train_seed"],
709
  "selected_candidate_index": int(sample["candidate_index"]),
710
  "predicted_margin": predicted_margin,
711
- "tau": float(tau),
712
  "execute_generated": float(execute),
713
  "coverage": float(execute),
714
  "fallback_rate": float(not execute),
@@ -736,6 +786,56 @@ def _evaluate_predictions(dataset: dict[str, Any], predictions: np.ndarray, *, t
736
  return rows
737
 
738
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
739
  def _simple_summary(rows: list[dict[str, Any]]) -> dict[str, float | None]:
740
  keys = [
741
  "base_success",
@@ -819,7 +919,8 @@ def _report(metrics: dict[str, Any]) -> str:
819
  f"Calibration rows: `{metrics['num_calibration_rows']}`",
820
  f"Eval rows: `{metrics['num_eval_rows']}`",
821
  f"Selected ridge lambda: `{metrics['selected_lambda']}`",
822
- f"Tau: `{metrics['tau']:.6f}`",
 
823
  f"Feature set: `{metrics['feature_set']}`",
824
  f"Target: `{metrics['target']}`",
825
  "",
@@ -899,6 +1000,14 @@ def _fmt(value: Any) -> str:
899
  return f"{float(value):.4f}"
900
 
901
 
 
 
 
 
 
 
 
 
902
  def _run(command: list[str]) -> str:
903
  try:
904
  return subprocess.check_output(command, cwd=PROJECT_ROOT, text=True).strip()
 
110
  "candidate success to prioritize the lexicographic success/progress utility."
111
  ),
112
  )
113
+ parser.add_argument(
114
+ "--threshold-scope",
115
+ choices=("global", "task"),
116
+ default="global",
117
+ help=(
118
+ "Calibrate one global execute/fallback threshold or a Mondrian "
119
+ "threshold per visible task_id bucket using calibration rows only."
120
+ ),
121
+ )
122
  parser.add_argument("--bootstrap-samples", type=int, default=1000)
123
  args = parser.parse_args(argv)
124
 
 
167
  target=args.target,
168
  source_evidence=source_evidence,
169
  )
170
+ best = _fit_select_ridge(
171
+ calibration_dataset,
172
+ lambdas=lambdas,
173
+ threshold_scope=args.threshold_scope,
174
+ )
175
  eval_cases = _evaluate_dataset(eval_dataset, best["weights"], best["mean"], best["std"], tau=best["tau"])
176
  calibration_cases = _evaluate_dataset(
177
  calibration_dataset,
 
205
  "k": args.k,
206
  "feature_set": args.feature_set,
207
  "target": args.target,
208
+ "threshold_scope": args.threshold_scope,
209
  "chart_feature_mode": chart_feature_mode,
210
  "feature_names": _feature_names(args.feature_set),
211
  "ridge_lambdas": lambdas,
 
249
  (out_dir / "train.log").write_text(
250
  "trained ridge dominance calibrator on calibration measured rows only\n"
251
  f"selected_lambda={best['lambda']}\n"
252
+ f"tau={_format_tau(best['tau'])}\n"
253
  f"calibration_input={args.calibration_input}\n"
254
  )
255
  (out_dir / "eval.log").write_text(
 
623
  raise ValueError(f"unknown target: {target}")
624
 
625
 
626
+ def _fit_select_ridge(
627
+ dataset: dict[str, Any],
628
+ *,
629
+ lambdas: list[float],
630
+ threshold_scope: str = "global",
631
+ ) -> dict[str, Any]:
632
  samples = dataset["samples"]
633
  if not samples:
634
  raise ValueError("cannot fit learned dominance selector without candidates")
 
646
  penalty[0, 0] = 0.0
647
  weights = np.linalg.pinv(x_norm.T @ x_norm + penalty) @ (x_norm.T @ y)
648
  predictions = x_norm @ weights
649
+ tau, selection = _choose_thresholds(
650
+ dataset,
651
+ predictions,
652
+ threshold_scope=threshold_scope,
653
+ )
654
  key = (
655
  float(selection["selected_success"]),
656
  float(selection["selected_utility"]),
 
671
  return best
672
 
673
 
674
+ def _choose_thresholds(
675
+ dataset: dict[str, Any],
676
+ predictions: np.ndarray,
677
+ *,
678
+ threshold_scope: str,
679
+ ) -> tuple[float | dict[str, float], dict[str, float | None]]:
680
+ if threshold_scope == "global":
681
+ return _choose_tau(dataset, predictions)
682
+ if threshold_scope != "task":
683
+ raise ValueError(f"unknown threshold_scope: {threshold_scope}")
684
+ global_tau, _global_summary = _choose_tau(dataset, predictions)
685
+ task_taus: dict[str, float] = {"__global__": float(global_tau)}
686
+ for task_id, row_indices in _rows_by_task(dataset).items():
687
+ subset = _subset_dataset_rows(dataset, row_indices)
688
+ subset_predictions = _predictions_for_subset(dataset, predictions, subset)
689
+ task_tau, _task_summary = _choose_tau(subset, subset_predictions)
690
+ task_taus[task_id] = float(task_tau)
691
+ cases = _evaluate_predictions(dataset, predictions, tau=task_taus)
692
+ return task_taus, _simple_summary(cases)
693
+
694
+
695
  def _choose_tau(dataset: dict[str, Any], predictions: np.ndarray) -> tuple[float, dict[str, float | None]]:
696
  candidates = sorted(float(value) for value in predictions)
697
  thresholds = [min(candidates) - 1.0, *candidates, max(candidates) + 1.0]
 
720
  mean: np.ndarray,
721
  std: np.ndarray,
722
  *,
723
+ tau: float | dict[str, float],
724
  ) -> list[dict[str, Any]]:
725
  x = np.stack([sample["feature"] for sample in dataset["samples"]], axis=0)
726
  x_norm = (x - mean) / std
 
728
  return _evaluate_predictions(dataset, x_norm @ weights, tau=tau)
729
 
730
 
731
+ def _evaluate_predictions(
732
+ dataset: dict[str, Any],
733
+ predictions: np.ndarray,
734
+ *,
735
+ tau: float | dict[str, float],
736
+ ) -> list[dict[str, Any]]:
737
  samples = dataset["samples"]
738
  rows: list[dict[str, Any]] = []
739
  for row_index, sample_indices in sorted(dataset["by_row"].items()):
740
  best_index = max(sample_indices, key=lambda index: float(predictions[index]))
741
  sample = samples[best_index]
742
  predicted_margin = float(predictions[best_index])
743
+ row_tau = _tau_for_sample(sample, tau)
744
+ execute = predicted_margin > row_tau
745
  selected_utility = (
746
  float(sample["candidate_utility"]) if execute else float(sample["base_utility"])
747
  )
 
758
  "train_seed": sample["train_seed"],
759
  "selected_candidate_index": int(sample["candidate_index"]),
760
  "predicted_margin": predicted_margin,
761
+ "tau": row_tau,
762
  "execute_generated": float(execute),
763
  "coverage": float(execute),
764
  "fallback_rate": float(not execute),
 
786
  return rows
787
 
788
 
789
+ def _tau_for_sample(sample: dict[str, Any], tau: float | dict[str, float]) -> float:
790
+ if isinstance(tau, dict):
791
+ return float(tau.get(str(sample.get("task_id", "")), tau.get("__global__", 0.0)))
792
+ return float(tau)
793
+
794
+
795
+ def _rows_by_task(dataset: dict[str, Any]) -> dict[str, list[int]]:
796
+ grouped: dict[str, list[int]] = defaultdict(list)
797
+ for row_index, sample_indices in dataset["by_row"].items():
798
+ if not sample_indices:
799
+ continue
800
+ task_id = str(dataset["samples"][sample_indices[0]].get("task_id", "unknown"))
801
+ grouped[task_id].append(int(row_index))
802
+ return grouped
803
+
804
+
805
+ def _subset_dataset_rows(dataset: dict[str, Any], row_indices: list[int]) -> dict[str, Any]:
806
+ wanted = set(int(row) for row in row_indices)
807
+ old_to_new_sample: dict[int, int] = {}
808
+ samples: list[dict[str, Any]] = []
809
+ by_row: dict[int, list[int]] = {}
810
+ for old_row in sorted(wanted):
811
+ if old_row not in dataset["by_row"]:
812
+ continue
813
+ new_row = len(by_row)
814
+ by_row[new_row] = []
815
+ for old_sample_index in dataset["by_row"][old_row]:
816
+ old_to_new_sample[old_sample_index] = len(samples)
817
+ sample = dict(dataset["samples"][old_sample_index])
818
+ sample["row_index"] = new_row
819
+ by_row[new_row].append(len(samples))
820
+ samples.append(sample)
821
+ return {
822
+ "samples": samples,
823
+ "by_row": by_row,
824
+ "num_rows": len(by_row),
825
+ "_old_to_new_sample": old_to_new_sample,
826
+ }
827
+
828
+
829
+ def _predictions_for_subset(
830
+ dataset: dict[str, Any],
831
+ predictions: np.ndarray,
832
+ subset: dict[str, Any],
833
+ ) -> np.ndarray:
834
+ old_to_new = subset.get("_old_to_new_sample", {})
835
+ ordered_old_indices = sorted(old_to_new, key=lambda old: old_to_new[old])
836
+ return np.asarray([float(predictions[old]) for old in ordered_old_indices], dtype=float)
837
+
838
+
839
  def _simple_summary(rows: list[dict[str, Any]]) -> dict[str, float | None]:
840
  keys = [
841
  "base_success",
 
919
  f"Calibration rows: `{metrics['num_calibration_rows']}`",
920
  f"Eval rows: `{metrics['num_eval_rows']}`",
921
  f"Selected ridge lambda: `{metrics['selected_lambda']}`",
922
+ f"Tau: `{_format_tau(metrics['tau'])}`",
923
+ f"Threshold scope: `{metrics.get('threshold_scope', 'global')}`",
924
  f"Feature set: `{metrics['feature_set']}`",
925
  f"Target: `{metrics['target']}`",
926
  "",
 
1000
  return f"{float(value):.4f}"
1001
 
1002
 
1003
+ def _format_tau(value: Any) -> str:
1004
+ if isinstance(value, dict):
1005
+ return json.dumps({key: round(float(val), 6) for key, val in sorted(value.items())})
1006
+ if isinstance(value, (int, float)) and math.isfinite(float(value)):
1007
+ return f"{float(value):.6f}"
1008
+ return str(value)
1009
+
1010
+
1011
  def _run(command: list[str]) -> str:
1012
  try:
1013
  return subprocess.check_output(command, cwd=PROJECT_ROOT, text=True).strip()
workspace/scripts/summarize_ctt_runs.py CHANGED
@@ -41,6 +41,7 @@ def main(argv: list[str] | None = None) -> int:
41
  args = parser.parse_args(argv)
42
 
43
  rows = []
 
44
  reproduce = args.run_root / "reproduce_v0" / "metrics.json"
45
  if reproduce.exists():
46
  rows.extend(_reproduce_rows(reproduce))
@@ -53,6 +54,7 @@ def main(argv: list[str] | None = None) -> int:
53
  }:
54
  continue
55
  rows.append(_ctt_row(metrics_path))
 
56
  for metrics_path in sorted(args.run_root.glob("*memory*_val_proxy/metrics.json")):
57
  rows.append(_positive_memory_row(metrics_path))
58
  local_atlas = args.run_root / "local_atlas_val_proxy" / "metrics.json"
@@ -65,11 +67,21 @@ def main(argv: list[str] | None = None) -> int:
65
  if utility.exists():
66
  rows.append(_utility_row(utility))
67
  for metrics_path in sorted(args.run_root.glob("ctt_dominance*/metrics.json")):
 
 
68
  rows.append(_dominance_row(metrics_path))
69
- for metrics_path in sorted(args.run_root.glob("ctt_learned_dominance*/metrics.json")):
70
- rows.append(_dominance_row(metrics_path))
 
 
 
 
 
71
  for metrics_path in sorted(args.run_root.glob("ctt*_nonlinear_dominance*/metrics.json")):
 
 
72
  rows.append(_dominance_row(metrics_path))
 
73
 
74
  args.out_csv.parent.mkdir(parents=True, exist_ok=True)
75
  with args.out_csv.open("w", newline="") as handle:
 
41
  args = parser.parse_args(argv)
42
 
43
  rows = []
44
+ seen_metric_paths: set[Path] = set()
45
  reproduce = args.run_root / "reproduce_v0" / "metrics.json"
46
  if reproduce.exists():
47
  rows.extend(_reproduce_rows(reproduce))
 
54
  }:
55
  continue
56
  rows.append(_ctt_row(metrics_path))
57
+ seen_metric_paths.add(metrics_path)
58
  for metrics_path in sorted(args.run_root.glob("*memory*_val_proxy/metrics.json")):
59
  rows.append(_positive_memory_row(metrics_path))
60
  local_atlas = args.run_root / "local_atlas_val_proxy" / "metrics.json"
 
67
  if utility.exists():
68
  rows.append(_utility_row(utility))
69
  for metrics_path in sorted(args.run_root.glob("ctt_dominance*/metrics.json")):
70
+ if metrics_path in seen_metric_paths:
71
+ continue
72
  rows.append(_dominance_row(metrics_path))
73
+ seen_metric_paths.add(metrics_path)
74
+ for pattern in ("ctt_learned_dominance*/metrics.json", "ctt*_learned_dominance*/metrics.json"):
75
+ for metrics_path in sorted(args.run_root.glob(pattern)):
76
+ if metrics_path in seen_metric_paths:
77
+ continue
78
+ rows.append(_dominance_row(metrics_path))
79
+ seen_metric_paths.add(metrics_path)
80
  for metrics_path in sorted(args.run_root.glob("ctt*_nonlinear_dominance*/metrics.json")):
81
+ if metrics_path in seen_metric_paths:
82
+ continue
83
  rows.append(_dominance_row(metrics_path))
84
+ seen_metric_paths.add(metrics_path)
85
 
86
  args.out_csv.parent.mkdir(parents=True, exist_ok=True)
87
  with args.out_csv.open("w", newline="") as handle: