Brainrot_Muxa/tools/compare_benchmark.py

83 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Парное сравнение двух прогонов полигона на одних и тех же вставках.
Полигон шумит сильнее, чем меняет его большинство правок: две реализации
случайности при одинаковых настройках расходятся на P@150 на 0.07, на P@100
у ящика — на 0.11 (EXPERIMENTS п. 16.1). Поэтому сравнивать итоговые таблицы
двух прогонов нельзя.
Но у каждого сценария свой генератор (`make_benchmark.scenario_rng`), и от
решений конвейера он не зависит: при другой настройке на вход идут те же
кадры с теми же вставками, до луча. Значит, разница двух прогонов — только
от настройки, и её видно по отдельным наблюдениям: сколько было 0 и стало 1
и наоборот. Перевороты в одну сторону — настоящий эффект, даже когда он
меньше межзернового шума; поровну в обе стороны — шум.
python tools/compare_benchmark.py artifacts/benchmark.json new.json
python tools/compare_benchmark.py a.json b.json --objects человек_лежа,ящик
"""
from __future__ import annotations
import argparse
import json
import numpy as np
MIN_VISIBLE_RAYS = 2 # как в plot_benchmark: меньше — предмет не освещён
def load(path: str) -> dict:
with open(path, encoding="utf-8") as f:
return {(r["bag"], r["obj"], r["lateral"]): r for r in json.load(f)}
def main() -> None:
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument("before", help="прогон «было» (json из make_benchmark)")
ap.add_argument("after", help="прогон «стало»")
ap.add_argument("--objects", default="",
help="через запятую; пусто — все предметы")
ap.add_argument("--edges", default="0,15,40,90,130,170,230",
help="границы полос дальности, м")
args = ap.parse_args()
a, b = load(args.before), load(args.after)
if set(a) != set(b):
raise SystemExit("разный состав сценариев — прогоны не парные")
edges = [float(x) for x in args.edges.split(",")]
objs = ([o for o in args.objects.split(",") if o] if args.objects
else sorted({k[1] for k in a}))
print(f"{'предмет':14s}{'полоса':>12}{'набл.':>7}{'было':>7}{'стало':>7}"
f"{'0→1':>6}{'1→0':>6}")
total_up = total_down = 0
for obj in objs:
obj_up = obj_down = 0
for lo, hi in zip(edges[:-1], edges[1:]):
n = ha = hb = up = down = 0
for k, ra in a.items():
if k[1] != obj:
continue
rb = b[k]
da = np.asarray(ra["d"])
if da.shape != np.shape(rb["d"]) or not np.allclose(da, rb["d"]):
raise SystemExit(f"вход разошёлся в {k}: прогоны не парные")
m = (da >= lo) & (da < hi) & (np.asarray(ra["rays"]) >= MIN_VISIBLE_RAYS)
x, y = np.asarray(ra["hit"])[m], np.asarray(rb["hit"])[m]
n += int(m.sum())
ha += int(x.sum())
hb += int(y.sum())
up += int(((x == 0) & (y == 1)).sum())
down += int(((x == 1) & (y == 0)).sum())
obj_up += up
obj_down += down
if n >= 20:
print(f"{obj:14s}{f'{lo:.0f}–{hi:.0f} м':>12}{n:7d}{ha / n:7.2f}"
f"{hb / n:7.2f}{up:6d}{down:6d}")
print(f"{obj:14s}{'всего':>12}{'':21s}{obj_up:6d}{obj_down:6d}")
total_up += obj_up
total_down += obj_down
print(f"\nвсе предметы: 0→1 {total_up}, 1→0 {total_down}")
if __name__ == "__main__":
main()