py-yolo-traffic-obstacle / aggregate.py
Pengzhen23's picture
Initial upload: YOLOv8m+aug best weight + training configs + reports
ffbd6eb verified
Raw
History Blame Contribute Delete
4.63 kB
"""
汇总 6 组 run 的 summary.json,生成两张论文对比表(Markdown 格式):
表 1 扩散对比: A(v8m 无扩散) vs B(v8m 含扩散)
表 2 模型对比: C(v8s) / B(v8m) / D(v8l) 含扩散下 mAP / P / R / FPS
表 3 LR 调参: B(1e-3) / E(5e-4) / F(1e-4)
也导出 CSV 方便论文图表用。
"""
from __future__ import annotations
import argparse
import csv
import json
from pathlib import Path
CLASSES = ["person", "car", "truck", "bus", "bicycle", "motorcycle", "traffic_cone"]
def load_summaries(runs_dir: Path) -> dict:
out = {}
for d in sorted(runs_dir.iterdir()):
p = d / "summary.json"
if p.exists():
out[d.name] = json.loads(p.read_text(encoding="utf-8"))
return out
def md_table(rows: list, headers: list) -> str:
lines = ["| " + " | ".join(headers) + " |"]
lines.append("|" + "|".join(["---"] * len(headers)) + "|")
for r in rows:
lines.append("| " + " | ".join(str(c) for c in r) + " |")
return "\n".join(lines)
def fmt(x, d=3):
if isinstance(x, (int, float)):
return f"{x:.{d}f}"
return str(x)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--runs-dir", required=True, type=Path)
ap.add_argument("--out", required=True, type=Path)
args = ap.parse_args()
sums = load_summaries(args.runs_dir)
print(f"发现 {len(sums)} 个 run")
out_md = ["# feat-005 训练结果汇总", ""]
# 表 1: 扩散对比
if "run_A_v8m_noaug" in sums and "run_B_v8m_aug" in sums:
A, B = sums["run_A_v8m_noaug"], sums["run_B_v8m_aug"]
rows = [
["v8m 无扩散", fmt(A["test_mAP50"]), fmt(A["test_mAP50_95"]),
fmt(A["test_precision"]), fmt(A["test_recall"])],
["v8m 含扩散", fmt(B["test_mAP50"]), fmt(B["test_mAP50_95"]),
fmt(B["test_precision"]), fmt(B["test_recall"])],
["Δ(含-无)", fmt(B["test_mAP50"] - A["test_mAP50"]),
fmt(B["test_mAP50_95"] - A["test_mAP50_95"]),
fmt(B["test_precision"] - A["test_precision"]),
fmt(B["test_recall"] - A["test_recall"])],
]
out_md += ["## 表 1. 扩散模型扩增效果(YOLOv8m)", "",
md_table(rows, ["条件", "mAP@50", "mAP@50-95", "Precision", "Recall"]), ""]
# 表 2: 模型对比(含扩散)
keys_size = [("run_C_v8s_aug", "v8s"), ("run_B_v8m_aug", "v8m"), ("run_D_v8l_aug", "v8l")]
rows = []
for k, label in keys_size:
if k in sums:
s = sums[k]
rows.append([label, fmt(s["test_mAP50"]), fmt(s["test_mAP50_95"]),
fmt(s["test_precision"]), fmt(s["test_recall"]),
fmt(s["test_fps_single"], 1)])
if rows:
out_md += ["## 表 2. YOLOv8 不同尺寸(均用扩散数据)", "",
md_table(rows, ["Model", "mAP@50", "mAP@50-95",
"Precision", "Recall", "FPS"]), ""]
# 表 3: LR 调参
keys_lr = [("run_B_v8m_aug", "1e-3"), ("run_E_v8m_aug_lr5e-4", "5e-4"),
("run_F_v8m_aug_lr1e-4", "1e-4")]
rows = []
for k, lr in keys_lr:
if k in sums:
s = sums[k]
rows.append([lr, fmt(s["test_mAP50"]), fmt(s["test_mAP50_95"]),
fmt(s["test_precision"]), fmt(s["test_recall"])])
if rows:
out_md += ["## 表 3. 学习率敏感性(YOLOv8m 含扩散)", "",
md_table(rows, ["lr0", "mAP@50", "mAP@50-95", "Precision", "Recall"]), ""]
# 各类别 AP
out_md += ["## 附录: 各类别 AP@50(v8m 含扩散)", ""]
if "run_B_v8m_aug" in sums:
B = sums["run_B_v8m_aug"]
rows = []
for i, cn in enumerate(CLASSES):
rows.append([i, cn, fmt(B["per_class_AP50"].get(str(i), 0.0))])
out_md += [md_table(rows, ["id", "class", "AP@50"]), ""]
args.out.write_text("\n".join(out_md), encoding="utf-8")
print(f"汇总报告 → {args.out}")
# CSV
csv_out = args.out.with_suffix(".csv")
with open(csv_out, "w", newline="", encoding="utf-8") as f:
w = csv.writer(f)
w.writerow(["run", "model", "lr", "train_time_min",
"mAP50", "mAP50_95", "P", "R", "FPS"])
for k, s in sums.items():
w.writerow([k, s["model"], s["lr"], s["train_time_min"],
s["test_mAP50"], s["test_mAP50_95"],
s["test_precision"], s["test_recall"],
s["test_fps_single"]])
print(f"CSV → {csv_out}")
if __name__ == "__main__":
main()