ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

PaddleSpeech ASR 解码器 Scorer 机制深度解析:从 ScorerInterface 到 CTC Prefix Score 与 N-gram 语言模型

PaddleSpeech ASR 解码器 Scorer 机制深度解析:从 ScorerInterface 到 CTC Prefix Score 与 N-gram 语言模型 人工智能语音音频NLP媒体生成【免费下载链接】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 源码中的 paddlespeech.s2t.decoders.scorers 包 为核心深入剖析其支撑的 ASR 束搜索beam search打分scoring体系。你将理解 PaddleSpeech 如何通过统一的 Scorer 接口把注意力解码器attention decoder、CTC 前缀打分CTC prefix score、N-gram 语言模型和长度惩罚length bonus组织进同一条解码流水线并掌握ctc_weight、lm_weight、penalty、ngram_weight等核心超参在recog_v2中的真实作用与配置方法。读完本文你既能看懂解码代码的调用链也能直接上手调优自己的识别解码参数。一、Scorers 包在 PaddleSpeech 解码体系中的位置PaddleSpeech 的 S2Tspeech-to-text模块采用混合 CTC/注意力端到端语音识别架构。训练好的模型在做识别解码时需要在束搜索过程中对每个候选 token 打分。打分来源不止一个注意力解码器attention decoder自身给出的预测概率CTC 前缀概率用于 CTC 前缀搜索可以独立解码也可以参与重打分训练好的外部语言模型RNNLM / N-gram LM长度惩罚防止束搜索偏向短句或鼓励更长输出。为了把这些来源不同、接口各异的分记者统一起来PaddleSpeech 在 paddlespeech/s2t/decoders/scorers/ 目录下实现了一组 scorer 类。对应的 API 文档页 paddlespeech.s2t.decoders.scorers.rst 将其划分为 4 个子模块子模块文件核心类scorer_interfacescorer_interface.pyScorerInterface、BatchScorerInterface、PartialScorerInterface、BatchPartialScorerInterfacectcctc.pyCTCPrefixScorerctc_prefix_scorectc_prefix_score.pyCTCPrefixScorePD、CTCPrefixScorelength_bonuslength_bonus.pyLengthBonus此外还有一个未在 toctree 中列出的 ngram.py实现了基于 kenlm 的 N-gram 语言模型打分器NgramFullScorer、NgramPartScorer并在recog_v2中与上面四个子模块共同被装配进束搜索。需要说明的是PaddleSpeech 的 S2T 解码器代码大量参考了 ESPnet 的设计源码文件头均注明 Modified from espnet因此这些 scorer 的接口约定与 ESPnet 一脉相承熟悉任一框架都有助于理解另一个。二、ScorerInterface束搜索打分器的统一抽象scorer_interface.py 是整个 scorer 体系的地基定义了四个逐层继承的接口类。它们的层级关系如下ScorerInterface ├── BatchScorerInterface (增加 batch 接口) └── PartialScorerInterface (增加部分 token 打分接口) └── BatchPartialScorerInterface (同时继承以上两者)2.1 ScorerInterface全量打分的最小契约ScorerInterfaceL24-L94定义了 4 个核心方法init_state(x)返回解码初始状态。默认返回None需要状态的分记者如 CTC、N-gram会重写它。参数x是编码器输出的特征张量encoded feature tensor。select_state(state, i, new_idNone)在主束搜索中按相对索引i选取状态必要时按新标签new_id选取。默认实现为None if state is None else state[i]。score(y, state, x)必须实现的打分方法。y是 1D 前缀 tokenpaddle.int64state是前缀对应的 scorer 状态x是编码器特征。返回(n_vocab,)形状的下一 token 得分张量以及更新后的状态。默认直接raise NotImplementedError。final_score(state)对 EOS 的最终打分默认返回0.0。类 docstring 给出了三类典型实现示例搜索启发式search heuristicsLengthBonus序列到序列模型的解码器网络transformer.decoder.Decoder、rnn.decoders.Decoder神经语言模型lm.transformer.TransformerLM、lm.default.DefaultRNNLM、lm.seq_rnn.SequentialRNNLM。也就是说凡是实现了ScorerInterface的模块无论内部是规则、神经网络还是外部工具都能被束搜索统一调度。这正体现了打分器插拔式架构的设计思路。2.2 BatchScorerInterface批量打分BatchScorerInterface 在ScorerInterface之上增加了batch_init_state(x)默认转调init_state(x)batch_score(ys, states, xs)批量打分。ys形状为(n_batch, ylen)states是状态列表xs形状为(n_batch, xlen, n_feat)。返回(n_batch, n_vocab)的批量得分和新的状态列表。值得注意的是其默认实现如果子类没有重写batch_score会退化为 Python for 循环逐条调用score同时发出警告{class} batch score is implemented through for loop not parallelized。这意味着接口允许伪批量降级但会失去向量化性能——真正的性能路径要求子类自己实现向量化批量打分下文CTCPrefixScorePD就是典型例子。2.3 PartialScorerInterface只给候选子集打分PartialScorerInterface 定义了score_partial(y, next_tokens, state, x)接收已经预剪枝的下一批 tokennext_tokens形状(len(next_tokens),)只对它们打分返回形状为(len(next_tokens),)的得分。设计动机在 docstring 中写得很清楚有些打分器如 CTC 前缀搜索对全部词表打分代价太高因此先在主打分器如注意力解码器上做一次 pre-beam 剪枝再只对剪枝后的候选子集做代价高昂的二次打分。BatchPartialScorerInterface 则同时继承BatchScorerInterface与PartialScorerInterface增加批量化的batch_score_partialys形状为(n_batch, ylen)next_tokens形状为(n_batch, n_token)返回(n_batch, n_vocab)得分。这四层接口构成了 PaddleSpeech 解码打分器的完整抽象全量打分score / batch_score用于常规 scorer部分打分score_partial / batch_score_partial用于代价高昂、只评估候选子集的 scorer。三、LengthBonus最简单的搜索启发式打分器LengthBonus 实现了BatchScorerInterface是搜索启发式打分器的代表也是整个 scorer 家族里最轻量的一员。其构造器只接收一个参数n_vocab词表大小并把所有 token 的得分恒定为1.0# length_bonus.py 中的核心实现单条打分 def score(self, y, state, x): return paddle.to_tensor( [1.0], placex.place, dtypex.dtype).expand(self.n), None # 批量打分 def batch_score(self, ys, states, xs): return (paddle.to_tensor([1.0], placexs.place, dtypexs.dtype).expand( ys.shape[0], self.n), None)从实现看LengthBonus并不是按长度给出差异化加分而是给每个候选 token 一个恒定1.0的得分。它的意义在于在束搜索中每扩展一个 token 都会累加这条恒定得分从而让更长的假设获得累计更高的分数以此抵消对数概率随句子变长而天然累积变小的趋势避免束搜索过度偏向短句。最终对搜索的影响大小由装配时的权重penalty决定见第六节。四、CTC Prefix Scorer基于 CTC 前缀概率的分记者CTCConnectionist Temporal Classification前缀打分是混合 CTC/注意力解码的核心。CTCPrefixScorerctc.py实现了BatchPartialScorerInterface把两种前缀打分算法封装成了统一的 scorer 接口。4.1 两层实现单条版与批量版ctc.py从 ctc_prefix_score.py 引入了两个底层算法类类后端特点CTCPrefixScoreNumPy单条单个假设CTC 前缀打分逐条计算状态以(T, 2)的前向概率张量表达CTCPrefixScorePDPaddle批量向量化版本同时为多个假设高效计算标签概率两者的算法基础都是 Watanabe 等人论文Hybrid CTC/Attention Architecture for End-to-End Speech Recognition中的 Algorithm 2批量版进一步采用了 Seki 等人INTERSPEECH 2019的向量化束搜索思想把多个假设的 CTC 前向概率组织进高维张量一次性计算。4.2 CTCPrefixScorePD 的批量计算CTCPrefixScorePD.__init__L20-L64接收x标签后验序列形状(B, T, O)B 为 batchT 为输入帧数O 为输出维度xlens每条样本的有效长度(B,)blankblank 标签 ideos结束符 idmarginCTC 窗口化windowing的 margin 参数margin0表示不启用窗口。初始化时它会把超出有效长度的帧填充为logzero-10000000000.0即-1e10的近似负无穷并构造(2, T, B, O)的张量self.x——轴 0 的两个通道分别对应非 blankn与 blankb的路径概率。核心计算在__call__L66-L187中完成维护 CTC 前向状态r_prev形状(T, 2, BW)对应论文中的r_t^n(h)与r_t^b(h)以及累积分数s_prev若传入scoring_ids预剪枝后的候选子集则只对这部分 id 构建x_并计算得分输出形状为(BW, O)支持基于注意力权重的 CTC 窗口化att_w与margin 0时生效对应论文 eq.(22,23)限定有效计算帧区间[f_min - margin, f_max margin]显著减少计算量通过paddle.logsumexp在(n, b)两通道上做前向概率合并得到 log 前缀概率log_psi为eos位置单独写入前缀自身即为完整序列的概率r_sum[end_frames]并把 blank 对应的概率置为logzeroCTC 解码中 blank 不作为输出 token返回(log_psi - s_prev)相对增量得分与更新的状态(r, log_psi, f_min, f_max, scoring_idmap)。index_select_stateL189-L221则负责在束剪枝后按best_ids从批量状态中选出存活假设对应的 CTC 状态供下一轮搜索使用。4.3 CTCPrefixScorer把算法封装成 Scorer 接口CTCPrefixScorerctc.py L24-L164的构造参数是ctcpaddle.nn.Layer类型的 CTC 实现例如paddlespeech.s2t.modules.ctc.CTCeos结束符 id。它在init_state中调用self.ctc.log_softmax(x.unsqueeze(0))得到对数后验再交给CTCPrefixScore构造单条实现并返回初始状态batch_init_state则使用CTCPrefixScorePD此时假设 batch_size1。score_partial实现相对得分用presub_score - prev_score求出本次新增 token 带来的 CTC 前缀概率增量这正是束搜索累计打分需要的边际得分。此外该类还实现了两个面向流式解码的方法对应论文 https://arxiv.org/abs/2006.14941 的 Eq.(14)extend_prob(x)当新的语音帧到达时扩展 CTC 后验概率矩阵self.impl.extend_prob(logp)extend_state(state)按新长度扩展 CTC 前向状态。这使得CTCPrefixScorer既能用于离线解码也能被流式streaming解码场景复用。五、N-gram 语言模型打分器基于 kenlm 的外部评分ngram.py 实现了基于 kenlm 的 N-gram 语言模型打分。基类NgrambaseL25-L69在初始化时把 token 列表中的eos映射为 kenlm 的/s加载kenlm.LanguageModel(ngram_model)用self.lm.NullContextWrite(state)初始化空上下文状态。核心方法score_partial_先通过BaseScore让当前前缀y的上文状态前进一步得到out_state再对候选 token 逐个调用self.lm.BaseScore(out_state, self.chardict[j], ...)得到语言模型得分。它派生出两个公开类NgramFullScorerL72-L91实现BatchScorerInterface对整个词表打分paddle.to_tensor(range(self.charlen))作为 next_tokenNgramPartScorerL94-L115实现PartialScorerInterface只对传入的候选子集打分并重写select_state返回原状态kenlm 状态不可按束索引切分直接复用。提供 Full / Part 两个版本的意义在于当 N-gram 被用作主打分器之外的辅助来源时可以根据整体解码策略选择全量打分还是只对 pre-beam 剪枝后的子集打分以平衡精度与速度。六、装配与调用recog_v2 如何把 Scorer 组织进束搜索上述 scorer 的最终装配点在 recog.py 的 recog_v2 中--api v2实验性 API支持任意实现ScorerInterface的模型。核心装配代码逻辑如下# recog_v2 中的 scorer 装配简化自源码 if args.ngram_model: from .scorers.ngram import NgramFullScorer from .scorers.ngram import NgramPartScorer if args.ngram_scorer full: ngram NgramFullScorer(args.ngram_model, char_list) else: ngram NgramPartScorer(args.ngram_model, char_list) else: ngram None scorers model.scorers() # 注意力解码器 模型自带 ctc scorers[lm] lm # RNNLM可选 scorers[ngram] ngram # N-gram LM可选 scorers[length_bonus] LengthBonus(len(char_list)) weights dict( decoder1.0 - args.ctc_weight, ctcargs.ctc_weight, lmargs.lm_weight, ngramargs.ngram_weight, length_bonusargs.penalty, ) beam_search BeamSearch( beam_sizeargs.beam_size, vocab_sizelen(char_list), weightsweights, scorersscorers, sosmodel.sos, eosmodel.eos, token_listchar_list, pre_beam_score_keyNone if args.ctc_weight 1.0 else full, )这段代码清晰展示了各打分来源的权重语义权重键命令行参数含义decoder1.0 - ctc_weight注意力解码器full scorer权重与 ctc 权重互补ctcctc_weightCTC 前缀打分权重1.0时纯 CTC 解码0~1时参与注意力重打分lmlm_weightRNN 语言模型权重ngramngram_weightN-gram 语言模型权重length_bonuspenalty长度惩罚权重作用于LengthBonus的恒定 1.0 得分随后若所有 full scorer 都实现了BatchScorerInterfacebeam_search会被替换为BatchBeamSearch实现以获得向量化性能否则回退到非批量实现recog.py L130-L141。在 beam_search.py 中BeamSearch构造器L84-L124会按权重是否为 0 过滤 scorerw 0 or v is None则跳过按是否实现PartialScorerInterface把 scorer 分成full_scorers与part_scorers两组计算pre_beam_size int(pre_beam_ratio * beam_size)当pre_beam_score_key有效、pre_beam_size n_vocab且存在 partial scorer 时启用 pre-beam 剪枝do_pre_beamTrue搜索开始时对每个 scorer 调用init_state(x)初始化状态。典型配置recog_v2在ctc_weight 1.0时把pre_beam_score_key设为full即先用注意力解码器full scorer对全词表打分并剪枝再由 CTC / N-gram 等 partial scorer 只对剪枝后的候选子集打分最终按权重融合。这完整解释了全量打分 部分打分两级架构的实际运作。七、实战配置参考以 AISHELL-1 为例PaddleSpeech 各示例仓库中已内置了可直接套用的解码配置。以 examples/aishell/asr1/conf/tuning/decode.yaml 为例beam_size: 10 ctc_weight: 0.5 # ctc weight for attention rescoring decode mode.beam_size: 10表示束宽度越大搜索越充分但耗时越高ctc_weight: 0.5表示注意力重打分attention rescoring模式下 CTC 与注意力解码器各占一半权重decoder 1 - 0.5 0.5。模型训练阶段ctc_weight默认取0.3见 examples/aishell/asr1/conf/conformer.yaml 等而解码阶段常调高到0.5附近以获得更好的重打分效果。chunk_decode.yaml与decode.yaml配置一致说明流式 chunk 模型与离线模型共用同一套解码调参思路。如需叠加语言模型可按第六节参数传入--rnnlm指定训练好的 RNNLM、--lm_weight控制其权重--ngram_model指定 kenlm 模型文件、--ngram_weight控制 N-gram 权重、--ngram_scorer full|partial选择全量还是部分打分--penalty控制长度惩罚强度。所有参数最终都会反映到weights字典中参与束搜索的加权融合。八、小结与源码地图PaddleSpeech 的 scorer 体系通过四层接口抽象将全量打分 / 部分打分 / 批量打分三类能力正交组合容纳了注意力解码器、CTC 前缀搜索、RNNLM、N-gram LM 与长度惩罚等多种打分来源并在 beam_search.py 中实现了先全量剪枝、再部分精打分的两级流水线。这种设计使得研究者可以低成本地接入自定义打分器只需实现ScorerInterface相关方法也让解码策略的调优权重、束宽、剪枝比例完全与模型结构解耦。继续深入阅读的源码路径接口定义paddlespeech/s2t/decoders/scorers/scorer_interface.pyCTC 前缀打分算法paddlespeech/s2t/decoders/scorers/ctc_prefix_score.pyCTC scorer 封装paddlespeech/s2t/decoders/scorers/ctc.py长度惩罚paddlespeech/s2t/decoders/scorers/length_bonus.pyN-gram LMpaddlespeech/s2t/decoders/scorers/ngram.py束搜索主体paddlespeech/s2t/decoders/beam_search/beam_search.py解码入口与装配paddlespeech/s2t/decoders/recog.py示例解码配置examples/aishell/asr1/conf/tuning/decode.yaml赞分享人工智能语音音频NLP媒体生成【免费下载链接】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 束搜索解码中的 Scorer 接口体系从 ScorerInterface 到 CTC 前缀打分与 N-gram 语言模型PaddleSpeech 束搜索解码中的 Scorer 接口体系从 ScorerInterface 到 CTC 前缀打分与 N gram 语言模型 Paddl人工智能语音音频NLP媒体生成PaddleSpeech 解码器评分器Scorers模块深度解析从 ScorerInterface 到 CTC 前缀评分与 N-gram 语言模型融合PaddleSpeech 解码器评分器Scorers模块深度解析从 ScorerInterface 到 CTC 前缀评分与 N gram 语言模型融合 P人工智能语音音频PaddleSpeech CTC Prefix Scorer 深度解析U2 混合模型中 CTC 前缀得分器的实现原理与解码应用PaddleSpeech CTC Prefix Scorer 深度解析U2 混合模型中 CTC 前缀得分器的实现原理与解码应用 本篇文章以 PaddleSpe人工智能语音音频NLP媒体生成创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表