- 人工智能
- 语音
- 音频
【免费下载链接】PaddleSpeech
Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.
本文以 PaddleSpeech 仓库中的 callcenter 示例 为核心,系统讲解面向呼叫中心、客服电话等 8k 采样率语音场景的 ASR 全流程:如何自备数据生成 manifest、如何配置离线 Conformer 与流式 Chunk Conformer、如何使用四种解码方式评估模型、以及如何做 CTC 对齐与 JIT 模型导出。读完本文,你将能够独立跑通一套 8k 电话语音识别(Mandarin 8k)的训练、评测、对齐与部署链路。
一、Recipe 定位:一个只含配置、不含数据的 8k ASR 示例
在 PaddleSpeech 中,examples/callcenter是一个特殊的示例:它不像 aishell 或 librispeech 那样自带数据下载逻辑,而是只提供面向 8k 采样率的模型配置与数据配置。正如其在 examples/callcenter/README.md 中明确说明的:
This recipe only has model/data config for 8k ASR, user need to prepare data and generate manifest metafile. You can see Aishell or Libripseeth.
也就是说:用户需要自行准备 8k 电话语音数据(如呼叫中心录音),并参照 Aishell/Librispeech 的流程生成 manifest 元数据文件,然后复用本 recipe 的配置与脚本完成训练和评测。呼叫中心语音与常规 16k 朗读语音差异明显:采样率低(8k)、信道特性复杂、口语化与噪声较多,因此单独维护一套 8k 配置是必要的。
该示例的实际目录结构如下:
examples/callcenter/ ├── README.md └── asr1/ ├── RESULTS.md # MandarinK8 实验结果(CER) ├── path.sh # 环境变量与 BIN_DIR(MODEL=u2) ├── run.sh # 主入口,按 stage 驱动全流程 ├── conf/ │ ├── conformer.yaml # 离线 Conformer 训练/推理配置 │ ├── chunk_conformer.yaml # 流式(分块)Conformer 配置 │ ├── preprocess.yaml # fbank 特征 + SpecAugment 预处理 │ ├── augmentation.json # 在线数据增强(speed/shift/specaug) │ └── tuning/ │ ├── decode.yaml # 离线解码配置 │ └── chunk_decode.yaml # 流式模拟解码配置 └── local/ ├── data.sh # 数据准备(CMVN、词表、格式化 manifest) ├── train.sh # 单机多卡训练 ├── test.sh # 四种解码方式评测 ├── align.sh # CTC 强制对齐 ├── export.sh # 导出 JIT 推理模型 └── download_lm_ch.sh # 下载中文语言模型(可选)从 path.sh 可以看出,该 recipe 使用的模型框架是MODEL=u2,训练与推理脚本位于paddlespeech/s2t/exps/u2/bin/(包括train.py、test.py、alignment.py、export.py、test_wav.py等)。U2 即论文Unified Streaming and Non-streaming Two-pass End-to-end Model for Speech Recognition(arXiv:2012.05481)所描述的两遍式模型,这也是本 recipe 既能跑离线识别、又能跑流式识别的原因。
二、数据准备:自备 8k 数据并生成 manifest
2.1 原始 manifest 的字段格式
callcenter 的data.sh假定用户已经准备好了data/manifest.train、data/manifest.dev、data/manifest.test三个原始 manifest 文件(jsonline 格式,每行一个 JSON 对象)。生成这种格式的参考实现是 paddlespeech/dataset/aishell/aishell.py,每个条目包含如下字段:
{ "utt": "音频ID(如 BAC009S0002W0123)", "utt2spk": "说话人ID", "feat": "/绝对路径/到/音频.wav", "feat_shape": [3.2], "text": "对应的中文转写文本" }其中feat_shape是音频时长(秒),feat直接指向 wav 文件路径(format_data.py会识别其为sound类型的输入)。如果你的数据是 Kaldi 风格的 ark 特征,format_data.py 会直接抛出NotImplementedError——当前 recipe 只支持直接读 wav。务必保证音频为 8k 采样率,这关系到后续 CMVN 与 fbank 参数的正确性。
2.2 三步数据流水线
local/data.sh 在拿到上述三个原始 manifest 后,分三步加工:
Step -1:备份原始文件。将data/manifest.{train,dev,test}重命名为.raw后缀,供后续步骤读取。
Step 0:计算 CMVN 统计量。调用 utils/compute_mean_std.py 生成data/mean_std.json,关键参数体现了 8k 场景的设定:
python3 ${MAIN_ROOT}/utils/compute_mean_std.py \ --manifest_path="data/manifest.train.raw" \ --spectrum_type="fbank" \ --feat_dim=80 \ --delta_delta=false \ --stride_ms=10 \ --window_ms=25 \ --sample_rate=8000 \ --use_dB_normalization=False \ --num_samples=-1 \ --num_workers=${num_workers} \ --output_path="data/mean_std.json"对比 Aishell 的同一脚本(--sample_rate=16000),callcenter 将sample_rate显式设为8000,这是整个 recipe 最核心的差异点;feat_dim=80的 fbank、stride_ms=10、window_ms=25则与标准配置保持一致。
Step 1:构建字符词表。调用 utils/build_vocab.py,以--unit_type="char"从训练集转写文本生成data/lang_char/vocab.txt(count_threshold=0表示不过滤低频字符)。
Step 2:格式化 manifest。对 train/dev/test 三个数据集并行调用 utils/format_data.py,把原始 manifest 转换为带 tokenid 的训练/评测格式(输出到data/manifest.{train,dev,test})。从 paddlespeech/dataset/s2t/format_data.py 的源码可以看到,转换后的条目形如:
{ "input": [{"name": "input1", "shape": [...], "feat": "/path/to/audio.wav", "filetype": "sound"}], "output": [{"name": "target1", "shape": [...], "text": "转写文本", "token": "...", "tokenid": "..."}], "utt": "...", "utt2spk": "..." }完成后,data/目录下应有manifest.train(.raw)、manifest.dev(.raw)、manifest.test(.raw)、mean_std.json以及lang_char/vocab.txt,与 conf/conformer.yaml 中train_manifest、dev_manifest、test_manifest、vocab_filepath的默认路径一一对应。
三、模型配置:离线 Conformer 与流式 Chunk Conformer
3.1 离线版 conf/conformer.yaml
conf/conformer.yaml 是默认训练配置,采用Conformer 编码器 + Transformer 解码器 + 混合 CTC/Attention的 U2 结构:
- 数据加载:
unit_type: 'char'、feat_dim: 80、sortagrad: 0(关闭按时长排序)、batch_size: 64、maxlen_in: 512/maxlen_out: 150(超长样本自动缩减 batch)、num_workers: 0; - 编码器 encoder_conf:
output_size: 256、attention_heads: 4、linear_units: 2048、num_blocks: 12、dropout_rate: 0.1、input_layer: conv2d、cnn_module_kernel: 15、activation_type: 'swish'、位置编码rel_pos、注意力rel_selfattn; - 解码器 decoder_conf:
attention_heads: 4、linear_units: 2048、num_blocks: 6; - 模型目标 model_conf:
ctc_weight: 0.3(CTC 与 attention 的混合权重)、lsm_weight: 0.1(标签平滑)、length_normalized_loss: false; - 训练策略:
n_epoch: 100、accum_grad: 4(梯度累积)、global_grad_clip: 5.0、优化器adam(lr: 0.002、weight_decay: 1e-6)、调度器warmuplr(warmup_steps: 25000)、checkpoint.kbest_n: 50/latest_n: 5。
3.2 流式版 conf/chunk_conformer.yaml
conf/chunk_conformer.yaml 用于训练支持流式推理的分块模型,与离线版的关键差异包括:
- 数据加载:
batch_size: 32、raw_wav: True(直接读原始 wav)、spectrum_type: fbank、target_sample_rate: 8000、dither: 1.0、use_dB_normalization: True(target_dB: -20)、sortagrad: True、shuffle_method: batch_shuffle、num_workers: 2; - 编码器新增流式相关字段:
causal: true(因果卷积)、use_dynamic_chunk: true(动态分块训练)、cnn_module_norm: 'layer_norm'(注释说明使用 LayerNorm 收敛更快)、use_dynamic_left_chunk: false; - 训练策略:
n_epoch: 240、lr: 0.001,其余结构(编码器 12 层、解码器 6 层、ctc_weight 0.3 等)与离线版保持一致。
从 paddlespeech/s2t/models/u2/u2.py 的源码看,推理时 U2 模型会依据decoding_chunk_size与num_decoding_left_chunks决定是否调用encoder.forward_chunk_by_chunk做逐块前向,这正是流式解码的底层机制。
3.3 特征预处理与数据增强
conf/preprocess.yaml 定义了特征提取与在线增强管线:
process: - type: fbank_kaldi fs: 8000 # 8k 采样率 n_mels: 80 n_shift: 160 # 10ms win_length: 400 # 25ms dither: 0.1 - type: cmvn_json cmvn_path: data/mean_std.json # SpecAugment 三件套 - type: time_warp max_time_warp: 5 inplace: true mode: PIL - type: freq_mask F: 30 n_mask: 2 inplace: true replace_with_zero: false - type: time_mask T: 40 n_mask: 2 inplace: true replace_with_zero: false注意fs: 8000、n_shift: 160(= 8000 × 0.01s)、win_length: 400(= 8000 × 0.025s)与 8k 采样率严格对应。
conf/augmentation.json 则提供了另一套在线增强:变速speed(0.9~1.1,prob 0.0 默认关闭)、时间平移shift(±5ms,prob 1.0)、SpecAugmentspecaug(F: 10、T: 50、各 2 个 mask、replace_with_zero: true,prob 1.0)。RESULTS.md 中标注的实验增强组合为spec_aug + shift。
四、解码配置与四种解码方式
4.1 离线解码 conf/tuning/decode.yaml
conf/tuning/decode.yaml 的完整参数如下:
decode_batch_size: 128 error_rate_type: cer decoding_method: attention # 'attention', 'ctc_greedy_search', 'ctc_prefix_beam_search', 'attention_rescoring' beam_size: 10 ctc_weight: 0.5 # ctc weight for attention rescoring decode mode. decoding_chunk_size: -1 # <0: 全序列解码; >0: 固定块大小; 0: 仅训练用,禁止 num_decoding_left_chunks: -1 # 左侧历史块数,-1 表示不限制 simulate_streaming: False # 是否模拟流式推理4.2 流式模拟解码 conf/tuning/chunk_decode.yaml
conf/tuning/chunk_decode.yaml 与离线版参数完全相同,唯一的区别是simulate_streaming: true——配合 chunk 模型(如decoding_chunk_size: 16)即可模拟流式推理的评测。RESULTS.md中 Chunk Conformer 的实验即采用Chunk Size & Left Chunks = 16, -1。
4.3 四种解码方法
local/test.sh 会遍历四种解码方式并分别输出结果文件({ckpt_prefix}/{method}.rsl):
| 解码方式 | 说明 |
|---|---|
attention | 纯 attention 解码(自回归) |
ctc_greedy_search | CTC 贪心搜索,速度最快 |
ctc_prefix_beam_search | CTC prefix beam search |
attention_rescoring | 两遍式:先用 CTC beam search 生成候选,再用 attention 重打分,通常效果最好 |
测试时通过--opts decode.decoding_method ${type} --opts decode.decode_batch_size 1逐项覆盖默认配置。如果需要使用中文语言模型参与 CTC 解码,可执行 local/download_lm_ch.sh 下载zh_giga.no_cna_cmn.prune01244.klm(脚本中已给出 URL 与 MD5 校验值),不过 local/test.sh 中该步骤默认处于注释状态。
五、端到端流水线:run.sh 的 stage 设计
run.sh 采用 PaddleSpeech 通用的 stage 驱动模式(配合 utils/parse_options.sh 支持--stage N --stop_stage M形式的命令行覆盖),顶部的关键变量:
gpus=0,1,2,3 stage=0 stop_stage=50 conf_path=conf/conformer.yaml ips= # 多机训练时填写节点 IP 列表 decode_conf_path=conf/tuning/decode.yaml avg_num=20各 stage 功能如下:
| Stage | 功能 | 调用脚本 |
|---|---|---|
| 0 | 数据准备(CMVN、词表、格式化 manifest) | local/data.sh |
| 1 | 模型训练(多卡) | local/train.sh |
| 2 | 平均 top-k 模型得到最终模型 | avg.sh best exp/${ckpt}/checkpoints ${avg_num} |
| 3 | 测试 avg_n 模型(四种解码方式) | local/test.sh |
| 4 | 测试集 CTC 强制对齐 | local/align.sh |
| 51 | 导出 JIT 推理模型 | local/export.sh |
例如只做数据准备:bash run.sh --stage 0 --stop_stage 0;完整跑训练到评测:bash run.sh --stage 0 --stop_stage 3。
训练(stage 1):local/train.sh 根据CUDA_VISIBLE_DEVICES中的 GPU 数量自动选择单卡或分布式模式。多卡时使用python3 -m paddle.distributed.launch --gpus=... [--ips=...] ${BIN_DIR}/train.py,其中ips用于多机训练。脚本还支持seed控制(非 0 时设置FLAGS_cudnn_deterministic=True保证可复现,但注释提示"seed may break model convergence")。
模型平均(stage 2):utils/avg.sh 调用avg_model.py,支持best(按验证损失选 top-k)与latest(取最近 k 个)两种模式,输出exp/${ckpt}/checkpoints/avg_${avg_num}.pdparams,这也是后续测试、对齐、导出所共用的 checkpoint 前缀。
六、CTC 对齐与模型导出
CTC 对齐(stage 4):local/align.sh 调用${BIN_DIR}/alignment.py,基于最终模型对测试集做 CTC 强制对齐,将对齐结果写入result_file(.align),并在结果文件所在目录生成.tier与.TextGrid格式的对齐文件——这些输出可直接用于音素级/字级边界分析或后续强制对齐工具链。
模型导出(stage 51):local/export.sh 调用${BIN_DIR}/export.py,把训练好的 checkpoint 转换为可部署的 JIT 模型:
CUDA_VISIBLE_DEVICES= ./local/export.sh ${conf_path} \ exp/${ckpt}/checkpoints/${avg_ckpt} \ exp/${ckpt}/checkpoints/${avg_ckpt}.jit导出的.jit模型可进一步配合 PaddleSpeech 的服务端(如paddlespeech/server)或 runtime 部署方案 使用。
七、MandarinK8 实验结果参考
RESULTS.md 记录了在MandarinK8(中文 8k)测试集上的官方复现结果。两个模型参数量均为45.73 M,增强方式均为spec_aug + shift:
Conformer(离线,conf/conformer.yaml,Loss 2.1795):
| 解码方式 | CER |
|---|---|
| attention | 0.102304 |
| ctc_greedy_search | 0.084295 |
| ctc_prefix_beam_search | 0.084340 |
| attention_rescoring | 0.081675 |
Chunk Conformer(流式,conf/chunk_conformer.yaml,Chunk=16 / Left=-1,Loss 2.2329):
| 解码方式 | CER |
|---|---|
| attention | 0.087982 |
| ctc_greedy_search | 0.086962 |
| ctc_prefix_beam_search | 0.086741 |
| attention_rescoring | 0.083495 |
这两组数据可以为你评估自备数据的训练效果提供对照基线:离线两遍式解码(attention_rescoring)在该任务上 CER 最低;流式模型在 16 帧分块约束下与离线模型差距约 0.2 个百分点,体现了 U2 两遍式架构在"低延迟"与"高精度"之间的折中能力。
八、从源码看 U2 的流式/非流式统一机制
本 recipe 之所以能同时覆盖离线与流式两种形态,根源在于 paddlespeech/s2t/models/u2/u2.py 实现的统一模型:训练时使用动态分块(dynamic chunk)策略让编码器适应分块输入;推理时根据simulate_streaming与decoding_chunk_size决定是否走forward_chunk_by_chunk逐块计算编码器输出(u2.py),再配合ctc_prefix_beam_search生成候选、attention_rescoring二次打分,形成完整的流式两遍解码。
对应地,训练与推理的完整实现位于 paddlespeech/s2t/exps/u2/model.py(U2Trainer/U2Tester的train_batch、test、export等),命令行入口则在 paddlespeech/s2t/exps/u2/bin/ 下。理解这层调用链,有助于你在修改conf/下任一配置后快速定位其生效的代码路径。
结语
examples/callcenter是一个"轻文档、重配置"的典型 recipe:文档虽短,但仓库内的两份 YAML、预处理与增强配置、stage 流水线脚本以及 MandarinK8 基线结果,共同构成了一套完整的 8k 电话语音识别落地模板。对于需要处理客服录音、电话会议等低采样率语音场景的开发者,直接复用本 recipe 的配置,替换为自己的数据并生成对应 manifest,即可复现出接近上表基线的离线与流式 ASR 系统。
- 人工智能
- 语音
- 音频
【免费下载链接】PaddleSpeech
Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.
相关推荐
PaddleSpeech 基于 SpeechX(runtime)的 U2/U2++ 流式 ASR C++ 工业部署实战指南
PaddleSpeech 基于 SpeechX(runtime)的 U2/U2++ 流式 ASR C++ 工业部署实战指南 PaddleSpeech 仓库中的
人工智能语音音频NLP媒体生成PaddleSpeech 基于 TAL_CSASR 中英混合教学语音数据集训练 U2(Conformer/Transformer)ASR 模型实战指南
PaddleSpeech 基于 TAL_CSASR 中英混合教学语音数据集训练 U2(Conformer/Transformer)ASR 模型实战指南 TAL_
人工智能语音音频中英混合课堂语音识别:TAL_CSASR 数据集解析与 PaddleSpeech U2/Conformer 全流程实战
中英混合课堂语音识别:TAL_CSASR 数据集解析与 PaddleSpeech U2/Conformer 全流程实战 TAL_CSASR 是 PaddleSp
人工智能语音音频NLP媒体生成
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考