AsianPlayer/TriDrive / code /eval /report_final_face.py
AsianPlayer's picture
download
raw
22.2 kB
"""cwm3/eval/report_final_face.py — results/tables/stage_final_face.md: R2 WP4 batch 1 **F3** (face channels into the driver GRU; pre-registration docs/decisions.md
2026-09-16T06:46:35Z; plan <local-notes>/plans/elegant-dazzling-stallman.md) from results/paired_compare.csv. Composes eval/report_joint.py blocks (load / render /
verdict / claim / provenance); nothing is recomputed here; every number comes from the CSV rows written by eval/run_joint_evals_final_face.sh.
python eval/report_final_face.py [--seeds 0,1,2] [--out results/tables/stage_final_face.md]
Blocks (tags): finalcv_s<k>_allminusface_vs_allminus (a-val) variant vs the FROZEN main on the VALIDATION split — the ADOPTION decision (rev-2 discipline)
finalc_s<k>_allminusface_vs_allminus (a) the same on the test split — confirmation; driver cells with Δ [CI] and the acceptable-degradation margins
finalc_s<k>_allminusface_vs_indepface (b) interaction effect on the face bases; finalc_s<k>_indepface_vs_indep the U-base swap alone
finalc_s<k>_allminusface_vs_allminusgzfc face INPUT alone vs face input + gaze-chain LOSS (the `_gzfc` appendix variant)
finalcm_* masked protocol; finalc/finalcm_*_vs_k0 B1 on the variant; finalP_* P cells; finalcv_*_vs_{indepface,allminusgzfc} (val, descriptive)
PRE-REGISTERED READING (written before any face run finished): acceptable degradation = onset PR-AUC −0.005 / hazard NLL +0.01 nats per cell (mean Δ over seeds AND
no seed's CI entirely beyond the margin); "no significant drop" is NOT non-inferiority. Adoption candidate iff on VALIDATION no own onset cell (report_joint.OWN,
both regimes) is WORSE or breaks its margin AND drv_onset|head_turn_onset|3s BEATS in >= 1 regime; the test block is the confirmation (the new held-out set, WP5,
confirms the frozen combination once). The F3 QUESTION (is engaged head_turn — 0.258 frozen vs k0 0.238 — limited by missing gaze observation?) is answered by
(i) face-alone vs frozen main on engaged head_turn_onset and (ii) face-alone vs gzfc: BEATS/NOT_WORSE in (ii) with a BEATS in (i) -> the observation, not the gaze-chain
loss, carries the gzfc gain; WORSE in (ii) with no BEATS in (i) -> the gain needs the gaze-chain supervision. Also writes results/tables/stage_final_face_decision.json.
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
import numpy as np
import pandas as pd
CWM3 = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(CWM3 / "eval"))
import report_joint as RJ # noqa: E402
HT = "drv_onset|head_turn_onset|3s"
EV = ("hand_leave", "hand_return", "head_turn_onset")
DRV = [f"drv_onset|{e}|3s" for e in EV]
NLL_DRV = [f"hazard_nll|{e}" for e in EV]
VEH = [f"veh_onset|{e}|3s" for e in ("gas_on", "brake_on", "steer_phase_on")]
NLL_VEH = [f"hazard_nll|{e}" for e in ("gas", "brake", "steer_phase")]
MARGIN_ONSET, MARGIN_NLL = -0.005, 0.010
FROZEN_ENGAGED_HT, K0_ENGAGED_HT = 0.258, 0.238 # the F3 question as briefed (stage_final.md: 0.2636 / 0.2554 / 0.2558; k0 rows finalc_*_vs_k0)
def block(stage, a, b, claim, title, seeds):
df = RJ.load(stage, a, b, seeds)
if not len(df):
return df, [f"### {title}: A = {a}, B = {b} — no rows yet (tags `{stage}_s<k>_{a}_vs_{b}`)", ""], {}, ("NO ROWS", [], [], [])
body, verdicts = RJ.render(df, sorted(df.seed.unique()), a, b, title)
return df, body, verdicts, RJ.claim(verdicts, claim)
def ms(v):
v = [float(x) for x in v if str(x) not in ("", "nan")]
return "—" if not v else (f"{np.mean(v):.3f} ± {np.std(v, ddof=1):.3f}" if len(v) > 1 else f"{v[0]:.3f}")
def fmt(ks):
return [f"{r}|{c}" + (f"|{m}" if m != "pr_auc" else "") for (r, c, m) in ks] or "none"
def margin_ok(g, lower_better):
"""acceptable-degradation check of one cell: mean Δ within the margin AND no seed CI entirely beyond it (Δ = A − B, A = variant)."""
d = g.delta.astype(float).to_numpy()
lo, hi = g.delta_ci_lo.astype(float).to_numpy(), g.delta_ci_hi.astype(float).to_numpy()
if lower_better:
return bool(np.nanmean(d) <= MARGIN_NLL and not np.any(lo > MARGIN_NLL)), float(np.nanmean(d))
return bool(np.nanmean(d) >= MARGIN_ONSET and not np.any(hi < MARGIN_ONSET)), float(np.nanmean(d))
def margin_table(df, verdicts, title, cells_onset, cells_nll):
"""driver cells with A / B per seed, Δ [CI] per seed, mean Δ, verdict and the margin check."""
lines = [f"### {title}", "", "| regime | cell | metric | A (variant) per seed | B per seed | Δ per seed [CI] | mean Δ ± sd | verdict | within margin |", "|---|---|---|---|---|---|---|---|---|"]
checks = {}
for r in ("manual", "engaged"):
for cell, metric, lb, margin in [(c, "pr_auc", False, MARGIN_ONSET) for c in cells_onset] + [(c, "nll", True, MARGIN_NLL) for c in cells_nll]:
g = df[(df.regime == r) & (df.cell == cell) & (df.metric == metric)].sort_values("seed")
if not len(g):
lines.append(f"| {r} | {cell.replace('|', '/')} | {metric} | — | — | no rows | | | |")
continue
v = verdicts.get((r, cell, metric), {"verdict": "—"})
ok, md = margin_ok(g, lb)
checks[(r, cell, metric)] = {"ok": ok, "mean_delta": md, "verdict": v["verdict"]}
A = " / ".join(f"{float(x):.4f}" for x in g.value_a)
B = " / ".join(f"{float(x):.4f}" for x in g.value_b)
D = " / ".join(f"{float(x.delta):+.4f} [{float(x.delta_ci_lo):+.4f},{float(x.delta_ci_hi):+.4f}]" for x in g.itertuples())
d = g.delta.astype(float).to_numpy()
lines.append(f"| {r} | {cell.replace('|', '/')} | {metric}{' (lower better)' if lb else ''} | {A} | {B} | {D} | {md:+.4f} ± {d.std(ddof=1) if len(d) > 1 else 0:.4f} | {v['verdict']} | "
f"{'yes' if ok else '**NO**'} (margin {margin:+.3f}) |")
return lines + [""], checks
def own_status(verdicts, checks):
"""-> (worse own onset cells, own onset cells breaking the margin, head_turn BEATS regimes, insufficient?)"""
own = {k: v for k, v in verdicts.items() if k[1] in RJ.OWN and k[2] == "pr_auc"}
worse = [k for k, v in own.items() if v["verdict"] == "WORSE"]
broke = [k for k, c in checks.items() if k[2] == "pr_auc" and k[1] in RJ.OWN and not c["ok"]]
ht = {r: verdicts.get((r, HT, "pr_auc"), {}).get("verdict", "NO ROWS") for r in ("manual", "engaged")}
insuff = any(v["verdict"] == "INSUFFICIENT" for v in own.values()) or len(own) < 6
return worse, broke, [r for r, v in ht.items() if v == "BEATS"], ht, insuff
def b1_lines(seeds, dfs):
out, js = [], {}
for proto, stage in (("all rows", "finalc"), ("suspect routes masked", "finalcm")):
out += [f"### B1 on the variant — driver onset PR-AUC@3s (v2 causal targets) vs the k0 heuristic / persistence, protocol: {proto}", "",
"| variant | regime | event | model | k0 | persistence (base rate) | Δ per seed [CI] | verdict |", "|---|---|---|---|---|---|---|---|"]
for var in ("indepface", "allminusface"):
if proto != "all rows" and var == "indepface":
continue
df = RJ.load(stage, var, "k0", seeds)
dfs.append(df)
if not len(df):
out.append(f"| {var} | — | — | no rows yet (`{stage}_s<k>_{var}_vs_k0`) | | | | |")
continue
verd = {}
for reg in ("manual", "engaged"):
for ev in EV:
cell = f"drv_onset|{ev}|3s"
g = df[(df.regime == reg) & (df.cell == cell) & (df.metric == "pr_auc")].sort_values("seed")
base = df[(df.regime == reg) & (df.cell == cell) & (df.metric == "base_rate")]
if not len(g):
continue
res = RJ.verdict(g)
verd[(reg, cell, "pr_auc")] = res
cells = " / ".join(f"{float(r.delta):+.3f} [{float(r.delta_ci_lo):+.3f},{float(r.delta_ci_hi):+.3f}]" for r in g.itertuples())
out.append(f"| {var} | {reg} | {ev} | {ms(g.value_a)} | {ms(g.value_b)} | {ms(base.value_a) if len(base) else '—'} | {cells} | {res['verdict']} |")
stb, _, _, _ = RJ.claim(verd, "B1")
n_beats = sum(v["verdict"] == "BEATS" for v in verd.values())
js[f"{var}|{proto}"] = {"verdict": stb, "beats": n_beats, "cells": {f"{r}|{c}": v["verdict"] for (r, c, _), v in verd.items()},
"engaged_head_turn": {"model": ms(df[(df.regime == "engaged") & (df.cell == HT) & (df.metric == "pr_auc")].value_a),
"k0": ms(df[(df.regime == "engaged") & (df.cell == HT) & (df.metric == "pr_auc")].value_b)}}
out.append(f"| {var} | **B1 ({proto})** | | | | | {n_beats}/6 cells BEATS k0; rule (hand_leave AND head_turn_onset BEATS in both regimes) | **{stb}** |")
out.append("")
return out, js
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--seeds", default="0,1,2")
ap.add_argument("--out", default=str(CWM3 / "results" / "tables" / "stage_final_face.md"))
a = ap.parse_args()
seeds = [int(s) for s in a.seeds.split(",")]
dfs = []
dV, bodyV, vV, (stV, worseV, bcV, boV) = block("finalcv", "allminusface", "allminus", "B2", "(a-val) variant vs the FROZEN main — VALIDATION split (the adoption decision)", seeds)
dA, bodyA, vA, (stA, worseA, bcA, boA) = block("finalc", "allminusface", "allminus", "B2", "(a) variant vs the FROZEN main — test split (confirmation), v2 causal kin targets", seeds)
dB, bodyB, vB, (stB, worseB, bcB, boB) = block("finalc", "allminusface", "indepface", "B2", "(b) interaction effect on the face bases: all_minus_road2drv_face vs indep_face (B2-style)", seeds)
dC, bodyC, vC, (stC, worseC, bcC, boC) = block("finalc", "indepface", "indep", "B2", "U-base swap alone: indep_face vs indep (assembled bases, no training)", seeds)
dG, bodyG, vG, (stG, worseG, bcG, boG) = block("finalc", "allminusface", "allminusgzfc", "B2", "face INPUT alone vs face input + gaze-chain LOSS: all_minus_face vs all_minus_gzfc (test)", seeds)
dGv, bodyGv, vGv, _ = block("finalcv", "allminusface", "allminusgzfc", "B2", "face alone vs gzfc — VALIDATION split", seeds)
dBv, bodyBv, vBv, _ = block("finalcv", "allminusface", "indepface", "B2", "all_minus_face vs indep_face — VALIDATION split", seeds)
dAm, bodyAm, vAm, (stAm, worseAm, bcAm, boAm) = block("finalcm", "allminusface", "allminus", "B2", "Masked protocol (64 v2 suspect routes censored): variant vs FROZEN main (test)", seeds)
dBm, bodyBm, vBm, _ = block("finalcm", "allminusface", "indepface", "B2", "Masked protocol: all_minus_face vs indep_face", seeds)
dP1, bodyP1, vP1, _ = block("finalP", "allminusface", "allminus", "B3", "P cells (road-pressure onset PR-AUC@3s, eval/pressure_eval.py): variant vs FROZEN main", seeds)
dP2, bodyP2, vP2, _ = block("finalP", "allminusface", "indepface", "B3", "P cells: all_minus_face vs indep_face", seeds)
dfs += [dV, dA, dB, dC, dG, dGv, dBv, dAm, dBm, dP1, dP2]
mV, chV = margin_table(dV, vV, "Driver cells with the acceptable-degradation margins — VALIDATION (a-val)", DRV, NLL_DRV) if len(dV) else (["(no validation rows yet)", ""], {})
mA, chA = margin_table(dA, vA, "Driver cells with the acceptable-degradation margins — TEST (a)", DRV, NLL_DRV) if len(dA) else (["(no test rows yet)", ""], {})
mVv, chVv = margin_table(dV, vV, "Vehicle own cells with the margins — VALIDATION (a-val)", VEH, NLL_VEH) if len(dV) else ([], {})
mAv, chAv = margin_table(dA, vA, "Vehicle own cells with the margins — TEST (a)", VEH, NLL_VEH) if len(dA) else ([], {})
mV, mA = mV + mVv, mA + mAv
# every own onset cell on validation gets the margin check too (vehicle / road cells)
chV_all = {}
if len(dV):
for (r, c, m), v in vV.items():
if c in RJ.OWN and m == "pr_auc":
g = dV[(dV.regime == r) & (dV.cell == c) & (dV.metric == m)]
ok, md = margin_ok(g, False)
chV_all[(r, c, m)] = {"ok": ok, "mean_delta": md, "verdict": v["verdict"]}
b1, b1_json = b1_lines(seeds, dfs)
# ---- decision (validation) + confirmation (test)
worseV_own, brokeV, htV_beats, htV, insuffV = own_status(vV, chV_all)
n_seeds_v = int(dV.seed.nunique()) if len(dV) else 0
if not len(dV):
decision, dtxt = "NOT DECIDABLE", "no finalcv_s<k>_allminusface_vs_allminus rows yet (validation split)"
elif n_seeds_v < 3 or insuffV:
decision, dtxt = "INSUFFICIENT", f"{n_seeds_v}/3 seeds paired on validation"
elif worseV_own or brokeV:
decision, dtxt = "REJECTED (validation): degradation", f"own onset cells WORSE {fmt(worseV_own)}; margin broken on {fmt(brokeV)}"
elif htV_beats:
decision, dtxt = "ADOPT-CANDIDATE (validation): face input", f"no own onset cell WORSE / beyond margin on validation; head_turn_onset BEATS in {htV_beats}"
else:
decision, dtxt = "NEGATIVE (validation): no head_turn gain", f"no own onset cell WORSE / beyond margin on validation, but head_turn_onset verdicts manual {htV['manual']} / engaged {htV['engaged']}"
worseA_own, brokeA, htA_beats, htA, insuffA = own_status(vA, {k: v for k, v in chA.items()} | {k: {"ok": margin_ok(dA[(dA.regime == k[0]) & (dA.cell == k[1]) & (dA.metric == k[2])], False)[0]} for k in vA if k[1] in RJ.OWN and k[2] == "pr_auc"}) if len(dA) else ([], [], [], {"manual": "NO ROWS", "engaged": "NO ROWS"}, True)
conf = ("no test rows yet" if not len(dA) else f"test: own onset WORSE {fmt(worseA_own)}; margin broken {fmt(brokeA)}; head_turn_onset manual {htA['manual']} / engaged {htA['engaged']}")
# ---- the F3 question
g_ht_e = dA[(dA.regime == "engaged") & (dA.cell == HT) & (dA.metric == "pr_auc")].sort_values("seed") if len(dA) else pd.DataFrame()
face_vs_gzfc_ht = {r: vG.get((r, HT, "pr_auc"), {}).get("verdict", "NO ROWS") for r in ("manual", "engaged")}
face_vs_gzfc_ht_v = {r: vGv.get((r, HT, "pr_auc"), {}).get("verdict", "NO ROWS") for r in ("manual", "engaged")}
if not len(dA) or not len(dG):
answer = "not answerable yet (need finalc_*_allminusface_vs_allminus and _vs_allminusgzfc rows)"
elif htA["engaged"] == "BEATS" and face_vs_gzfc_ht["engaged"] in ("NOT_WORSE", "BEATS", "INCONCLUSIVE"):
answer = "YES — the face-landmark channels alone lift engaged head_turn_onset over the frozen main and are not worse than gzfc: the engaged head-turn cell was limited by missing gaze observation, not by the gaze-chain loss"
elif htA["engaged"] != "BEATS" and face_vs_gzfc_ht["engaged"] == "WORSE":
answer = "NO — the face channels alone do not lift engaged head_turn_onset and are WORSE than gzfc: the gzfc gain needs the gaze-chain supervision (auxiliary loss), not just the observation"
elif htA["engaged"] == "BEATS" and face_vs_gzfc_ht["engaged"] == "WORSE":
answer = "PARTLY — the face observation alone helps engaged head_turn_onset but less than face + gaze chain: observation and gaze-chain supervision both contribute"
else:
answer = f"MIXED / INCONCLUSIVE — engaged head_turn_onset face vs frozen {htA['engaged']}, face vs gzfc {face_vs_gzfc_ht['engaged']}"
allrows = pd.concat([d for d in dfs if len(d)], ignore_index=True) if any(len(d) for d in dfs) else pd.DataFrame(columns=["a", "b", "regime", "run_stamp"])
prov, stale = RJ.provenance(allrows) if len(allrows) else ([], [])
void = f" — **VOID: stale rows for {stale}**" if stale else ""
eng_vals = (" / ".join(f"{float(x):.4f}" for x in g_ht_e.value_a) + f" (frozen main {' / '.join(f'{float(x):.4f}' for x in g_ht_e.value_b)})") if len(g_ht_e) else "—"
L = ["# Stage FINAL — R2 WP4 batch 1 **F3**: face channels into the driver GRU (`U0_kin_can_noK_face_s<k>_kcv2_clip8_ln` = FINAL U recipe + `u_face`, NO gaze chain), 3 seeds, both regimes", "",
"Runs `I1_{indep,all_minus_road2drv}_s<k>_final_face` = the FINAL command line with only the U base swapped (V0 `can4s_stats2`, E0 `pooled_P_v2`, seeds, recipe and selection "
"unchanged; driver inputs = 18 kinematics / CAN channels + the 9 causal `lm_*` face-landmark channels + the face valid bit per step). The frozen main `I1_all_minus_road2drv_s<k>_final`, "
"`I1_indep_s<k>_final` and the gaze-chain appendix variant `I1_all_minus_road2drv_s<k>_final_gzfc` are read as B layouts only. Paired device-cluster bootstrap on identical rows "
"(eval/paired_compare_joint.py, n_boot 1000; verdict = kill_checks.beats: ≥ 2/3 seeds CI excl. 0, same sign, |mean Δ| > seed sd); driver populations from the v2 causal kin targets; "
"`finalcv_*` = VALIDATION split (adoption), `finalc_*` = test (confirmation), `finalcm_*` masked protocol, `finalP_*` P cells. Identity of the assembled `indep_face` with its bases: "
"`results/tables/identity_final_face.md`. Every number comes from `results/paired_compare.csv`.", "",
f"**Pre-registered reading (docs/decisions.md 2026-09-16T06:46:35Z; this renderer written before the face runs finished):** acceptable degradation onset PR-AUC {MARGIN_ONSET:+.3f} / hazard NLL "
f"{MARGIN_NLL:+.3f} nats (mean Δ within the margin and no seed CI entirely beyond it; 'no significant drop' ≠ non-inferior). Adoption candidate iff on VALIDATION no own onset cell is WORSE or "
"breaks its margin AND head_turn_onset BEATS in ≥ 1 regime; test = confirmation; the held-out set (WP5) confirms the frozen combination once. The variant never replaces the headline by itself.", "",
f"## DECISION (validation): **{decision}**{void}", "", f"- {dtxt}", f"- confirmation on test: {conf}",
f"- validation head_turn_onset verdicts: manual {htV['manual']} / engaged {htV['engaged']}; own onset cells beyond margin (val): {fmt(brokeV)}", "",
"## F3 QUESTION — is engaged head_turn_onset (frozen 0.258 vs k0 0.238) limited by missing gaze observation?", "",
f"- **{answer}**", f"- engaged head_turn_onset PR-AUC@3s, variant per seed (test): {eng_vals}; briefed reference frozen {FROZEN_ENGAGED_HT:.3f} / k0 {K0_ENGAGED_HT:.3f}",
f"- face alone vs gzfc on head_turn_onset: test manual {face_vs_gzfc_ht['manual']} / engaged {face_vs_gzfc_ht['engaged']}; validation manual {face_vs_gzfc_ht_v['manual']} / engaged {face_vs_gzfc_ht_v['engaged']}",
f"- B1 (variant vs k0) engaged head_turn: " + "; ".join(f"{k}: model {v['engaged_head_turn']['model']} vs k0 {v['engaged_head_turn']['k0']} ({v['cells'].get('engaged|' + HT, '—')})" for k, v in b1_json.items()) if b1_json else "- B1 rows pending", "",
"## Provenance of the A / B layouts (guard 2): layout mtime, source hash, model_id / code hash, completeness; rows older than the layout are STALE", "",
"| run | regime | layout mtime (UTC) | source sha256 | model_id / code | status |", "|---|---|---|---|---|---|", *prov, "",
*([f"**STALE ROWS DETECTED for {stale} — every verdict is VOID; recompute (eval/run_joint_evals_final_face.sh).**", ""] if stale else []),
"## 1. (a-val) Variant vs the FROZEN main — VALIDATION split (adoption decision)", ""] + mV + bodyV + ["", f"B2-style status (a-val): **{stV}** — own WORSE {fmt(worseV)}; own BEATS {fmt(boV)}; cross BEATS {fmt(bcV)}", "",
"## 2. (a) Variant vs the FROZEN main — TEST split (confirmation)", ""] + mA + bodyA + ["", f"B2-style status (a): **{stA}** — own WORSE {fmt(worseA)}; own BEATS {fmt(boA)}; cross BEATS {fmt(bcA)}", "",
"## 3. Face input alone vs face input + gaze chain (gzfc)", ""] + bodyG + [""] + bodyGv + ["",
"## 4. Attribution — the U-base swap alone (indep_face vs indep, no training)", ""] + bodyC + ["", f"B2-style status: **{stC}** — own WORSE {fmt(worseC)}; own BEATS {fmt(boC)}", "",
"## 5. (b) Interaction effect on the face bases", ""] + bodyB + [""] + bodyBv + ["", f"B2-style verdict (b): **{stB}** — own WORSE {fmt(worseB)}; cross BEATS {fmt(bcB)}; own BEATS {fmt(boB)}", "",
"## 6. Masked protocol (sensitivity to the 64 suspect routes)", ""] + bodyAm + [""] + bodyBm + ["",
"## 7. P cells (road-pressure chains, detached head)", ""] + bodyP1 + [""] + bodyP2 + ["",
"## 8. B1 on the variant (driver cells vs k0 / persistence)", ""] + b1
out = Path(a.out); out.parent.mkdir(parents=True, exist_ok=True)
out.write_text("\n".join(L) + "\n")
dec = {"decision": decision, "detail": dtxt, "confirmation_test": conf, "f3_answer": answer, "head_turn_val": htV, "head_turn_test": htA, "face_vs_gzfc_head_turn_test": face_vs_gzfc_ht,
"face_vs_gzfc_head_turn_val": face_vs_gzfc_ht_v, "engaged_head_turn_variant_test": [float(x) for x in g_ht_e.value_a] if len(g_ht_e) else [],
"engaged_head_turn_frozen_test": [float(x) for x in g_ht_e.value_b] if len(g_ht_e) else [],
"margins": {"onset": MARGIN_ONSET, "nll": MARGIN_NLL}, "val_margin_checks": {f"{r}|{c}|{m}": v for (r, c, m), v in chV_all.items()},
"val_driver_checks": {f"{r}|{c}|{m}": v for (r, c, m), v in chV.items()}, "test_driver_checks": {f"{r}|{c}|{m}": v for (r, c, m), v in chA.items()},
"val_vehicle_checks": {f"{r}|{c}|{m}": v for (r, c, m), v in chVv.items()}, "test_vehicle_checks": {f"{r}|{c}|{m}": v for (r, c, m), v in chAv.items()},
"worse_own_val": fmt(worseV_own), "broke_margin_val": fmt(brokeV), "worse_own_test": fmt(worseA_own), "broke_margin_test": fmt(brokeA),
"B2_style_a_val": stV, "B2_style_a_test": stA, "B2_style_b": stB, "B1": b1_json, "stale": stale, "seeds": seeds, "n_seeds_paired_val": n_seeds_v}
(out.parent / "stage_final_face_decision.json").write_text(json.dumps(dec, indent=1, default=str))
print("\n".join(L[:14]))
print(f"\nVERDICT {decision}: {dtxt}\nF3: {answer}\nwritten {out} and {out.parent / 'stage_final_face_decision.json'}")
if __name__ == "__main__":
main()

Xet Storage Details

Size:
22.2 kB
·
Xet hash:
3e135d30d0e1ec93a405900ad81bfd5c1e4622056108c73e2a7289f55620ac7b

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