- 人工智能
- 语音
- 音频
- NLP
- 媒体生成
【免费下载链接】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.
导读
本文以 examples/tiny/asr0/README.md 为主线,完整讲解如何在 PaddleSpeech 中用 Tiny 数据集(LibriSpeech 的一个小子集,仅 64 条样本)从数据准备、模型训练、Top-k 参数平均、解码评测到静态图导出,走通一套 DeepSpeech2(DS2)离线/在线语音识别模型的标准实验流程。读完本文,你将掌握run.sh五个 stage 的完整调用链、deepspeech2.yaml与deepspeech2_online.yaml的离线/在线网络结构差异,以及每个配置项背后的源码级含义,能够直接复刻或在自有数据集上改造这一套 ASR 训练流水线。
一、示例概览:Tiny + DeepSpeech2 的定位
本示例用 DeepSpeech2 模型在 Tiny 数据集上训练**离线(offline)或在线(online)**语音识别模型。Tiny 数据集取自 LibriSpeech,是其中很小的一部分(examples/tiny/asr0/local/data.sh中通过head -n 64 data/manifest.dev-clean > data/manifest.tiny.raw只取 64 条样本),因此非常适合验证工具链是否安装正确、快速跑通端到端流程,而不适合追求识别精度。
示例中所有脚本都收敛在run.sh这一个入口里,分为 5 个 stage,各 stage 的功能如下表:
| Stage | 功能 |
|---|---|
| 0 | 数据处理:下载数据集、计算训练集 CMVN、生成词表、生成训练/开发/测试集的 manifest 文件 |
| 1 | 训练模型 |
| 2 | 对 top-k 个模型参数做平均得到最终模型,k=1 表示直接选最优模型 |
| 3 | 测试最终模型性能(WER 评测) |
| 4 | 导出静态图(static graph)模型,供推理部署使用 |
run.sh通过--stage与--stop_stage两个参数控制执行区间。例如只跑 stage 2 和 stage 3:
bash run.sh --stage 2 --stop_stage 3只跑 stage 0(数据准备):
bash run.sh --stage 0 --stop_stage 0stage等于stop_stage时即只执行单个 stage。逐 stage 的执行区间组合,可以让实验在任意阶段中断、续跑或只重跑某个环节。
二、环境变量:先 source path.sh
run.sh第 3 行就是source path.sh,这是所有脚本运行的前提。path.sh 中的关键设置如下:
export MAIN_ROOT=`realpath ${PWD}/../../../` export PATH=${MAIN_ROOT}:${MAIN_ROOT}/utils:${PATH} export LC_ALL=C export PYTHONIOENCODING=UTF-8 export PYTHONPATH=${MAIN_ROOT}:${PYTHONPATH} export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/local/lib/ MODEL=deepspeech2 export BIN_DIR=${MAIN_ROOT}/paddlespeech/s2t/exps/${MODEL}/binMAIN_ROOT:定位到仓库根目录,后续utils、paddlespeech下的所有脚本都以此为基准;PATH/PYTHONPATH:让avg.sh、parse_options.sh等工具脚本和paddlespeech包随处可用;LC_ALL=C配合PYTHONIOENCODING=UTF-8:统一 locale 与 Python 输出编码,避免中文/特殊字符引发UnicodeDecodeError;BIN_DIR:指向paddlespeech/s2t/exps/deepspeech2/bin,train.py、test.py、export.py等训练/评测/导出入口都从该目录加载。
此外,各脚本内部还会加载通用参数解析器:
source ${MAIN_ROOT}/utils/parse_options.sh它实现了 shell 脚本中--variable value式的参数解析,是bash run.sh --gpus 0,1 --avg_num 1这类用法得以工作的基础。
三、本地变量:run.sh 的核心参数
run.sh顶部定义了一系列本地变量,你可以随时通过命令行覆盖它们(ckpt除外):
| 变量 | 含义 |
|---|---|
gpus | 使用的 GPU 数量/编号,设为空字符串则只用 CPU |
stage | 实验从第几阶段开始 |
stop_stage | 实验在第几阶段结束 |
conf_path | 模型配置文件路径 |
ips | 分布式训练节点 IP 列表(逗号分隔),单机可不设置 |
decode_conf_path | 解码(评测)配置文件路径 |
avg_num | Top-k 平均时的 k 值 |
avg_ckpt | 平均后的检查点前缀,即avg_${avg_num} |
ckpt | 检查点前缀,由conf_path文件名自动推导(如deepspeech2) |
model_type | 模型类型:offline 或 online(README 中导出阶段使用) |
例如同时指定 GPU 与平均数量:
bash run.sh --gpus 0,1 --avg_num 1注意ckpt=$(basename ${conf_path} | awk -F'.' '{print $1}'),即conf/deepspeech2.yaml会自动推导出ckpt=deepspeech2,因此该变量无需手动设置。avg_ckpt=avg_${avg_num}则决定了 Stage 2/3/4 中模型文件的命名约定:平均后模型位于exp/${ckpt}/checkpoints/avg_${avg_num}.pdparams。
四、Stage 0:数据处理
if [ ${stage} -le 0 ] && [ ${stop_stage} -ge 0 ]; then # prepare data bash ./local/data.sh || exit -1 fidata.sh内部又细分为 4 个子步骤(用stage/stop_stage控制,默认stage=-1到stop_stage=100全部执行):
- 下载数据、生成 manifest:调用 dataset/librispeech/librispeech.py 下载 LibriSpeech 的 dev-clean 子集并生成
data/manifest.dev-clean,随后head -n 64截取前 64 条得到data/manifest.tiny.raw; - 计算 CMVN:调用 utils/compute_mean_std.py,对 64 条样本统计线性谱的均值/方差,输出
data/mean_std.json,并指定--spectrum_type=linear --sample_rate=16000 --stride_ms=10 --window_ms=20 --use_dB_normalization=False等特征参数; - 构建词表:调用 utils/build_vocab.py,以
--unit_type char(字符级建模单元)从 raw manifest 统计出data/lang_char/vocab.txt; - 格式化 manifest:调用 utils/format_data.py,结合 CMVN 与词表,将文本转成 token id 并附带音频长度信息,输出
data/manifest.tiny,这才是训练真正读取的 manifest。
单独执行数据准备的两种方式:
bash run.sh --stage 0 --stop_stage 0或直接在命令行逐条执行:
source path.sh bash ./local/data.sh数据处理完成后,data目录结构如下:
data/ |-- dev.meta |-- lang_char | `-- vocab.txt |-- manifest.dev |-- manifest.dev.raw |-- manifest.test |-- manifest.test.raw |-- manifest.train |-- manifest.train.raw |-- mean_std.json |-- test.meta `-- train.meta其中.raw后缀的 manifest 为未做 token 化的原始清单,manifest.*为格式化后的训练清单,*.meta为按说话人组织的元数据,mean_std.json是 CMVN 归一化统计量。
五、Stage 1:模型训练
if [ ${stage} -le 1 ] && [ ${stop_stage} -ge 1 ]; then # train model, all `ckpt` under `exp` dir CUDA_VISIBLE_DEVICES=${gpus} ./local/train.sh ${conf_path} ${ckpt} ${ips} fitrain.sh 的逻辑要点:
- 根据
CUDA_VISIBLE_DEVICES的逗号个数推断ngpu;ngpu=0时单进程训练,否则通过python3 -m paddle.distributed.launch --gpus=...拉起分布式训练(ips非空时追加--ips参数支持多机); - 设置
FLAGS_allocator_strategy=naive_best_fit,注释明确说明这是为了避免显存耗尽时 GPU 训练挂起; seed默认 0(不设固定随机种子,因为注释指出"seed may break model convergence");若设非 0,会同时开启FLAGS_cudnn_deterministic=True保证可复现;- 实际执行
paddlespeech/s2t/exps/deepspeech2/bin/train.py,输出目录为exp/${ckpt},模型检查点存于exp/${ckpt}/checkpoints。
连跑数据准备与训练:
bash run.sh --stage 0 --stop_stage 1仅用 CPU 逐条执行:
source path.sh bash ./local/data.sh CUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech25.1 离线/在线配置文件对比
本示例提供两套配置,对应 DS2 的两种工作模式:
- 离线版 conf/deepspeech2.yaml:
train_manifest: data/manifest.tiny dev_manifest: data/manifest.tiny test_manifest: data/manifest.tiny min_input_len: 0.0 max_input_len: 30.0 min_output_len: 0.0 max_output_len: 400.0 min_output_input_ratio: 0.05 max_output_input_ratio: 10.0 vocab_filepath: data/lang_char/vocab.txt spm_model_prefix: '' unit_type: 'char' preprocess_config: conf/preprocess.yaml feat_dim: 161 stride_ms: 10.0 window_ms: 25.0 sortagrad: 0 batch_size: 4 maxlen_in: 512 maxlen_out: 150 minibatches: 0 batch_count: auto num_workers: 8 subsampling_factor: 1 num_encs: 1 num_conv_layers: 2 num_rnn_layers: 3 rnn_layer_size: 2048 rnn_direction: bidirect num_fc_layers: 0 fc_layers_size_list: -1, use_gru: False blank_id: 0 n_epoch: 5 accum_grad: 1 lr: 1.0e-5 lr_decay: 0.8 weight_decay: 1.0e-6 global_grad_clip: 5.0 dist_sampler: False log_interval: 1 checkpoint: kbest_n: 3 latest_n: 2- 在线版 conf/deepspeech2_online.yaml 与离线版的关键差异集中在网络结构上:
| 配置项 | 离线 deepspeech2.yaml | 在线 deepspeech2_online.yaml |
|---|---|---|
num_rnn_layers | 3 | 4 |
rnn_direction | bidirect(双向) | forward(单向) |
num_fc_layers | 0 | 2 |
fc_layers_size_list | -1,(无效) | 512, 256 |
use_gru | False(LSTM) | True(GRU) |
lr_decay | 0.8 | 1.0 |
其物理含义是:离线模型可看到整句上下文,故使用 3 层双向 RNN 捕捉前后文信息;在线模型要求逐帧/分块流式输出,只能依赖历史帧,故改为 4 层单向 RNN,并加 2 层全连接(512, 256)做投影,同时采用 GRU 以降低流式计算开销。这一差异与 docs/images/ds2offlineModel.png(双向 RNN 结构)和 docs/images/ds2onlineModel.png(单向 RNN 结构)两张架构图一致。
5.2 核心训练参数速查
feat_dim: 161:kaldi 风格 fbank 的滤波组数(见preprocess_config中n_mels: 161),也对应源码中feat_size # 161 for linear的注释;stride_ms / window_ms:帧移 10ms、窗长 25ms,与预处理的n_shift: 160 / win_length: 400(16kHz 采样率下换算)对应;sortagrad: 0:是否按序列长度排序喂样(-1 全 epoch 启用,0 禁用,其他数值表示从第几个 epoch 开始启用);maxlen_in / maxlen_out:输入/输出超过该长度时自动降低 batch size,防止 OOM;accum_grad: 1:梯度累积步数;lr_decay: 0.8:每个 epoch 学习率衰减系数;checkpoint: {kbest_n: 3, latest_n: 2}:训练过程同时保留验证集最优的 3 个和最新的 2 个检查点,供 Stage 2 平均使用。
5.3 数据预处理管线
conf/preprocess.yaml 定义了训练时对音频的特征处理链,与配置文件中的feat_dim、stride_ms等参数直接联动:
process: # extract kaldi fbank from PCM - type: fbank_kaldi fs: 16000 n_mels: 161 n_shift: 160 win_length: 400 dither: 0.1 - type: cmvn_json cmvn_path: data/mean_std.json # these three processes are a.k.a. SpecAugument - 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即:先提取 161 维 kaldi fbank(16kHz、帧移 160 点、窗长 400 点、加 0.1 dither),再做 CMVN 均值方差归一化,最后叠加 SpecAugment 的 time_warp / freq_mask / time_mask 三件套做数据增强(源码注释明确标注 "these three processes are a.k.a. SpecAugument")。
六、Stage 2:Top-k 模型平均
if [ ${stage} -le 2 ] && [ ${stop_stage} -ge 2 ]; then # avg n best model avg.sh best exp/${ckpt}/checkpoints ${avg_num} fi训练时每个 epoch 都会保存检查点,因此可基于验证集损失挑选最优模型,或对 top-k 个模型的参数做平均以得到更稳健的最终模型。utils/avg.sh 支持两种模式:
best:调用 utils/avg_model.py 并加--val_best,取验证集最优的 k 个检查点平均;latest:不加--val_best,取最近保存的 k 个检查点平均。
平均产物为exp/${ckpt}/checkpoints/avg_${avg_num}.pdparams。注意avg.sh位于utils/目录(由path.sh加入PATH),因此可以直接调用。
从数据到最终模型的完整链路:
bash run.sh --stage 0 --stop_stage 2或仅用 CPU 逐条执行:
source path.sh bash ./local/data.sh CUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2 avg.sh best exp/deepspeech2/checkpoints 1七、Stage 3:模型测试
if [ ${stage} -le 3 ] && [ ${stop_stage} -ge 3 ]; then # test ckpt avg_n CUDA_VISIBLE_DEVICES=${gpus} ./local/test.sh ${conf_path} ${decode_conf_path} exp/${ckpt}/checkpoints/${avg_ckpt}|| exit -1 fitrain.sh 会先调用 download_lm_en.sh 下载英文语言模型common_crawl_00.prune01111.trie.klm(KenLM 二进制格式,约百 MB 级),随后执行paddlespeech/s2t/exps/deepspeech2/bin/test.py,将解码结果写入${ckpt_prefix}.rsl(即avg_1.rsl),评测指标为 WER。
解码行为由 conf/tuning/decode.yaml 控制:
decode_batch_size: 128 error_rate_type: wer decoding_method: ctc_beam_search lang_model_path: data/lm/common_crawl_00.prune01111.trie.klm alpha: 2.5 beta: 0.3 beam_size: 500 cutoff_prob: 1.0 cutoff_top_n: 40 num_proc_bsearch: 8参数说明:
decoding_method: ctc_beam_search:使用 CTC 前缀束搜索解码,而非贪心解码;beam_size: 500:束宽,越大搜索空间越大、效果通常越好但速度越慢;lang_model_path+alpha: 2.5+beta: 0.3:外部语言模型融合,alpha是 LM 权重、beta是词插入惩罚,这是 DS2 在测试阶段显著降低 WER 的关键手段;cutoff_prob: 1.0/cutoff_top_n: 40:束搜索时对概率的剪枝策略,用于控制计算量;num_proc_bsearch: 8:束搜索并行进程数。
完整训练+评测流水线:
bash run.sh --stage 0 --stop_stage 3CPU 逐条执行:
source path.sh bash ./local/data.sh CUDA_VISIBLE_DEVICES= ./local/train.sh conf/deepspeech2.yaml deepspeech2 avg.sh best exp/deepspeech2/checkpoints 1 CUDA_VISIBLE_DEVICES= ./local/test.sh conf/deepspeech2.yaml conf/tuning/decode.yaml exp/deepspeech2/checkpoints/avg_1如果只想做贪心解码验证,可将decoding_method改为ctc_greedy(对应仓库其他示例中常见的ctc_greedy_search类解码配置),此时lang_model_path/alpha/beta不参与计算。
八、Stage 4:静态图模型导出
if [ ${stage} -le 4 ] && [ ${stop_stage} -ge 4 ]; then # export ckpt avg_n CUDA_VISIBLE_DEVICES=0 ./local/export.sh ${conf_path} exp/${ckpt}/checkpoints/${avg_ckpt} exp/${ckpt}/checkpoints/${avg_ckpt}.jit ${model_type} fiexport.sh 调用paddlespeech/s2t/exps/deepspeech2/bin/export.py,将动态图(dygraph)检查点转换为静态图(static graph)模型,导出路径为exp/deepspeech2/checkpoints/avg_1.jit。转换后的.jit模型可用于后续的预测部署(包括 Paddle Inference、服务端推理、移动端等场景)。
已有动态图模型时的导出命令:
source path.sh ./local/export.sh deepspeech2.yaml exp/deepspeech2/checkpoints/avg_1 exp/deepspeech2/checkpoints/avg_1.jit offline最后一个参数即模型类型(offline/online),在线模型导出的静态图面向流式推理场景。
九、源码级原理:DeepSpeech2 网络结构
deepspeech2.py 中CRNNEncoder的实现与配置文件一一对应:
- 卷积降采样层:
Conv2dSubsampling4Pure(feat_size, 32)将 161 维特征先做 2D 卷积与 4 倍时间降采样,对应配置的num_conv_layers: 2; - RNN 层:按
num_rnn_layers循环堆叠nn.LSTM或nn.GRU,rnn_direction决定每层的direction='bidirect'或'forward';双向时 LayerNorm 维度取2 * rnn_size,单向取rnn_size; - 全连接投影层:
num_fc_layers与fc_layers_size_list控制是否追加nn.Linear层(在线版为512, 256两层的 MLP 投影); - CTC 输出:编码器输出经 Softmax 得到逐帧类别概率,再交给
CTCDecoder做 CTC 解码,blank_id: 0指定 CTC 空白符的 token id。
离线与在线的本质区别就体现在rnn_direction上:离线模型每层 RNN 同时看到过去与未来帧,解码时可整句束搜索(配合ctc_beam_search与 LM 融合);在线模型 RNN 单向传播,仅依赖历史帧,天然适配流式/分块推理场景。
十、完整流水线与后续延伸
一条从零到部署的标准命令链(离线模式,4 卡 GPU):
bash run.sh --gpus 0,1,2,3 --avg_num 1 # 覆盖默认参数 bash run.sh --stage 0 --stop_stage 4 # 一次跑完数据→训练→平均→测试→导出要点回顾:
path.sh必须先 source,所有脚本的路径依赖它;- Stage 0 产出的
manifest.tiny.raw是 64 条样本的裁剪结果,后续compute_mean_std.py、build_vocab.py、format_data.py都基于它; - 换用更大数据集时,只需把
data.sh中的下载/截取逻辑替换为完整 LibriSpeech(参考 examples/librispeech/asr1 的run.sh组织方式),并调整deepspeech2.yaml中的n_epoch、batch_size、lr等训练超参; - 需要在线(流式)能力时,将
conf_path切换为conf/deepspeech2_online.yaml,并配套使用conf/tuning/chunk_decode.yaml进行分块解码; - 静态图模型导出后可对接 PaddleSpeech 的服务端引擎(paddlespeech/server)或 runtime 推理引擎 完成部署。
以 64 条样本跑通上述全流程后,你就掌握了 PaddleSpeech 以 manifest + 配置驱动 ASR 实验的核心方法论,可以无障碍迁移到 LibriSpeech、AISHELL 等真实规模数据集上训练和评测 DeepSpeech2 模型。
- 人工智能
- 语音
- 音频
- NLP
- 媒体生成
【免费下载链接】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.
相关推荐
Playwright MCP 如何在 VS Code、Cursor 等 MCP 客户端中配置并完成第一次页面操作?
Playwright MCP 如何在 VS Code、Cursor 等 MCP 客户端中配置并完成第一次页面操作? 如果你希望 IDE 里的 AI 助手能直接打
人工智能语音音频PaddleSpeech DeepSpeech2 模块源码解析:CRNN 编码器、CTC 训练与在线/离线推理实现
PaddleSpeech DeepSpeech2 模块源码解析:CRNN 编码器、CTC 训练与在线/离线推理实现 DeepSpeech2(DS2)是 Padd
人工智能语音音频NLP媒体生成PaddleSpeech FastSpeech2 训练全流程解析:exps 包数据流水线与模型训练实战
PaddleSpeech FastSpeech2 训练全流程解析:exps 包数据流水线与模型训练实战 导读 本文以 PaddleSpeech 仓库中 padd
人工智能语音音频NLP媒体生成
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考