File size: 4,634 Bytes
ffbd6eb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"""
汇总 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()