vimeml-tiny-zh-v1 / source /scripts /benchmarks /compare_standard_ime.py
Voltline's picture
Release vimeml-tiny-zh-v1 (step 844730): FP32 bundle, INT8 Core ML packages, source snapshot
81cffe7 verified
Raw History Blame Contribute Delete
4.65 kB
"""Compare completed standard IME scores without rerunning model inference."""
import argparse
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "src"))
from vimeml.benchmarks.comparison import paired, rows
from vimeml.benchmarks.standard_ime import read
from vimeml.training.data import write_json
def comparison(before, after):
result = paired(before, after)
counts = result.pop("paired")
counts["before_wrong_after_correct"] = counts.pop("v1_wrong_v2_correct")
counts["before_correct_after_wrong"] = counts.pop("v1_correct_v2_wrong")
# Cases share authors/users; the unadjusted case-level p is exploratory.
counts.pop("significant_at_0_05")
result["before"] = result.pop("v1")
result["after"] = result.pop("v2")
result["paired"] = counts
result["top1_delta_percentage_points"] = 100 * (
result["after"]["top1_accuracy"] - result["before"]["top1_accuracy"])
return result
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--before", required=True, type=Path)
parser.add_argument("--after", required=True, type=Path)
parser.add_argument("--output", required=True, type=Path)
args = parser.parse_args()
if args.output.exists():
raise ValueError("Preserve prior comparisons; choose a new output.")
before_report = read(args.before / "metrics.json")
after_report = read(args.after / "metrics.json")
# Historical regression caches predate explicit label-quality metadata.
for report in (before_report, after_report):
if report.get("split") == "regression":
report.setdefault("label_quality", "legacy_historical_draft")
for key in ("format", "split", "label_quality", "labels_formal_gold", "policy", "result_role"):
if before_report[key] != after_report[key]:
raise ValueError(f"Evaluation protocol differs: {key}")
if before_report["format"] != "vimeml_standard_ime_metrics_v1":
raise ValueError("Expected completed standard IME reports.")
if before_report["status"] != "complete" or after_report["status"] != "complete":
raise ValueError("Both evaluations must be complete.")
if before_report["benchmark_manifest"] != after_report["benchmark_manifest"]:
raise ValueError("Frozen benchmark versions differ.")
if before_report["export_provenance"] != after_report["export_provenance"]:
raise ValueError("Converter/dictionary exports differ.")
if before_report["split"] == "blind":
if before_report["evaluation_plan"] != after_report["evaluation_plan"]:
raise ValueError("Blind comparisons must share the registered plan.")
before = rows(args.before / "scores.jsonl")
after = rows(args.after / "scores.jsonl")
after_by_id = {row["id"]: row for row in after}
for row in before:
other = after_by_id.get(row["id"])
if other is None or any(row[k] != other[k] for k in ("source", "provenance", "candidates")):
raise ValueError("Frozen source, provenance or candidate contents differ.")
sources = sorted({row["source"] for row in before})
report = {
"format": "vimeml_standard_ime_paired_v1", "status": "complete",
"split": before_report["split"], "result_role": before_report["result_role"],
"benchmark_release_id": before_report["benchmark_manifest"]["release_id"],
"label_quality": before_report["label_quality"],
"labels_formal_gold": before_report["labels_formal_gold"],
"before_model": before_report["model"], "after_model": after_report["model"],
"before_scores": str(args.before.resolve()), "after_scores": str(args.after.resolve()),
"policy": before_report["policy"],
"statistical_note": "Case-level exact McNemar p is exploratory: shared author/user groups and multiple comparisons are not adjusted; no equivalence claim.",
"by_source": {source: comparison([r for r in before if r["source"] == source],
[r for r in after if r["source"] == source]) for source in sources},
"micro": comparison(before, after),
}
if set(sources) == {"wrime", "jmultiwoz"}:
report["equal_source_macro_top1_delta_percentage_points"] = sum(
result["top1_delta_percentage_points"] for result in report["by_source"].values()) / 2
write_json(args.output, report)
print({"split": report["split"], "paired": report["micro"]["paired"],
"delta_pp": report["micro"]["top1_delta_percentage_points"]})
if __name__ == "__main__":
main()