Skip to content

feat(core/desktop): 单层参数自动调优循环(识别 → 手动框 GT → 评估 → 调参 → 再识别) #89

Description

@loootte
## 背景

已实现:**按层编辑模式下手动调节的框作为 GT**,用于量化评价该层识别结果。

当前能力可概括为:

```text
识别 → 手动编辑/校正框(作 GT)→ 评估指标

仍缺闭环中的自动环节:根据「识别框 vs 手动 GT」的误差,自动搜索本层参数,写回配置并再跑识别,形成可重复的单层拟合循环。

目标工作流:

识别 → 手动编辑标注(GT)→ 评估 → 自动调优参数 → 再识别 → (可选)再标注 …

本 Issue 只做 单层 参数拟合调优循环(一次只锁一层,如仅 L3 或仅 L4),不做跨层联合大搜索。


目标

  1. 以当前工程中 某层手动框 为 GT,计算该层识别结果与 GT 的量化误差。
  2. 在该层 已暴露的参数空间 内自动搜索,优化上述误差(可加正则/约束)。
  3. 写回 best_params(YAML/工程内配置),触发 仅该层及必要下游 的再识别。
  4. UI/脚本均可发起「对本层跑一轮调优」;过程可中断、可复现、有报告。
  5. 支持多轮:调优后再手动改框 → 再评估/再调优(人在环)。

非目标

  • 跨 L1–L5 一次性联合优化全部参数
  • 重训 OCR 深度模型
  • 无自动调优替代手动标注(GT 仍以人调框为准)
  • 本 Issue 不要求分布式/云端大规模搜索

用户故事

  1. 用户对一页(或当前小节/行)跑识别。
  2. 进入 L3(或 L4)编辑模式,拖拽/修正框,保存为该层 GT。
  3. 点击「评估」:看到 IoU / 数量误差 / 匹配率等。
  4. 点击「本层自动调优」:系统在参数空间内搜索,展示 trial 进度与当前最优指标。
  5. 应用最优参数并 再识别该层;用户可继续改框或进入下一层。

设计要点

1. GT 来源(已有能力对接)

  • GT = 对应层编辑态下用户确认的框集合(页面/行/小节作用域与现有编辑模型一致)。
  • 需稳定序列化,例如写入工程或旁路文件:
    • gt.l3.measures[]:bbox + id/order
    • gt.l4.notes[] / anchors:bbox + 可选类型
  • 明确版本:GT 与哪次识别图、哪层、哪版 schema 绑定,避免图改了 GT 仍在用。

2. 预测与对齐

  • 识别输出同层框:pred.l3 / pred.l4
  • 匹配策略(需写进实现与单测):
    • 优先 IoU 贪心一对一(阈值可配,如 IoU ≥ 0.5)
    • 输出:TP / FP / FN、均值 IoU、数量差 |n_pred - n_gt|
  • L3 可额外:整行单节惩罚、与阅读顺序相关的序误差(可选)。

3. 单层目标函数

示例(可配置权重):

loss = w_iou * (1 - mean_iou_matched)
     + w_cnt * normalize(|n_pred - n_gt|)
     + w_fn  * fn_rate
     + w_fp  * fp_rate
  • 只使用当前层 GT 与当前层 pred,不拿下游 Pitch F1 反传改 L3(避免层间耦合;跨层以后另开 Issue)。
  • 优化目标:最小化 loss(或最大化 score = 1 - loss)。

4. 参数空间

  • 复用/落地 configs/tune/space_l3.yamlspace_l4.yaml(或层内嵌默认空间)。
  • 仅优化 当前层 键;其他层参数固定为工程当前值。
  • 所有 L3/L4 检测逻辑必须从 params 读阈值,禁止残留魔法数导致调了不生效。

5. 搜索与预算

  • MVP:随机搜索或规则网格,trials 默认 30–80,可配置。
  • 可选:Optuna TPE(同一 CLI 开关)。
  • 约束:max_trialsmax_seconds、固定 seed
  • 每 trial:params → 只跑该层(及读入该层所需的上游缓存)→ 算 loss
  • 上游布局缓存:调 L4 时不要每 trial 重跑全页 L1–L2;L3 ROI 缓存后只跑 L4。

6. 写回与再识别

  • 输出:
    • best_params.yaml(或合并进工程 tune.l3 / tune.l4
    • trials.jsonl + 简短 summary
  • 「应用并再识别」:更新运行时参数 → 重跑该层 → 刷新 UI 框与评估数字。
  • 保留「恢复默认参数」入口。

7. 人在环

  • 调优不修改 GT;仅改参数与 pred。
  • 用户再次改框后,可基于 新 GT 重新评估/调优。
  • UI 提示:样张过少时易过拟合;建议至少 N 个 measure/页再拟合。

建议模块划分

core/
  enpu/
    tuning/
      gt_match.py       # pred 框 vs GT 框对齐与 TP/FP/FN、IoU
      layer_objective.py # 单层 loss
      search.py           # random/grid/optuna
      apply_params.py     # 写回与校验键名
scripts/
  tune_layer.py         # CLI:--layer l3|l4 --project ... --trials N
desktop/
  # 「本层评估」「本层调优」「应用最优并再识别」入口(可先 CLI 后 UI)
configs/tune/
  space_l3.yaml
  space_l4.yaml
  default_params.yaml

任务清单

  • 约定并实现层 GT 的导出/读取格式(与现有手动编辑存储对齐)
  • match_boxes(pred, gt) + 单测(合成框)
  • evaluate_layer(layer, pred, gt) -> metrics/loss
  • L3/L4 参数全部配置化,确认改 YAML 能改变识别行为
  • tune_layer:搜索循环、预算、seed、写 best + trials 日志
  • 调 L4 时复用 L3 ROI 缓存,避免全管线重跑
  • 再识别路径:应用 best → 只重跑该层 → 返回新 pred
  • CLI 跑通一条闭环;桌面入口(可第二 PR)
  • 文档:操作步骤、过拟合说明、与 eval-baseline 全页指标的区别

验收标准

  1. 闭环可演示(单层)
    固定一页:识别 → 手动改 L3(或 L4)框并保存 GT → 评估有数字 → 自动调优结束 → 应用参数再识别 → 同 GT 下 loss/均值 IoU 优于或等于 调优前(在可搜空间内;若已最优允许持平并说明)。

  2. 只动本层参数
    调优报告中列出的变更键均属于该层 space;其他层参数不变。

  3. 可复现
    相同 seed、相同 GT、相同 trials 设置,best 指标一致(允许浮点公差)。

  4. GT 不被自动修改
    调优前后 GT 框数据一致。

  5. 有预算控制
    max_trials / 超时能停,并留下当前最优。

  6. 匹配逻辑可测
    合成 pred/gt 上 IoU 匹配与 TP/FP/FN 符合预期。


MVP 范围建议

可后置
仅 L3 或仅 L4 先打通一层 两层 UI 都做花
随机搜索 + YAML Optuna
CLI 闭环 桌面进度条与图表
IoU + 数量误差 复杂序误差、跨行 measure 专项

推荐:先 L3(小节框) 打通闭环(与「整行一节」痛点直接相关),再复用同一套 tune_layer 到 L4。


风险

风险 缓解
单页 GT 过拟合 文档提示;支持多页 GT 聚合 loss(Should)
参数无效(代码未读配置) 调优前做「扰动参数 → 指标应变化」的冒烟
trial 过慢 层缓存;降分辨率仅用于 tune(若可接受)
框匹配错误导致优错参 IoU 阈值可配;可视化 pred/gt 叠加抽查

相关

  • 手动分层编辑框作 GT 的现有功能(本 Issue 上游)
  • L3 小节划分准确率(旋律带小节线、整行单节、跨行)
  • L3 内数字锚点与附属符号绑定
  • L3/L4 参数化与自动调优骨架设计
  • docs/eval-baseline.md(全页 pitch 指标与本层框 IoU 互补,不互相替代)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions