Kaldi简单解码器(SimpleDecoder)

Kaldi简单解码器(SimpleDecoder)

  • 总述

本节我们讲述kaldi中一个最简单的解码器,实现这个解码器的类是SimpleDecoder,理解了这个解码器,也就打下了解码搜索的基础,其他的解码器方法也与其类似,目录在kaldi/src/decoder/simple-decoder.h。解码图数据结构依赖于openfst,基本上可以通过名称猜到表达的含义。

  • 分析

上一节已经知道,解码的过程就是在解码图中搜索最优路径的过程,解码图的构建也在上一节做了简单的介绍,它就是语言模型、词典、上下文音素和HMM构成的一个大的资源图。关于具体如何去做以后我们结合脚本再进行细讲。

我们知道,WFST解码图中,信息都在边上、节点上没有信息(终止节点除外),边上输入表示建模单元、输出表示词、权重表示概率(语言模型概率+转移概率+词典发音概率)。

在解码前,需要先加载解码图,设定剪枝系数beam,传进解码器中,调用构造函数

SimpleDecoder(const fst::Fst<fst::StdArc> &fst, BaseFloat beam): fst_(fst), beam_(beam) { }

bool Decode(DecodableInterface *decodable);解码一整句话。

函数bool ReachedFinal() const;表示是否有节点到达终止节点。

函数bool GetBestPath(Lattice *fst_out, bool use_final_probs = true) const;获取最后输出路径。

函数BaseFloat FinalRelativeCost() const;会返回全局最优路径和到达终止节点的最优路径的差值。

函数void InitDecoding();初始化解码器,一句新的语音开始,要初始化解码器。

函数void AdvanceDecoding(DecodableInterface *decodable,int32 max_num_frames = -1);解码一段语音数据。

函数int32 NumFramesDecoded() const { return num_frames_decoded_; }返回已经解码的帧数。

类class Token;在解码过程中挂载在某个状态上的令牌,保存当前解码信息。

函数void ProcessEmitting(DecodableInterface *decodable);每帧调用,扩展实边(ilabel!=0)。

函数void ProcessNonemitting();每帧调用,扩展空边(ilabel==0)。

成员变量unordered_map<StateId, Token*> cur_toks_;当前帧活跃的节点和对应的令牌。

成员变量unordered_map<StateId, Token*> prev_toks_;上一帧活跃的节点和对应的令牌。

成员变量const fst::Fst<fst::StdArc> &fst_;解码图

成员变量BaseFloat beam_;剪枝系数

函数static void ClearToks(unordered_map<StateId, Token*> &toks);清空令牌。

函数static void PruneToks(BaseFloat beam, unordered_map<StateId, Token*> *toks);剪枝令牌

 

下面解析几个主要的方法:

先来看一个整的解码过程

bool SimpleDecoder::Decode(DecodableInterface *decodable) {

  //初始化解码器

  InitDecoding();

  //帧同步解码,循环次数为帧数

  while( !deco

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值