"""Build analysis/quant_report.html from analysis/quant_*.json files given on argv.""" import sys, json, html, datetime runs=[json.load(open(p)) for p in sys.argv[1:]] ORDER=["fp32","fp32_onnx","int8_ort","int8_w","int4_w"] LABEL={"fp32":"FP32 (PyTorch)","fp32_onnx":"FP32 (ONNX Runtime)","int8_ort":"INT8 static (ONNX Runtime)","int8_w":"INT8 weight-only (simulated)","int4_w":"INT4 weight-only (simulated)"} def pct(v): return "" if v is None else f"{v*100:.1f}%" def delta(v,ref): return "" if v is None else f"{(v-ref)*100:+.1f}" def cls(v,ref): if v is None: return "" d=(v-ref)*100; return "good" if d>=-0.5 else ("warn" if d>=-3 else "bad") css="""body{font-family:Segoe UI,system-ui,sans-serif;max-width:1100px;margin:2rem auto;padding:0 1rem;color:#222;line-height:1.45} h1{font-size:1.6rem}h2{font-size:1.2rem;margin-top:2rem;border-bottom:1px solid #ddd;padding-bottom:.3rem} table{border-collapse:collapse;width:100%;margin:1rem 0;font-size:.92rem}th,td{border:1px solid #ddd;padding:.45rem .6rem;text-align:right} th:first-child,td:first-child{text-align:left}th{background:#f4f4f4}tr:nth-child(even){background:#fafafa} .good{color:#1a7f37}.warn{color:#9a6700}.bad{color:#c0392b;font-weight:600}.muted{color:#666;font-size:.88rem} .bar{display:inline-block;height:10px;background:#4a7bd0;vertical-align:middle;margin-right:.4rem}code{background:#f2f2f2;padding:0 .25rem} .note{background:#fff8e1;border-left:4px solid #e0a800;padding:.6rem 1rem;margin:1rem 0}""" out=[f"
Generated {datetime.date.today()} · CPU i7-1360P · torch 2.12 / onnxruntime 1.26
", "{html.escape(r['ckpt'])}test faces: {r['n_test']} ({r['n_test_family']} family) · agreement subset: {r['n_agree']} · THR={r['thr']}
") out.append("| Variant | Family acc | Δ pts | Open-set acc | Δ pts | Agreement vs FP32 | Cos vs FP32 | Size | Latency/face (this PC) | Note |
|---|---|---|---|---|---|---|---|---|---|
| {LABEL[k]} | {pct(v['fam_acc'])} | {delta(v['fam_acc'],ref['fam_acc'])} | " f"{pct(v['openset_acc'])} | {delta(v['openset_acc'],ref['openset_acc'])} | " f"{pct(v['argmax_agree_vs_fp32'])} | {v['cos_vs_fp32']:.4f} | " f"{v['size_kb']/1024:.2f} MB | {lat} | {html.escape(v['note'])} |
| Variant | "+"".join(f"{n} | " for n in names)+"
|---|---|
| {LABEL[k]} | "+"".join(f"{pct(R[k]['per_class'].get(n))} | " for n in names)+"