Download code/tt_meteor/tests/test_reference_cpu.py from changh95/meteor-p150: direct link, hf CLI and curl.
- Browser
- Download file 15.1 kB
-
https://huggingface.co/changh95/meteor-p150/resolve/main/code/tt_meteor/tests/test_reference_cpu.py
- Command line
-
hf download hf://changh95/meteor-p150/code/tt_meteor/tests/test_reference_cpu.py
-
curl -L -o test_reference_cpu.py https://huggingface.co/changh95/meteor-p150/resolve/main/code/tt_meteor/tests/test_reference_cpu.py
15.1 kB
| # SPDX-License-Identifier: Apache-2.0 | |
| """The fp32 CPU reference (``tt_meteor.reference``) against ONNX Runtime on the deployed ``meteor_v157c3Z.onnx`` | |
| (PLAN.md 0.3 item 1: PCC >= 0.9999 before any data-dependent selection, set-based after it). | |
| Runs in the research venv (onnxruntime + torch + onnx); skipped where onnxruntime, torch or the ONNX is missing:: | |
| cd bundles/meteor-p150 && OMP_NUM_THREADS=4 PYTHONPATH=$PWD/code \\ | |
| /home/ubuntu/experiments/tt-models/tools/research-venv/bin/python -m pytest -q -s -p no:cacheprovider \\ | |
| code/tt_meteor/tests/test_reference_cpu.py | |
| 1. The shipped sample (PandaSet 019 frame 40) through ORT with every reference tap as an extra graph output and through | |
| the reference: all 48 internal taps and the 19 outputs. Float tensors PCC >= 0.9999 (measured 1.0000000000); | |
| boolean / argmax maps agreement >= 0.9999 (``lift.valid`` exact). ``depth_mean`` follows an argmax (a +-2-bin | |
| window around the softmax maximum): it is compared set-based, >= 99.9 % of the pixels within 2 fp16 ulps. | |
| 2. The stored ORT goldens of three more frames from two more rigs (METEOR's in-domain valday #40, nuScenes scene-0103 | |
| key-frame 9, PandaSet 090 frame 40; research/meteor and research/meteor/public_data), fed exactly as ORT saw them; | |
| valday also against its fp16 internal taps. | |
| 3. ``input_norm="imagenet"`` (D12 option) against ORT on the graph with the training normalisation inserted. | |
| 4. The TT port's exact rewrites (``reference.port_form``) teacher-forced from the ORT taps; the host lift geometry | |
| (``host.calib``) bit-exact against the graph's; the host decode (``host.result``) against the research decode | |
| (``research/meteor/public_data/scripts/me_public_common.py``). | |
| A JSON report with every number is written to ``logs/meteor/test_reference_cpu.json`` of the workspace. | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import os | |
| import sys | |
| from pathlib import Path | |
| import numpy as np | |
| import pytest | |
| ort = pytest.importorskip("onnxruntime") | |
| torch = pytest.importorskip("torch") | |
| pytest.importorskip("onnx") | |
| from tt_meteor.host.calib import lift_geometry, lift_ground_points # noqa: E402 | |
| from tt_meteor.host.postprocess import PostConfig # noqa: E402 | |
| from tt_meteor.host.preprocess import MeteorFrame, load_scene_frame # noqa: E402 | |
| from tt_meteor.host.result import build_output # noqa: E402 | |
| from tt_meteor.reference import config as C # noqa: E402 | |
| from tt_meteor.reference import port_form as PF # noqa: E402 | |
| from tt_meteor.reference.model import OUTPUT_NAMES, MeteorNet # noqa: E402 | |
| from tt_meteor.reference.ort import ORT_TAPS, OrtOracle # noqa: E402 | |
| from tt_meteor.reference.pipeline import MeteorReference # noqa: E402 | |
| from tt_meteor.reference.weights import MeteorWeights, find_onnx # noqa: E402 | |
| from tt_meteor.ttaw.golden import TapRegistry # noqa: E402 | |
| from tt_meteor.ttaw.metrics import pcc # noqa: E402 | |
| PKG = Path(__file__).resolve().parents[1] | |
| from tt_meteor.tests import paths as P # noqa: E402 | |
| SAMPLE = P.PANDASET_SCENE / "pandaset_019_f40" # the staged PandaSet sample (tests/paths.py) | |
| ROOT = Path("/home/ubuntu/experiments/tt-models") | |
| RESEARCH = ROOT / "research" / "meteor" | |
| THREADS = int(os.environ.get("METEOR_TEST_THREADS", "4")) | |
| PCC_MIN = 0.9999 | |
| AGREE_MIN = 0.9999 | |
| REPORT: dict = {} | |
| try: | |
| ONNX = find_onnx() | |
| except FileNotFoundError: | |
| pytest.skip("meteor_v157c3Z.onnx not found (METEOR_WEIGHTS_DIR or assets/meteor/hf_meteor)", | |
| allow_module_level=True) | |
| def _report(section: str, rows: dict) -> None: | |
| REPORT.setdefault(section, {}).update(rows) | |
| out = ROOT / "logs" / "meteor" | |
| if out.is_dir(): | |
| (out / "test_reference_cpu.json").write_text(json.dumps(REPORT, indent=1, sort_keys=True)) | |
| def _cmp(name: str, test, ref) -> dict: | |
| t, r = np.asarray(test), np.asarray(ref) | |
| assert t.shape == r.shape, f"{name}: shape {t.shape} vs {r.shape}" | |
| if r.dtype in (np.bool_, np.uint8) or t.dtype in (np.bool_, np.uint8): | |
| return {"agreement": float((t == r).mean())} | |
| tf, rf = t.astype(np.float64), r.astype(np.float64) | |
| return {"pcc": pcc(tf, rf), "max_abs": float(np.abs(tf - rf).max()), "ref_max": float(np.abs(rf).max())} | |
| def _depth_mean_setwise(test, ref) -> dict: | |
| t, r = np.asarray(test, np.float64), np.asarray(ref, np.float64) | |
| ulp = 2.0 ** (np.floor(np.log2(np.maximum(np.abs(r), 2.0 ** -14))) - 10) # fp16 spacing at the value | |
| return {"within_2ulp": float((np.abs(t - r) <= 2 * ulp).mean()), "pcc": pcc(t, r)} | |
| def _check(name: str, m: dict) -> None: | |
| if "agreement" in m: | |
| assert m["agreement"] >= AGREE_MIN, f"{name}: agreement {m['agreement']:.6f}" | |
| else: | |
| assert m["pcc"] >= PCC_MIN, f"{name}: pcc {m['pcc']:.8f}" | |
| # ------------------------------------------------------------------------------------------------- fixtures | |
| def weights(): | |
| return MeteorWeights(ONNX) | |
| def reference(weights): | |
| return MeteorReference(weights=weights, threads=THREADS) | |
| def frame(): | |
| P.need_pandaset() | |
| return load_scene_frame(SAMPLE, 0) | |
| def ort_taps(frame): | |
| oracle = OrtOracle(ONNX, taps=list(ORT_TAPS), threads=THREADS) | |
| out = oracle(frame.feed()) | |
| del oracle | |
| return out | |
| def ref_taps(reference, frame): | |
| taps = TapRegistry() | |
| reference.run_frame(frame, taps) | |
| return taps.to_dict() | |
| # ---------------------------------------------------------------------------------------------------- tests | |
| def test_graph_check(weights): | |
| ops = weights.check_graph() | |
| assert ops["Conv"] == 190 and ops["Gemm"] == 15 and ops.get("BatchNormalization", 0) == 0 | |
| assert len(weights.conv_modules()) == 190 | |
| assert weights.paint_classes() == C.PAINT_CLASSES | |
| assert abs(weights.risk_gate() - 2.2981195) < 1e-6 and abs(weights.dec_gate() - 0.0336921) < 1e-6 | |
| np.testing.assert_array_equal(lift_ground_points(), weights.lift_ground_points()[0]) # torch linspace | |
| def test_every_tap_matches_ort(ort_taps, ref_taps): | |
| rows = {} | |
| for name in list(ORT_TAPS) + list(OUTPUT_NAMES): | |
| if name == "depth_mean": | |
| rows[name] = _depth_mean_setwise(ref_taps[name], ort_taps[name]) | |
| assert rows[name]["within_2ulp"] >= 0.999 and rows[name]["pcc"] >= PCC_MIN, rows[name] | |
| continue | |
| rows[name] = _cmp(name, ref_taps[name], ort_taps[name]) | |
| _check(name, rows[name]) | |
| assert rows["lift.valid"]["agreement"] == 1.0 and rows["lift.grid"]["max_abs"] == 0.0 | |
| _report("pandaset_019_f40 vs ORT (live, all taps)", rows) | |
| print("\n".join(f" {k:22s} {v}" for k, v in rows.items())) | |
| GOLDENS = [ | |
| ("valday_f040", RESEARCH / "golden" / "valday_f040_ort.npz", | |
| RESEARCH / "golden" / "valday_f040_intermediates_fp16.npz"), | |
| ("ns0103_f0009", RESEARCH / "public_data" / "golden" / "ns0103" / "full_f0009.npz", None), | |
| ("ps090_f0020", RESEARCH / "public_data" / "golden" / "ps090" / "full_f0020.npz", None), | |
| ] | |
| # research intermediate name -> reference tap name (research/meteor/scripts/dump_intermediates.py) | |
| FP16_TAPS = {"f_fpn": "img.fpn", "depth_logits": "depth.logits", "ctx_painted": "ctx.painted", | |
| "lift_weight": "lift.weight", "lift_bev_04": "lift.bev", "raw_bev": "bev.raw", "fused_bev": "bev.fused", | |
| "lane_logits_pre_refiner": "lane.pre", "det_feat": "det.feat", "hm_pre_refiner": "det.hm_pre", | |
| "reg_pre_refiner": "det.reg_pre", "occ_feat": "occ.feat", "traj_feat256": "traj.feat", | |
| "ego_mlp": "ego.mlp", "ego_plus_attn": "ego.plus_attn", "ego_plus_sem": "ego.plus_sem", | |
| "ego_plus_kin": "ego.plus_kin", "ego_after_risk": "ego.after_risk", "ego_after_dec": "ego.after_dec"} | |
| def test_stored_ort_goldens(reference, name, path, taps_path): | |
| if not path.is_file(): | |
| pytest.skip(f"{path} not present (research goldens are not shipped)") | |
| g = np.load(path) | |
| present = np.array([bool(np.asarray(g["in_imgs"])[0, i].any()) for i in range(C.N_CAMS)]) | |
| frame = MeteorFrame(g["in_imgs"], g["in_K"], g["in_T_cam_ego"], g["in_v0"], present) | |
| want_taps = taps_path is not None and taps_path.is_file() | |
| taps = TapRegistry(include=list(FP16_TAPS.values())) if want_taps else TapRegistry(enabled=False) | |
| out = reference.run_frame(frame, taps) | |
| rows = {} | |
| for k in OUTPUT_NAMES: | |
| if k == "depth_mean": | |
| rows[k] = _depth_mean_setwise(out[k], g[k]) | |
| assert rows[k]["within_2ulp"] >= 0.999 and rows[k]["pcc"] >= PCC_MIN, (k, rows[k]) | |
| continue | |
| rows[k] = _cmp(k, out[k], g[k]) | |
| _check(f"{name}.{k}", rows[k]) | |
| if want_taps: | |
| it = np.load(taps_path) | |
| for rk, tk in FP16_TAPS.items(): | |
| rows["tap." + tk] = _cmp(tk, taps[tk], it[rk].astype(np.float32)) | |
| assert rows["tap." + tk]["pcc"] >= PCC_MIN, (tk, rows["tap." + tk]) | |
| _report(f"{name} vs stored ORT golden", rows) | |
| def test_imagenet_variant(weights, frame): | |
| """The oracle graph normalises every camera; the port also zeroes an absent camera after normalising (the | |
| trained "absent" input, SPEC section 2), so the parity check runs with every camera marked present.""" | |
| oracle = OrtOracle(ONNX, threads=THREADS, input_norm="imagenet") | |
| want = oracle(frame.feed()) | |
| del oracle | |
| ref = MeteorReference(weights=weights, threads=THREADS, cfg=C.default_config(input_norm="imagenet")) | |
| all_present = MeteorFrame(frame.imgs, frame.K, frame.T_cam_ego, frame.v0, np.ones(C.N_CAMS, bool)) | |
| out = ref.run_frame(all_present) | |
| rows = {} | |
| for k in OUTPUT_NAMES: | |
| if k == "depth_mean": | |
| rows[k] = _depth_mean_setwise(out[k], want[k]) | |
| assert rows[k]["within_2ulp"] >= 0.999, rows[k] | |
| continue | |
| rows[k] = _cmp(k, out[k], want[k]) | |
| _check(f"imagenet.{k}", rows[k]) | |
| _report("pandaset_019_f40 input_norm=imagenet vs ORT (normalisation inserted after /Div)", rows) | |
| def test_port_form_rewrites(weights, ort_taps, frame): | |
| """Every rewrite of ``reference.port_form`` reproduces the literal graph (teacher-forced from ORT).""" | |
| F = torch.nn.functional | |
| net = MeteorNet(weights, check_graph=False) | |
| T = lambda k: torch.from_numpy(np.ascontiguousarray(ort_taps[k])) | |
| rows = {} | |
| w, b, off = PF.stem_input_fold(weights, "onnx") | |
| x = torch.from_numpy(frame.imgs.reshape(C.N_CAMS, 3, C.IMG_H, C.IMG_W).astype(np.float32)) | |
| y = F.max_pool2d(F.relu(F.conv2d(x - torch.from_numpy(off).reshape(1, 3, 1, 1), torch.from_numpy(w), | |
| torch.from_numpy(b), stride=2, padding=3)), 3, 2, 1) | |
| rows["stem_input_fold"] = _cmp("stem", y, ort_taps["img.stem"]) | |
| wm, bg, bt = PF.tgate_tfuse_merged(weights) | |
| gate, t0 = PF.fused_from_merged(F.conv2d(T("bev.raw"), torch.from_numpy(wm)), bg, bt) | |
| rows["tgate_tfuse_merged.gate"] = _cmp("gate", gate, ort_taps["bev.gate"]) | |
| rows["tgate_tfuse_merged.fused"] = _cmp("fused", T("bev.raw") + net.block(t0, "tfuse3_slim/tfuse3_slim.3"), | |
| ort_taps["bev.fused"]) | |
| wd, bd = PF.merged_heads(weights)["det"] | |
| o = F.conv2d(T("det.feat"), torch.from_numpy(wd), torch.from_numpy(bd)) | |
| rows["merged_heads.hm"] = _cmp("hm", o[:, :2], ort_taps["det.hm_pre"]) | |
| rows["merged_heads.reg"] = _cmp("reg", o[:, 2:], ort_taps["det.reg_pre"]) | |
| w2, b2 = PF.merged_heads(weights)["det2d_s0"] | |
| det2d_stem = net.block(T("img.fpn"), "det2d_stem") | |
| o2 = F.conv2d(det2d_stem, torch.from_numpy(w2), torch.from_numpy(b2)) | |
| rows["merged_heads.hm2d_s0"] = _cmp("hm2d", o2[:, :10].reshape(1, 8, 10, 108, 192), ort_taps["hm2d_s0"]) | |
| wp, bp = PF.paint_conv21(weights) | |
| p = torch.softmax(net.nan_to_num(T("seg2d.logits")), dim=1) | |
| rows["paint_conv21"] = _cmp("ctx", net.conv(T("img.fpn"), "ctx") + F.conv2d(p, torch.from_numpy(wp), | |
| torch.from_numpy(bp)), | |
| ort_taps["ctx.painted"]) | |
| wl, bl = PF.traj_stem_live(weights) | |
| s = net.block(F.relu(F.conv2d(T("bev.fused"), torch.from_numpy(wl), torch.from_numpy(bl), stride=2, padding=1)), | |
| "traj_stem/traj_stem.3") | |
| rows["traj_stem_live"] = _cmp("traj.stem", s, ort_taps["traj.stem"]) | |
| geom = lift_geometry(frame.K, frame.T_cam_ego, points=weights.lift_ground_points()[0]) | |
| rows["lift_from_tables"] = _cmp("lift.bev", PF.lift_from_tables(T("ctx.painted"), T("depth.prob"), geom), | |
| ort_taps["lift.bev"]) | |
| for k, m in rows.items(): | |
| assert m["pcc"] >= 0.99999, (k, m) | |
| assert m["max_abs"] <= 1e-4 * max(1.0, m["ref_max"]), (k, m) | |
| _report("port_form rewrites (teacher-forced from ORT)", rows) | |
| def test_host_lift_geometry_bit_exact(ort_taps, frame, weights): | |
| geom = lift_geometry(frame.K, frame.T_cam_ego, points=weights.lift_ground_points()[0]) | |
| np.testing.assert_array_equal(geom.grid, ort_taps["lift.grid"][:, :, 0, :]) | |
| np.testing.assert_array_equal(geom.valid, ort_taps["lift.valid"]) | |
| st = geom.stats() | |
| assert st["pairs_total"] == 173111 and st["k_max"] == 3 # research/meteor/public_data README (ps019) | |
| _report("host lift geometry (pandaset_019)", st) | |
| def test_host_decode_matches_research(ort_taps, frame): | |
| """``host.result.build_output`` on ORT's outputs == the research decode of METEOR's C++ rules.""" | |
| scripts = RESEARCH / "public_data" / "scripts" | |
| if not (scripts / "me_public_common.py").is_file(): | |
| pytest.skip("research scripts not present") | |
| sys.path.insert(0, str(scripts)) | |
| import me_public_common as R | |
| out = {k: ort_taps[k] for k in OUTPUT_NAMES} | |
| res = build_output(out, frame, PostConfig(), None) | |
| rd, healthy = R.decode_3d(out) | |
| assert healthy == res.stationary_healthy and len(rd) == len(res.boxes3d) | |
| for a, b in zip(sorted(res.boxes3d, key=lambda z: -z.score), rd): | |
| assert (a.cls, a.stationary, a.future_mode, tuple(a.cell)) == (b["cls"], b["stationary"], b["future_mode"], | |
| tuple(b["cell"])) | |
| assert abs(a.score - b["score"]) < 1e-6 and abs(a.x - b["x"]) < 1e-4 and abs(a.y - b["y"]) < 1e-4 | |
| assert abs(a.yaw - b["yaw"]) < 1e-5 and np.abs(np.asarray(a.future) - np.asarray(b["future"])).max() < 1e-3 | |
| r2 = R.decode_2d(out) | |
| for cam in range(C.N_CAMS): | |
| assert len(res.boxes2d[cam]) == len(r2[cam]), C.CAMERAS[cam] | |
| for a, b in zip(res.boxes2d[cam], r2[cam]): | |
| assert a.cls == b["cls"] and abs(a.score - b["score"]) < 1e-6, C.CAMERAS[cam] | |
| assert max(abs(a.cx - b["cx"]), abs(a.cy - b["cy"]), abs(a.w - b["w"]), abs(a.h - b["h"])) < 1e-3 | |
| assert res.plan["mode"] == R.select_mode(out["ego"]) | |
| _report("host decode vs research decode (pandaset_019, ORT outputs)", | |
| {"boxes3d": len(rd), "boxes2d": [len(x) for x in r2], "mode": int(res.plan["mode"])}) | |