forked from Dan4ick/Lidar_Muxa
104 lines
5.6 KiB
Python
104 lines
5.6 KiB
Python
"""Ложные тревоги на участке `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()
|