Lidar_Muxa/tools/eval_new_data.py

104 lines
5.6 KiB
Python
Raw Permalink 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.

"""Ложные тревоги на участке `new_data`, которого считывание не видело.
Прокси незнакомой линии в `evaluate.py --no-memory` — пять коротких записей,
вместе чуть больше километра пути, и все они сняты в один день. `new_data` —
двадцать минут непрерывной езды другим днём. Если учить считывание на
вставках в первую половину, а ложные тревоги мерить на второй, проверка
остаётся честной при любом ответе на вопрос, та ли это линия: второй половины
модель не видела ни в каком виде.
Вторая половина идёт одним непрерывным потоком — состояние конвейера (поза,
ось, треки) переносится между кусками, как в `stream_new_data.py`. Памяти
тоннеля нет. Несколько вариантов считывания гоняются по одним и тем же
кадрам, поэтому разница между ними — только от считывания. Вариант может
нести и свои настройки конвейера через `@`: так сравниваются модели при
одинаковой строгости (`@mbon_power=2`), а не только при умолчаниях.
python tools/eval_new_data.py --shards 110: \\
--readout было=artifacts/mbon_readout.npz --readout стало=new.npz \\
--readout строже=artifacts/mbon_readout.npz@mbon_power=2 \\
--out nd_eval.json
"""
from __future__ import annotations
import argparse
import json
import time
import _bootstrap as B # noqa: F401
import _new_data as ND
import _params as PS
from flyguard.bag import Bag
from flyguard.mbon_readout import MbonReadout
from flyguard.pipeline import FlyGuard, Params
def main() -> None:
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument("--tar", default=ND.DEFAULT_TAR)
ap.add_argument("--shards", default="110:",
help="номера шардов срезом; по умолчанию вторая половина")
ap.add_argument("--per-chunk", type=int, default=5,
help="сколько шардов распаковывать за раз")
ap.add_argument("--readout", action="append", default=[],
metavar="ИМЯ=ПУТЬ[@ПОЛЕ=ЗНАЧЕНИЕ...]",
help="вариант считывания, после @ — свои поля Params; можно несколько")
ap.add_argument("--out", required=True)
PS.add_argument(ap)
args = ap.parse_args()
if not args.readout:
raise SystemExit("нужен хотя бы один --readout ИМЯ=ПУТЬ")
members = ND.pick(ND.shards(args.tar), args.shards)
pipes, stats = {}, {}
for item in args.readout:
name, _, rest = item.partition("=")
path, *own = rest.split("@")
params = Params(**PS.apply({}, args.set + own, Params))
pipes[name] = FlyGuard(params, memory=None, readout=MbonReadout.load(path))
stats[name] = dict(frames=0, path_m=0.0, back_m=0.0, alarm_frames=0,
fp_objects=0, tracks=set())
print(f"шарды {members[0][0]}–{members[-1][0]} ({len(members)} шт.), "
f"вариантов считывания {len(pipes)}")
t0 = time.time()
for part in ND.split(members, args.per_chunk):
with ND.chunk(args.tar, part) as d:
for _, pc in Bag(d).frames():
for name, fg in pipes.items():
res = fg.process(pc)
if res is None:
continue
s = stats[name]
s["frames"] += 1
ds = res.ego.ds if res.ego else 0.0
s["path_m"] += ds
s["back_m"] += max(-ds, 0.0)
objs = res.decision.objects
if objs:
s["alarm_frames"] += 1
s["fp_objects"] += len(objs)
s["tracks"].update(o.track_id for o in objs)
line = " | ".join(f"{n}: {len(s['tracks'])} треков на {s['path_m'] / 1000:.2f} км"
for n, s in stats.items())
print(f" шарды до {part[-1][0]:3d}: {line} | {(time.time() - t0) / 60:5.1f} мин",
flush=True)
rows = []
for name, s in stats.items():
km = max(s["path_m"] / 1000.0, 1e-6)
rows.append(dict(readout=name, frames=s["frames"], path_m=s["path_m"],
back_m=s["back_m"], alarm_frames=s["alarm_frames"],
alarm_rate=s["alarm_frames"] / max(s["frames"], 1),
fp_objects=s["fp_objects"], fp_tracks=len(s["tracks"]),
fp_per_km=len(s["tracks"]) / km))
print(f"{name:12s} кадров {s['frames']:6d}, путь {s['path_m'] / 1000:6.2f} км "
f"(назад {s['back_m']:.0f} м) | кадров с тревогой {rows[-1]['alarm_rate']:6.1%} | "
f"ложных треков {len(s['tracks']):4d} = {rows[-1]['fp_per_km']:5.1f} на км")
with open(args.out, "w", encoding="utf-8") as f:
json.dump(rows, f, ensure_ascii=False, indent=1)
print("сохранено:", args.out)
if __name__ == "__main__":
main()