Commit fa7f5f57 fa7f5f576d81902b8b307b47f4452244423b9657 by cnb.bofCdSsphPA

Clarify the real data contract before scaling external datasets

Constraint: Must document code-true behavior for training crops, retrieval windows, GPU support, and FMA reuse before more dataset automation lands
Rejected: Leave docs at high-level abstractions only | Would hide 5s-vs-8s and CPU-vs-GPU operational realities
Confidence: high
Scope-risk: narrow
Directive: Keep future dataset docs aligned with actual code paths and artifact timestamps, not intended architecture alone
Tested: Source review of dataset.py manifest_tools.py external_adapters.py utils/audio.py ecapa_embedder.py train.py; live FMA smoke progress observed through epoch completion
Not-tested: Markdown renderer-specific Mermaid rendering and every relative link target in external viewers
1 parent 713425f5
......@@ -2,6 +2,34 @@
## 2026-06-02
### Stage: 补齐训练数据、重叠窗口、GPU 与 FMA 数据处理文档
完成项:
- 重写并压缩 `dataset-spec.md`,补齐训练切片、检索重叠滑窗、manifest 生成差异
- 扩展 `training-data-and-pgvector-guide.md`,补齐 FMA / MTG / 自有数据接入、目录规范、脚本职责、GPU 加速说明
- 明确记录当前真实代码事实:训练端 5s 随机裁剪、检索端 5s/2.5s 重叠滑窗、外部 manifest 默认 8s query
- 记录当前 smoke 现状:`smoke-local` 仍固定 CPU,真实 FMA smoke 正在运行
- 记录当前实验产物一致性风险:旧的 `fma_reports_smoke/config.json` 与最新 manifests 时间戳不一致,需后续统一配置治理
验证结果:
- 源码复核:
- `src/data/dataset.py`:训练端随机 5s crop
- `src/utils/audio.py` / `src/engines/ecapa_embedder.py`:5s window + 2.5s stride
- `src/data/manifest_tools.py`:每首歌 1 个随机 query,默认 `8.0s`
- `src/data/external_adapters.py``smoke-local` 当前硬编码 `--device cpu`
- `train.py`:支持 `--device auto`,CUDA 路径支持 mixed precision
- 真实运行状态:
- FMA smoke 进程仍在运行
- 最新可见进度约 `82%` epoch 1
- 文档链接验证:主文档仍使用相对路径链接到仓库文件与同组文档
结论:
- 当前项目关于训练数据格式、3 分钟 mp3 切片、是否重叠窗口、GPU 是否可显著加速、FMA 与开放数据如何复用流程,已形成可交接文档
- 后续可继续沿两条线推进:
1.`smoke-local` 支持 GPU
2. 增加 overlap query manifest 生成能力
### Stage: 真实 FMA 本地数据门槛打开并进入 smoke 训练
完成项:
......
# ACR Dataset / 输入输出规范
> 更新:2026-06-02
> 关联文档:[训练数据与 pgvector 指南](./training-data-and-pgvector-guide.md) · [开放数据工作流](./open-dataset-workflow.md) · [数据来源与接入](./dataset-sources-and-licensing.md)
## 一页结论
- 数据规范的核心不是文件格式,而是**分离 catalog 与 query**
- 外部数据集进入系统前必须先转换成统一 manifest
- 当前系统的标准输入是:
- **16k mono audio**
- **128 Mel**
- **window-level retrieval**
- 当前系统的标准输出是:
- top-k candidates
- confidence
- reject/accept
- metadata
当前项目的数据规范,最重要的是 4 件事:
1. **训练输入不是“整首 mp3 文件”本身,而是 manifest 驱动的 reference + query 样本体系**
2. **训练和检索的切窗策略不同**:训练端当前是**随机裁剪 5s**,检索/建索引端当前是**5s 窗口 + 2.5s stride 的 50% 重叠滑窗**
3. **外部开源数据集进入项目时,必须先转换成统一 manifest**,再做训练、评测、索引和 pgvector 入库。
4. **当前音乐任务输入层已切换到 128 维 Mel 频谱**,并开启 band-split 方向;FMA 这类真实数据建议优先使用 GPU。
---
......@@ -22,13 +18,14 @@
```mermaid
flowchart LR
A[External / Synthetic Audio] --> B[Manifest Conversion]
B --> C[Catalog Manifest]
B --> D[Query Manifest]
C --> E[Reference Index Build]
D --> F[Training / Evaluation Queries]
A[Raw Audio\nFMA / MTG / 自有 BGM / 录音] --> B[Manifest Conversion]
B --> C[Catalog Manifest\nreference]
B --> D[Train/Test Manifest\nquery]
C --> E[Reference Index Build\nsliding windows]
D --> F[Training / Evaluation]
E --> G[Hybrid Retrieval]
F --> G
G --> H[pgvector / report / service]
```
---
......@@ -58,6 +55,7 @@ flowchart TD
Q --> Q2[audio_path]
Q --> Q3[duration]
Q --> Q4[type=clean/augmented/confused/humming_like]
Q --> Q5[offset]
```
---
......@@ -66,14 +64,60 @@ flowchart TD
| 环节 | 输入 | 输出 |
|---|---|---|
| 训练 | query segments | embeddings + logits |
| 训练 | query segments + references | embeddings + logits |
| 索引 | catalog references | chromaprint index + embedding index |
| 识别 | query audio | ranked candidates |
| 评测 | query manifest + catalog | top1/top5/hard-case report |
| 入库 | manifest + embedding | pgvector-ready JSON / SQL rows |
---
## 4.1 Hard-case 训练信号图
## 5. 3 分钟 mp3 到 5–8 秒片段:当前到底怎么切
## 5.1 当前代码里有 **3 种不同切法**
```mermaid
flowchart TD
A[3min mp3] --> B[训练 Dataset]
A --> C[检索 / 建索引]
A --> D[外部数据集 manifest 生成]
B --> B1[随机裁 1 个 5s clip]
C --> C1[5s 窗 + 2.5s stride]\n50% overlap
D --> D1[每首歌随机采 1 个 query]\n默认 8s
```
| 场景 | 当前实现 | 是否重叠 | 代码位置 |
|---|---|---:|---|
| 训练 `SongPairDataset` | 每次采样随机取一个 5s clip | 否,**不是固定滑窗** | [acr-engine/src/data/dataset.py](../acr-engine/src/data/dataset.py) |
| 检索 / embedding / 建索引 | `window_sec=5.0`, `stride_sec=2.5` | 是,**50% overlap** | [acr-engine/src/utils/audio.py](../acr-engine/src/utils/audio.py), [acr-engine/src/engines/ecapa_embedder.py](../acr-engine/src/engines/ecapa_embedder.py) |
| `audio-dir-to-splits` | 每首歌只生成 1 个随机 query | 否 | [acr-engine/src/data/manifest_tools.py](../acr-engine/src/data/manifest_tools.py) |
### 直接回答你的问题
- **有重叠窗口,但只在检索/索引链路里有。**
- **当前训练主链路没有对 3 分钟 mp3 预展开成“全量重叠切片集”**,而是每次 batch 动态随机裁一个 5s 片段。
- **当前外部数据集 manifest 生成器也没有自动为每首歌生成多个重叠 query。**
---
## 5.2 为什么这样设计
| 设计点 | 当前好处 | 当前限制 |
|---|---|---|
| 训练随机裁剪 | 节省存储,不必预生成几万切片 | 同一 epoch 暴露到的时间区域有限 |
| 检索重叠滑窗 | 更接近真实 ACR reference coverage | 索引体积更大 |
| 外部数据一首歌一个 query | smoke 更轻、更快验证 | 训练/评测覆盖不充分 |
推荐理解方式:
- **训练端**更像“随机数据增强采样器”
- **检索端**更像“为了召回覆盖做滑窗索引”
---
## 6. 当前训练信号与 hard-case 规则
## 6.1 Hard-case 训练信号图
```mermaid
flowchart LR
......@@ -97,7 +141,7 @@ flowchart LR
---
## 4.2 检索融合参数图
## 6.2 检索融合参数图
```mermaid
flowchart LR
......@@ -112,14 +156,9 @@ flowchart LR
| `ecapa_weight` | 0.50 | 0.55 | 提高 embedding 检索主导 |
| `melody_weight` | 0.25 | 0.25 | 暂时保持不变 |
说明:
- 当前仓库已经支持在 `evaluate.py` 中直接传入融合参数
- 对个人使用场景,推荐把一部分开源数据集固定成 **fusion tuning eval set**
- 这样训练、检索、调参可以分离,而不是每次都重训
---
## 4.3 开源数据集 train/eval 切分图
## 7. 开源数据集 train/eval 切分图
```mermaid
flowchart LR
......@@ -137,7 +176,7 @@ flowchart LR
| [test.json](../acr-engine/data/external_ingested/demo_via_adapter/fma/manifests/test.json) | 评估查询 | query + references |
| [val.json](../acr-engine/data/external_ingested/demo_via_adapter/fma/manifests/val.json) | 预留验证集 | 当前可为空 |
推荐法则(个人使用)
推荐法则:
- FMA / MTG-Jamendo 可优先用于真实 train/eval baseline
- 至少固定一部分曲目只进 [test.json](../acr-engine/data/external_ingested/demo_via_adapter/fma/manifests/test.json),不要同时参与训练
- 小数据集也要保证至少 1 个 train query + 1 个 test query
......@@ -148,38 +187,48 @@ CLI 入口:
- 导入前预检查:[acr-engine/src/data/external_adapters.py](../acr-engine/src/data/external_adapters.py) `inspect-local <dataset> <input_dir>`
- 多目录批量预检查:[acr-engine/src/data/external_adapters.py](../acr-engine/src/data/external_adapters.py) `inspect-batch fma=<dir> mtg_jamendo=<dir> ...`
## 5. 文字说明
---
## 8. 当前项目输入层规范
| 项目 | 当前值/建议 | 说明 |
|---|---|---|
| 采样率 | `16kHz` | 统一音频读取口径 |
| 声道 | `mono` | 当前链路按单声道处理 |
| 频谱 | `128 Mel` | 音乐任务输入层 |
| 训练 clip | `5s` | 当前训练代码事实 |
| 外部 query manifest 默认 | `8s` | 当前 `prepare-local/smoke-local` 默认 |
| Band split | `enabled` | 已纳入当前模型配置 |
### 5.1 为什么必须分离 catalog 和 query
早期原型容易把 train split 直接当搜索库,这会让评测和真实服务语义混乱。工业化系统必须把:
- “可搜索曲库”
- “训练/评测 query”
---
明确分离。
## 9. 文字说明
### 5.2 为什么输入层是 128 Mel
音乐任务需要更丰富的频带表达,128 Mel 更适合 band-split 和音乐 timbre/harmony 建模
### 9.1 为什么必须分离 catalog 和 query
工业化系统里,“可搜索曲库”和“训练/评测 query”必须分离,否则评测会和真实服务语义混在一起
### 5.3 query 类型为什么要显式标注
`clean / augmented / confused / humming_like` 是评测与训练策略的重要条件,不应只放在隐式文件名里
### 9.2 为什么输入层是 128 Mel
音乐任务需要更丰富的频带表达;128 Mel 比 40 维 MFCC 更适合 timbre/harmony/band-split 建模
### 5.4 为什么 hard-case 权重必须做到 sample-level
如果只在 batch 级取平均权重,`confused` 这种少量但高风险样本会被正常样本稀释。当前版本已经改成 **sample-level weighted SupCon + sample-level weighted CE**,从而让单个困难片段在损失中真实“被看见”
### 9.3 为什么 query 类型必须显式标注
`clean / augmented / confused / humming_like` 不只是标签名,而是训练权重、评测 bucket、难例治理的入口
### 5.5 当前经验结论
### 9.4 关于 5s vs 8s 的一个当前注意点
当前仓库有两组时长:
- **训练 Dataset 与默认模型训练:5s**
- **开放数据 manifest/query 默认:8s**
这不是同一层配置,因此当前文档和实验报告里必须明确区分;不要把它们误认为一套统一参数。
### 9.5 当前经验结论
- 简单过采样会导致整体退化
- type-aware weighting 能提升一部分 hard case
- confused 类需要更高权重,但过强偏置会回伤 `humming_like`
- residual confused failure 往往集中在 `intro` 片段,因此 `segment_type` 不只是元数据,还应参与后续难负例设计
- 因此 dataset 规范中必须保留 `type` 字段,后续才能继续做:
- confusion-aware negative mining
- melody-aware reranking
- 双支路 hard-case curriculum
- segment-type-aware hard negatives
---
## 6. 细节附录
## 10. 细节附录
### Reference 示例
```json
......@@ -203,6 +252,5 @@ CLI 入口:
}
```
## Sources
- See [references-and-sources.md](./references-and-sources.md) for the current source map.
- 当前代码事实来自 [acr-engine/src/data/dataset.py](../acr-engine/src/data/dataset.py), [acr-engine/src/data/manifest_tools.py](../acr-engine/src/data/manifest_tools.py), [acr-engine/src/utils/audio.py](../acr-engine/src/utils/audio.py), [acr-engine/src/engines/ecapa_embedder.py](../acr-engine/src/engines/ecapa_embedder.py), [acr-engine/train.py](../acr-engine/train.py)
......