PaddleSpeech 定制化流式语音识别实战基于 Slot WFST 解码图实现打车报销场景的稀有地名精准识别【免费下载链接】PaddleSpeechEasy-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.项目地址: https://gitcode.com/paddlepaddle/PaddleSpeech本篇技术指南围绕 PaddleSpeech 仓库中 demos/custom_streaming_asr 演示目录展开讲解如何通过「带槽位Slot的 WFST 解码图定制」解决通用 ASR 在稀有词如打车场景中的生僻地名上识别准确率不足的问题并给出从 Docker 环境搭建、WebSocket 服务端启动、客户端调用到定制解码图构建的完整可运行流程。读完本文你将掌握 PaddleSpeech 定制化流式识别Customized Streaming ASR的整体架构、核心参数含义以及如何在本地复现一个能识别「打车到某地名」句式的端到端演示。一、为什么需要定制化 ASR稀有词识别的痛点通用语音识别系统在常见语料上表现良好但在某些垂直场景中需要对特定稀有词保持极高的识别准确率。典型例子是导航软件中的地名识别一个城市的街道名、小区名、商圈名往往不在通用词典里通用模型很容易将其识别错误。本文演示的 demo 正是取自打车报销单场景用户说「打车到某某地名多少钱」系统需要准确识别出其中的稀有地址。原文档给出了两种解法在线识别演示即本目录 demos/custom_streaming_asr 的用法通过 WebSocket 服务端/客户端完成定制化流式识别定制解码图构建仓库中与之配套的完整建图脚本位于 runtime/examples/custom_asr展示如何从零构建自己的解码图TLG.fst。两者的核心思想一致在解码图的语言模型层G中为稀有词预留槽位Slot再通过 WFST 的 replace 操作把槽位替换成可扩展的定制词表从而让解码器认识这些稀有词。二、核心原理Slot WFST 定制解码图定制化的关键在于修改解码图而非重新训练声学模型。原文档用三张图说明了这一过程其核心链路如下G with slot在语言模型 G 中把需要定制的部分抽象为一个槽位。例如句子模板「打车到 address_slot」其中address_slot就是一个占位符槽位表示「此处可填入任意地名」。address slot 的 WFST单独构建一个 address 槽位对应的 WFST里面列出所有需要识别的地名。想新增地名时只需扩充这个槽位图即可无需重新训练声学模型。fstreplace 替换执行G fstreplace(G_with_slot, address_slot)将主图G_with_slot中的槽位用槽位图address_slot替换最终得到定制化的解码图。替换后得到的定制化 TLG.fst 即可直接用于解码。从 runtime/examples/custom_asr/run.sh 的源码可以看到该演示实际预留了 5 个槽位分别对应打车报销单中常见的实体类型echo MONEY_SLOT 一 $dir/local/dict/lexicon.txt echo DATE_SLOT 一 $dir/local/dict/lexicon.txt echo ADDRESS_SLOT 一 $dir/local/dict/lexicon.txt echo YEAR_SLOT 一 $dir/local/dict/lexicon.txt echo TIME_SLOT 一 $dir/local/dict/lexicon.txt这些槽位会被加入 lexicon以避免语言模型训练脚本将其过滤掉源码注释add slot to lexicon, just in case the lm training script filter the slot。整个定制流程与最终识别效果WER 1.23%记录在 runtime/examples/custom_asr/README.md 中。三、整体架构WebSocket 服务端 客户端本 demo 采用 WebSocket 进行流式语音识别交互架构上分为两部分服务端websocket_server_main负责加载声学模型Paddle 推理模型、解码图TLG.fst、词表与 cmvn 统计量并监听指定端口接收客户端流式音频。客户端websocket_client_main按wav.scp逐条读取语音以流式 chunk 方式发送给服务端并获取识别结果。服务端入口在 runtime/engine/asr/server/websocket/websocket_server_main.cc其核心逻辑非常清晰通过 gflags 解析命令行参数组装RecognizerResource包含声学模型、特征管线、TLG 解码器配置随后启动WebSocketServer并开始监听DEFINE_int32(port, 8082, websocket listening port); ppspeech::RecognizerResource InitRecognizerResoure() { ppspeech::RecognizerResource resource; resource.acoustic_scale FLAGS_acoustic_scale; resource.feature_pipeline_opts ppspeech::FeaturePipelineOptions::InitFromFlags(); resource.model_opts ppspeech::ModelOptions::InitFromFlags(); resource.tlg_opts ppspeech::TLGDecoderOptions::InitFromFlags(); return resource; } int main(int argc, char *argv[]) { gflags::ParseCommandLineFlags(argc, argv, false); google::InitGoogleLogging(argv[0]); ppspeech::RecognizerResource resource InitRecognizerResoure(); ppspeech::WebSocketServer server(FLAGS_port, resource); LOG(INFO) Listening at port FLAGS_port; server.Start(); return 0; }所有可配置参数声学特征、解码、模型相关统一定义在 runtime/engine/asr/decoder/param.hdemo 文档中提到的port、graph_path、model_path均来自这里。四、环境准备Paddle 2.2.2 Docker 镜像原文档要求使用 Paddle 2.2.2 的 Docker 镜像搭建运行环境。CPU 版拉取与启动命令如下sudo docker pull registry.baidubce.com/paddlepaddle/paddle:2.2.2 sudo docker run --privileged --nethost --ipchost -it --rm \ -v $PWD:/paddle --namepaddle_demo_docker \ registry.baidubce.com/paddlepaddle/paddle:2.2.2 /bin/bash其中关键参数说明--privileged授予容器特权保证网络与设备访问正常--nethost容器与宿主机共享网络栈便于客户端直连服务端口--ipchost共享进程间通信命名空间配合 WebSocket 流式传输使用-v $PWD:/paddle将当前目录即 demo 目录挂载到容器内/paddle--rm退出容器后自动清理。如果使用 GPU 环境仓库还提供了 setup_docker.sh其内部使用sudo nvidia-docker run启动同一镜像以便声学模型在 GPU 上推理。五、启动服务端websocket_server.sh 详解进入容器后执行cd /paddle bash websocket_server.sh该脚本demos/custom_streaming_asr/websocket_server.sh实际完成两步工作。5.1 第一步下载并解压资源脚本首先检查 cmvn 文件是否存在不存在则下载并解压resource.tar.gzif [ ! -f $cmvn ]; then wget -c https://paddlespeech.cdn.bcebos.com/s2t/paddle_asr_online/resource.tar.gz tar xzfv resource.tar.gz ln -s ./resource/data . fi解压后在resource目录下会得到以下内容与文档描述一致目录作用model声学模型Deepspeech2 在线模型jit 推理格式graph解码图TLG.fst与词表words.txtlib运行所需动态库bin可执行程序websocket_server_main 等data测试语音与 wav.scp同时脚本会ln -s ./resource/data .创建data软链接供 cmvn 与语音数据引用。5.2 第二步启动 WebSocket 服务资源就绪后脚本调用websocket_server_main并传入一组参数websocket_server_main \ --cmvn_file$cmvn \ --streaming_chunk0.1 \ --use_fbanktrue \ --model_path$model_dir/avg_10.jit.pdmodel \ --param_path$model_dir/avg_10.jit.pdiparams \ --model_cache_shapes5-1-2048,5-1-2048 \ --model_output_namessoftmax_0.tmp_0,tmp_5,concat_0.tmp_0,concat_1.tmp_0 \ --word_symbol_table$graph_dir/words.txt \ --graph_path$graph_dir/TLG.fst --max_active7500 \ --port8881 \ --acoustic_scale12各参数含义如下参数示例值说明cmvn_file./data/cmvn.ark特征均值方差归一化统计量文件streaming_chunk0.1流式解码的音频分块时长秒越小实时性越好use_fbanktrue使用 Fbank 特征false 则为线性特征model_path/param_pathavg_10.jit.pdmodel/avg_10.jit.pdiparamsPaddle 推理模型结构文件与参数文件model_cache_shapes5-1-2048,5-1-2048流式模型各层缓存张量的 shape用于跨 chunk 传递状态model_output_namessoftmax_0.tmp_0,...模型输出节点名称对应 CTC softmax 与缓存输出word_symbol_tablewords.txt词符号表将解码输出映射为文字graph_pathTLG.fst解码图路径定制化 ASR 的核心输入max_active7500解码时保持活跃的 token 数量上限port8881服务监听端口acoustic_scale12声学分数缩放系数5.3 参数定义出处以上参数的默认值与完整定义可追溯到 runtime/engine/asr/decoder/param.h例如DEFINE_string(cmvn_file, , read cmvn); DEFINE_string(model_path, avg_1.jit.pdmodel, paddle nnet model); DEFINE_double(acoustic_scale, 1.0, acoustic scale); DEFINE_string(graph_path, , decoder graph); DEFINE_string(word_symbol_table, , word symbol table); DEFINE_int32(max_active, 7500, max active); DEFINE_double(beam, 15.0, decoder beam); DEFINE_double(lattice_beam, 7.5, decoder beam); DEFINE_double(blank_threshold, 0.98, blank skip threshold); DEFINE_int32(nbest, 10, nbest for ctc wfst or prefix search);其中beam、lattice_beam、blank_threshold、nbest等参数在 demo 脚本中未显式给出均使用param.h中的默认值若需调整解码精度与速度的平衡可直接在启动命令中追加同名参数。另外port的默认值8082定义在 websocket_server_main.cc 中demo 通过显式传入--port8881覆盖。六、启动客户端websocket_client.sh服务端运行后在另一个终端执行bash websocket_client.sh客户端脚本demos/custom_streaming_asr/websocket_client.sh内容如下data$PWD/data wav_scpwav.scp export GLOG_logtostderr1 websocket_client_main \ --wav_rspecifierscp:$data/$wav_scp \ --streaming_chunk0.36 \ --port8881参数说明--wav_rspecifierscp:$data/$wav.scp以 Kaldi scp 格式指定待识别的语音集合wav.scp位于解压出的data目录下--streaming_chunk0.36客户端每次发送的音频分块时长秒与服务端0.1的 chunk 配合完成流式解码--port8881服务端监听端口必须与websocket_server.sh中保持一致。两个脚本顶部均执行. path.shdemos/custom_streaming_asr/path.sh它把resource/lib加入LD_LIBRARY_PATH、把resource/bin加入PATH保证websocket_server_main/websocket_client_main可被直接调用。七、运行结果解读客户端日志中可以看到类似如下的输出0513 10:58:13.827821 41768 recognizer_test_main.cc:56] wav len (sample): 70208 I0513 10:58:13.884493 41768 feature_cache.h:52] set finished I0513 10:58:24.247171 41768 paddle_nnet.h:76] Tensor neml: 10240 I0513 10:58:24.247249 41768 paddle_nnet.h:76] Tensor neml: 10240 LOG ([5.5.544~2-f21d7]:main():decoder/recognizer_test_main.cc:90) the result of case_10 is 五月十二日二十二点三十六分加班打车回家四十一元逐行含义wav len (sample): 70208当前语音共 70208 个采样点约 4.4 秒 16kHzfeature_cache.h:52] set finished特征缓存写入完成进入流式解码状态paddle_nnet.h:76] Tensor neml: 10240Paddle 神经网络前向计算输出的帧数信息最后一行LOG (...:90) the result of case_10 is ...即为最终识别结果五月十二日二十二点三十六分加班打车回家四十一元。注意该结果中包含了日期五月十二日、时间二十二点三十六分、金额四十一元等槽位化实体正是定制解码图生效的体现——通用模型很难在单句中同时精确给出这些稀有组合。类似的 batch 识别与 WER 统计流程也可参考 runtime/examples/custom_asr/run.sh 的 stage 4使用recognizer_test_main对wav.scp批量解码再用utils/compute-wer.py与标注data/wav.trans比对计算字错误率。八、从零构建自己的定制解码图如果不想使用预置的resource.tar.gz仓库在 runtime/examples/custom_asr 提供了完整的建图教程脚本对应原文档中提到的speechx/examples/custom_asr流程。执行bash run.sh后按 stage 依次完成stage 1 制作词典由声学模型词表vocab.txt与发音词典data/lexicon.txt通过 utils/fst/prepare_dict.py 生成 lexicon并手工追加MONEY_SLOT、DATE_SLOT、ADDRESS_SLOT、YEAR_SLOT、TIME_SLOT五个槽位条目stage 2 训练带槽语言模型调用 local/train_lm_with_slot.sh 生成包含槽位 token 的 n-gram 语言模型stage 3 构建 TLG依次执行 local/compile_lexicon_token_fst.sh生成 T、L 图、local/mk_slot_graph.sh生成槽位图、local/mk_tlg_with_slot.sh执行 fstreplace 并组合成 TLG.fststage 4 测试用recognizer_test_main解码data/wav.scp通过 utils/compute-wer.py 计算 WER仓库记录的参考结果约为Overall 1.23%N1134, C1126, S6, D2, I6。对开发者而言定制自己的地名/人名/术语只需在槽位 WFST 中扩充对应词条并重新执行 stage 3而无需重新训练声学模型这正是该方案在垂直场景下快速落地的价值所在。九、小结PaddleSpeech 的定制化流式 ASR 演示给出了一条「不改声学模型、只改解码图」的稀有词识别路径通过带槽位的 G 图与fstreplace组合出定制化 TLG.fst配合 WebSocket 流式服务完成在线识别。本文覆盖了从 Docker 环境搭建、服务端/客户端脚本逐参数解读、日志结果分析到定制解码图构建全流程并给出了各参数在 param.h 中的定义出处可直接作为在 demos/custom_streaming_asr 目录下复现实验、或参考 runtime/examples/custom_asr 构建自有定制词表的实战手册。【免费下载链接】PaddleSpeechEasy-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.项目地址: https://gitcode.com/paddlepaddle/PaddleSpeech创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考