diff options
| author | YurenHao0426 <Blackhao0426@gmail.com> | 2026-08-06 12:12:41 -0500 |
|---|---|---|
| committer | YurenHao0426 <Blackhao0426@gmail.com> | 2026-08-06 12:12:41 -0500 |
| commit | d91cfe4d806f4c1e09c6cb75829a8625ff6506ec (patch) | |
| tree | a5cf10dddfbdd904877872e38c03b8e81dff0107 /experiments/analyze_contrastive_bias_b1.py | |
| parent | 051414af6f3b7016ce8ee4125a41dfacf0a01a3e (diff) | |
experiment: add contrastive state-bias screen
Diffstat (limited to 'experiments/analyze_contrastive_bias_b1.py')
| -rw-r--r-- | experiments/analyze_contrastive_bias_b1.py | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/experiments/analyze_contrastive_bias_b1.py b/experiments/analyze_contrastive_bias_b1.py new file mode 100644 index 0000000..527b2ba --- /dev/null +++ b/experiments/analyze_contrastive_bias_b1.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python3 +"""Audit the frozen contrastive state-bias B1 gate.""" +import argparse +import json +import math +from pathlib import Path + +from contrastive_bias_b1 import RESULT_ROOT, bias_cells + + +def read_json(path): + with open(path, encoding="utf-8") as handle: + return json.load(handle) + + +def cell_path(cell_id): + return RESULT_ROOT / ("dp-bias-b1-" + cell_id + ".json") + + +def valid_record(record, cell): + history = record.get("history") or {} + return ( + record.get("status") == "completed" + and record.get("cell_id") == cell["cell_id"] + and record.get("kind") == cell["kind"] + and record.get("rule") == cell["rule"] + and record.get("ratio") == cell["ratio"] + and history.get("finite") is True + and history.get("epochs_completed") == 20 + and math.isnan(float(history.get("test_accuracy", float("nan")))) + ) + + +def metric_max(record, key): + values = record["history"]["curves"][key] + return max(abs(float(value)) for value in values) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--out", type=Path, + default=RESULT_ROOT.parent / "b1_gate.json") + args = parser.parse_args() + cells = bias_cells() + missing = [cell["cell_id"] for cell in cells if not cell_path(cell["cell_id"]).is_file()] + if missing: + raise RuntimeError("missing B1 cells: " + ", ".join(missing)) + records = {} + for cell in cells: + record = read_json(cell_path(cell["cell_id"])) + if not valid_record(record, cell): + raise RuntimeError(f"invalid or incomplete B1 cell: {cell['cell_id']}") + records[cell["cell_id"]] = record + clean = records["clean"] + clean_acc = float(clean["history"]["final_validation_accuracy"]) + common = records["common-activity-r4-raw"] + common_acc = float(common["history"]["final_validation_accuracy"]) + common_error = metric_max( + common, "maximum_used_clean_difference_relative_error") + predictor_instruction_max = max( + metric_max(record, "instruction_observations_for_predictor") + for record in records.values() + ) + innovation_post_max = max( + metric_max(record, "post_bias_raw_bias_rms_ratio") + for cell_id, record in records.items() if "-innovation" in cell_id + ) + candidates = [] + table = [] + for ratio in (0.25, 1.0, 4.0): + tag = rate_tag = f"{ratio:g}".replace(".", "p") + row = {"ratio": ratio} + for rule in ("raw", "innovation", "oracle"): + record = records[f"activity-r{tag}-{rule}"] + row[rule] = float(record["history"]["final_validation_accuracy"]) + row["raw_degradation"] = clean_acc - row["raw"] + row["innovation_clean_gap"] = abs(row["innovation"] - clean_acc) + row["innovation_oracle_gap"] = abs(row["innovation"] - row["oracle"]) + row["innovation_post_bias_ratio_max"] = metric_max( + records[f"activity-r{tag}-innovation"], + "post_bias_raw_bias_rms_ratio") + row["passes"] = ( + row["raw_degradation"] >= 5.0 + and row["innovation_clean_gap"] <= 2.0 + and row["innovation_oracle_gap"] <= 1.0 + and row["innovation_post_bias_ratio_max"] <= 1e-3 + ) + if row["passes"]: + candidates.append(ratio) + table.append(row) + checks = { + "clean_at_least_70": clean_acc >= 70.0, + "common_within_0p2": abs(common_acc - clean_acc) <= 0.2, + "common_difference_error_at_most_1e_6": common_error <= 1e-6, + "some_activity_ratio_passes": bool(candidates), + "all_innovation_post_bias_at_most_1e_3": innovation_post_max <= 1e-3, + "predictor_saw_zero_instruction_observations": predictor_instruction_max == 0.0, + } + source_values = {json.dumps(row["source"], sort_keys=True) for row in records.values()} + registry_values = {row["registry_sha256"] for row in records.values()} + checks["single_source_lock"] = len(source_values) == 1 + checks["single_registry_lock"] = len(registry_values) == 1 + report = { + "stage": "contrastive_bias_b1", "gate": ( + "pass" if all(checks.values()) else "fail"), + "checks": checks, "clean_final_validation_accuracy": clean_acc, + "common_final_validation_accuracy": common_acc, + "common_maximum_difference_relative_error": common_error, + "innovation_maximum_post_bias_ratio": innovation_post_max, + "predictor_maximum_instruction_observations": predictor_instruction_max, + "activity_table": table, + "selected_confirmation_ratio": max(candidates) if candidates else None, + "num_expected_records": 17, "num_audited_records": len(records), + "source": clean["source"], "registry_sha256": clean["registry_sha256"], + } + args.out.parent.mkdir(parents=True, exist_ok=True) + with open(args.out, "w", encoding="utf-8") as handle: + json.dump(report, handle, indent=2, sort_keys=True) + handle.write("\n") + print(json.dumps(report, indent=2, sort_keys=True)) + + +if __name__ == "__main__": + main() |
