finetune_spk-sortformer / docs /simulation_pipelines.md
czyhust's picture
Add files using upload-large-folder tool
bed2cee verified
|
Raw
History Blame Contribute Delete
13.6 kB
# Simulation Data Pipelines
本文档描述 G-STAR finetuning pipeline 中两条独立的多说话人数据仿真流水线:**FastMSS 流水线(主)****NeMo 流水线(旧)**
---
## 一、全局概览
两条流水线共享 LibriSpeech 源数据,但在仿真引擎、中间格式和最终产物上完全不同。
```
┌─── LibriSpeech 源数据 ──────────────┐
│ WHAM/MUSAN 噪声 │
│ │
┌─────▼──────────────────────────────────┐ │
│ PIPE A: NeMo 仿真流水线(旧) │ │
│ data_simulation_nemo.sh │ │
│ run_all_speakers_simulation_nemo.sh │ │
│ → sentence_level_multispeaker_ │ │
│ simulator.py │ │
│ → utterance-level JSON │ │
│ → standardize_manifest_format.py │ │
│ → segment-level JSONL │ │
└────────────────────────────────────────┘ │
┌─────▼──────────────────────────────────┐ │
│ PIPE B: FastMSS 仿真流水线(主) │ │
│ data_simulation_fastmss.sh │ │
│ run_fastmss-*.sh │ │
│ → recipes/sim.py (5-stage Hydra) │ │
│ → Lhotse CutSet → WAV + RTTM │ │
│ → nemo_manifest.jsonl │ │
└────────────────────────────────────────┘ │
┌─────▼──────────────────────────────────┐ │
│ Training / Inference │ │
│ train.sh → streaming_sortformer_ │ │
│ diar_train.py │ │
│ infer.sh → e2e_diarize_speech.py │ │
│ (消耗 segment-level JSONL) │ │
└────────────────────────────────────────┘ │
```
---
## 二、根目录 Shell 脚本总览
| 脚本 | 用途 | 所属流水线 |
|---|---|---|
| `data/nemo/simulate.sh` | NeMo 单次仿真:并行跑 train/dev/test | Pipe A |
| `data/nemo/run_all_speakers.sh` | NeMo 全量仿真:遍历 2-10 spk,合并输出,标准化为 JSONL | Pipe A |
| `data/fastmss/simulate.sh` | FastMSS 单次仿真入口:调用 `recipes/sim.py` + 分析脚本 | Pipe B |
| `data/fastmss/run_6spk_v1.sh` | v1 config: 90s, WHAM noise, 1-6 spk, 30k train / 3k dev / 3k test | Pipe B |
| `data/fastmss/run_6spk_v1.1.sh` | v1.1 config: 50% reverb/noise 概率, 2-6 spk, speed perturbation | Pipe B |
| `data/fastmss/run_6spk_v2.sh` | v2 config: WHAM + MUSAN 双噪声源, 基于 v1.1 | Pipe B |
| `data/fastmss/run_mini_testset.sh` | 小测试集: 600 meetings, seed=45, 8 workers, 用于调试验证 | Pipe B |
| `train.sh` | Sortformer 微调入口 (Hydra) | 训练 |
| `run_finetune_8spk.sh` | 8-spk 微调预设 | 训练 |
| `run_train_10spk.sh` | 10-spk 微调预设(从 4-spk checkpoint 扩展) | 训练 |
| `infer.sh` | 流式 diarization 推理 + DER 评估 | 推理 |
| `run_infer_8spk.sh` / `run_infer_8spk_base.sh` | 8-spk 推理(微调模型 / 预训练 baseline) | 推理 |
| `path.sh` | 环境配置:PYTHONPATH + conda env 激活 | 全局 |
| `data/nemo/prepare_data.sh` | 6 阶段数据预处理(详见第三节) | Pipe A 前置 |
---
## 三、Pipe A:NeMo 仿真流水线(旧)
### 3.1 数据预处理:`data/nemo/prepare_data.sh`
为 NeMo 模拟器准备 LibriSpeech + WHAM 源数据,共 6 个阶段(stage 参数控制):
| 阶段 | 脚本 | 说明 |
|---|---|---|
| Stage 1 | `data/nemo/scripts/get_librispeech_data.py` | FLAC → WAV 转换(sox),生成 JSON manifest |
| Stage 2 | `data/nemo/scripts/create_alignment_manifest.py` | 集成 CorentinJ 格式的词级对齐,产出 CTM + 对齐 manifest |
| Stage 3 | `data/shared/scripts/pathfiles_to_diarize_manifest.py` | WHAM 噪声 wav → diarization manifest |
| Stage 4 | `cat` | 合并 train clean_100+360+other_500 → train_960(test/dev 同理) |
| Stage 5 | `data/fastmss/scripts/get_max_audio_duration.py` | 分析仿真数据集音频时长分布(直方图 + CDF) |
| Stage 6 | `data/shared/scripts/split_manifest_by_spk.py` | 按说话人数拆分标准化 manifest(≤4 / >4) |
### 3.2 仿真过程
```
data_simulation_nemo.sh
→ sentence_level_multispeaker_simulator.py
→ 输出:utterance-level JSON(每行一个 utterance)
→ standardize_manifest_format.py
→ 输出:segment-level JSONL(每行一个音频段)
→ split_manifest_by_spk.py
→ 输出:按 spk 数拆分的 JSONL
```
**核心脚本:`data/nemo/scripts/sentence_level_multispeaker_simulator.py`**
- NeMo `MultiSpeakerSimulator` 的子类
- 以整句为单位拼接(非词级 chunk)
- 可配置 silence/overlap/session_length/spk_count
- 输出 utterance-level JSON + RTTM 文件
**桥接脚本:`data/nemo/scripts/standardize_manifest_format.py`**
- NeMo utterance-level JSON → 标准 segment-level JSONL
- 添加 `uniq_id` 字段防止 key 冲突
- 这是训练/推理实际消费的格式
### 3.3 相关文件清单
```
data/
├── prepare_data.sh # 6 阶段数据预处理
├── conf/default_data_simulator.yaml # NeMo 仿真器配置
└── scripts/
├── get_librispeech_data.py # FLAC→WAV + manifest
├── create_alignment_manifest.py # 对齐 manifest
├── pathfiles_to_diarize_manifest.py # 噪声 manifest
├── sentence_level_multispeaker_simulator.py # 句子级模拟器(入口)
├── multispeaker_simulator.py # 词级模拟器(旧,已弃用)
├── standardize_manifest_format.py # 格式标准化(桥接)
└── get_max_audio_duration.py # 时长分布分析
```
---
## 四、Pipe B:FastMSS 仿真流水线(主)
### 4.1 前置准备
FastMSS 的输入是 Lhotse CutSet(含词级对齐),由以下脚本生成:
**`data/fastmss/scripts/create_cutsets.py`**
-`/F00120240032/librispeech/.../lhotse_format_manifests/` 读取 recordings + supervisions manifests
- 生成 `librispeech_cutset_{split}.jsonl.gz`
**`src/third_party/FastMSS/scripts/split_musan.py`**(v2 新增)
- 将 MUSAN 噪声按 8:1:1 拆分到 `{tr,cv,tt}.wavlist`
### 4.2 仿真过程
```
run_fastmss-*.sh
→ data_simulation_fastmss.sh
→ src/third_party/FastMSS/recipes/sim.py (Hydra 5 阶段流水线)
→ Stage 1: 加载 CutSet → 停顿处切分 → 保存 merged CutSet
→ Stage 2: 扫描噪声目录/wavlist → 过滤短噪声 → noise_files.txt
→ Stage 3: RIRSimulator → pyroomacoustics → all_rooms.json
→ Stage 4: ConversationalMeetingSimulator → 并行生成 WAV + Lhotse manifests
→ Stage 5: 生成 RTTM + nemo_manifest.jsonl
→ analyze_speaker_distribution.py
→ analyze_duration_distribution.py
```
### 4.3 `recipes/sim.py` 5 阶段详解
| 阶段 | 输入 | 输出 | 说明 |
|---|---|---|---|
| **Stage 1** | `librispeech_cutset_{split}.jsonl.gz` | `{data_dir}/manifests/all_cuts.jsonl.gz` | 加载 CutSet,merge 指定 split,在词对齐停顿处切分 utterance |
| **Stage 2** | 噪声目录 + wavlist 文件 | `{output_dir}/manifests/noise_files.txt` | 递归扫描音频文件(支持目录 glob 和 wavlist 逐行读取),过滤 <2s 的短噪声 |
| **Stage 3** | 房间/麦克风/RIR 配置 | `{rir_dir}/all_rooms.json` | pyroomacoustics 生成房间脉冲响应,可配 RT60/房间尺寸/麦克风类型 |
| **Stage 4** | CutSet + 噪声 + RIR | WAV 文件 + Lhotse manifests | 并行生成 n_meetings 场会议:HMM 轮次切换、spk 权重采样、增益随机化、RIR 卷积、噪声混合 |
| **Stage 5** | Stage 4 manifests | RTTM 文件 + `nemo_manifest.jsonl` | 生成逐 meeting 的 RTTM(0.2s 间隙合并),生成 NeMo 格式 diarization manifest |
### 4.4 配置文件层级
```
src/third_party/FastMSS/recipes/
├── default.yaml # 基础配置
└── extend_sortformer/6spk/
├── v1.yaml # 6-spk base: 90s, WHAM, RIR, Markov HMM
├── v1.1.yaml # 增强版: 50% reverb/noise, speed perturbation
├── v2.yaml # 新增 MUSAN 双噪声
└── dataset_splits/
├── train.yaml # cutset_train-clean-{100,360,500}
├── dev.yaml # cutset_dev-{clean,other}
└── test.yaml # cutset_test-{clean,other}
```
### 4.5 相关文件清单
```
src/third_party/FastMSS/
├── fastmss/
│ ├── simulator.py # ConversationalMeetingSimulator 核心引擎
│ ├── hmm_turn_taking.py # 4 状态 HMM 轮次模型
│ ├── rirsimulator.py # RIR 生成器 (pyroomacoustics)
│ └── utils.py # 音频工具
├── recipes/
│ ├── sim.py # 5 阶段 Hydra 仿真入口
│ ├── default.yaml
│ └── extend_sortformer/6spk/ # 6-spk 配置
├── scripts/
│ ├── split_musan.py # MUSAN 噪声拆分
│ ├── analyze_speaker_distribution.py # 说话人分布统计
│ └── analyze_duration_distribution.py # 时长分布统计
└── preprocessing/
├── download_wham.sh # 下载 WHAM 噪声
└── download_otospeech.sh # 下载 otoSpeech
```
---
## 五、两条流水线对比
| 维度 | Pipe A (NeMo) | Pipe B (FastMSS) |
|---|---|---|
| **模仿真引擎** | `sentence_level_multispeaker_simulator.py` | `recipes/sim.py` (Hydra) |
| **输入格式** | LibriSpeech WAV + 对齐 JSON | Lhotse CutSet (`.jsonl.gz`) |
| **轮次模型** | 简单 silence/overlap 控制 | 4 状态 Markov HMM(hold/switch/interruption/backchannel) |
| **房间仿真** | NeMo RIRMultiSpeakerSimulator | pyroomacoustics RIRSimulator |
| **噪声输入** | WHAM dir | 目录 + wavlist(支持 WHAM/MUSAN 等) |
| **仿真粒度** | 句子级 chunk 拼接 | 词级对齐切分,更细粒度 |
| **并行策略** | Shell 级 `&` 后台并行 | Python 多进程 `parallel_map` |
| **中间输出** | utterance-level JSON | Lhotse Recording + Supervision manifests |
| **最终产物** | segment-level JSONL(需 `standardize_manifest_format.py` 转换) | `nemo_manifest.jsonl`(直接可用) |
| **当前状态** | 旧流水线,用于 10-spk | **主线流水线**,用于 Sortformer 微调 |
---
## 六、关键桥接脚本
| 脚本 | 方向 | 说明 |
|---|---|---|
| `data/fastmss/scripts/create_cutsets.py` | Lhotse manifests → CutSet | 为 FastMSS 生成输入 |
| `data/nemo/scripts/standardize_manifest_format.py` | NeMo utterance JSON → segment JSONL | 为训练/推理转换格式 |
**注意**:FastMSS Stage 5 直接产出 `nemo_manifest.jsonl`,格式与训练/推理消费的 segment-level JSONL 兼容,无需额外转换步骤。
---
## 七、典型使用流程
### 使用 FastMSS (Pipe B) 生成 v2 数据集:
```bash
# 1. 拆分 MUSAN(仅 v2 需要)
python src/third_party/FastMSS/scripts/split_musan.py /path/to/musan data/dump_fastmss/musan_noise_wavlists
# 2. 运行仿真(生成 train/dev/test)
bash run_fastmss-extend_sortformer-6spk-dataset_v2.sh
# 3. 产物位于 data/dump_fastmss/simulated_sessions/extend_sortformer-6spk-dataset_v2/{train,dev,test}/
# 每个目录包含: audio/*.wav, rttm/*.rttm, nemo_manifest.jsonl
```
### 使用 NeMo (Pipe A) 生成 10-spk 数据集:
```bash
# 1. 预处理
bash data/prepare_data.sh
# 2. 全量仿真
bash run_all_speakers_simulation_nemo.sh
```
---
## 八、路径约定
| 用途 | 默认路径 | 说明 |
|---|---|---|
| LibriSpeech | `/F00120240032/librispeech/corpus_librispeech/corpus` | 源数据 |
| lhotse manifests | `/F00120240032/librispeech/.../lhotse_format_manifests` | FastMSS 输入 |
| WHAM noise | `/F00120240032/wham_noise/wham_noise/wham_noise/{tr,cv,tt}` | 噪声目录 |
| LibriSpeech Alignments | `/F00120240032/LibriSpeech-Alignments` | 词级对齐 |
| FastMSS 输出 | `data/dump_fastmss/simulated_sessions/{version}/{split}/` | 仿真产物 |
| NeMo 输出 | `data/dump/simulated_10spk_dataset/` | 旧流水线产物 |
| 训练输出 | `exp/` | gitignored |
| 模型 checkpoints | `checkpoints/` | gitignored |