AsianPlayer/TriDrive / code /eval /gaze_rows_from_joint.py
AsianPlayer's picture
download
raw
3.96 kB
"""cwm3/eval/gaze_rows_from_joint.py — the JOINT gaze-variant run's own gaze_off chain on the warning head's TRAIN label rows -> pred_gaze_{regime}_train_labelrows.npz
in the joint run dir (the file eval/predict_u0_rows.py writes for a U0 `*_gz*` run; same keys / dtypes, taus 5 / 10 / 15 / 25), so train/train_warning_head.py
--extra-features gaze --gaze-run <joint gzfc run> reads the joint model's (fine-tuned) gaze chain instead of the U0 base's. (2026-09-13, gaze-chain appendix variant.)
Source: <run>/pred_{regime}_train_labelrows.npz (train/train_cwm3_joint.predict_split on label_rows.npz): hz_on_G / hz_off_G f16[n,25,1], z0_G, z0valid_G, valid_U, rows, uid, t.
Arithmetic = eval/write_pred_layout_joint.py's gaze block (clip hazards to [1e-6, 1-1e-6], onset_p = 1 - prod(1 - h_on[:tau]), forward marginal from z0); NaN where
valid_U is False or the anchor gaze state is undefined. No test / val row is touched; no openpilot DMS field is read.
python eval/gaze_rows_from_joint.py --run I1_all_minus_road2drv_s0_final_gzfc
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
import numpy as np
CWM3 = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(CWM3.parent / "cwm2" / "eval"))
from pred_layout import ONSET_TAUS # noqa: E402 (5, 10, 15, 25)
RUNS = CWM3 / "results" / "runs"
def convert(run, force=False):
rd = RUNS / run
assert (rd / "PRED_DONE").exists(), f"{rd}: not finished"
out_paths = []
for regime in ("manual", "engaged"):
src, dst = rd / f"pred_{regime}_train_labelrows.npz", rd / f"pred_gaze_{regime}_train_labelrows.npz"
if dst.exists() and not force:
print(f"have {dst}")
out_paths.append(dst)
continue
with np.load(src, allow_pickle=True) as z:
assert "hz_on_G" in z.files, f"{src}: no gaze chain block (not a gaze-variant joint run)"
assert [str(c) for c in z["g_chain_names"]] == ["gaze_off"]
hon = np.clip(z["hz_on_G"].astype(np.float64)[..., 0], 1e-6, 1 - 1e-6)
hoff = np.clip(z["hz_off_G"].astype(np.float64)[..., 0], 1e-6, 1 - 1e-6)
z0 = z["z0_G"].astype(np.float64)[:, 0]
z0v = z["z0valid_G"].astype(bool)[:, 0] & z["valid_U"].astype(bool)
rows, uid, t, best = z["rows"].astype(np.int64), z["uid"], z["t"], str(z["best_ckpt"])
onset = np.stack([1 - np.prod(1 - hon[:, :tau], 1) for tau in ONSET_TAUS], 1)
pi = np.empty_like(hon)
prev = z0.copy()
for k in range(hon.shape[1]):
prev = prev * (1 - hoff[:, k]) + (1 - prev) * hon[:, k]
pi[:, k] = prev
bad = ~z0v
for arr in (onset, pi, hon, hoff):
arr[bad] = np.nan
z0 = z0.copy()
z0[bad] = np.nan
np.savez_compressed(dst, rows=rows, uid=uid, t=t, gaze_off_onset_p=onset.astype(np.float32), gaze_off_pi=pi.astype(np.float32), gaze_off_h_on=hon.astype(np.float32),
gaze_off_h_off=hoff.astype(np.float32), gaze_off_z0=z0.astype(np.float32), gaze_off_z0valid=z0v, gaze_off_taus=np.array(ONSET_TAUS),
best_ckpt=np.array(best), run=np.array(run), source_rows=np.array(str(rd / "label_rows.npz")),
derived_from=np.array(json.dumps({"file": src.name, "writer": "eval/gaze_rows_from_joint.py", "note": "joint model's own gaze_off chain (fine-tuned), not the U0 base's"})))
print(f"wrote {dst}: n={len(rows)} valid={int(z0v.sum())} onset_p@3s mean={np.nanmean(onset[:, 2]):.4f}")
out_paths.append(dst)
return out_paths
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--run", required=True, nargs="+")
ap.add_argument("--force", action="store_true")
a = ap.parse_args()
for r in a.run:
convert(r, a.force)
if __name__ == "__main__":
main()

Xet Storage Details

Size:
3.96 kB
·
Xet hash:
d109e551376d2ac13747123579bb2b7f20746f3ef2b7efda8b5ca7440ac1ecac

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.