kaldi(3) SimpleDecoder:ProcessEmitting

复制代码
void SimpleDecoder::ProcessEmitting(DecodableInterface *decodable) {
    int32 frame = num_frames_decoded_;
    // Processes emitting arcs for one frame.  Propagates from
    // prev_toks_ to cur_toks_.
    // 处理一帧。从prev_toks_传递到cur_toks_
    // 在调用本函数之前,cur_toks_.swap(prev_toks_)已完成了prev_toks_的填充
    // 设置一个界限,用于剪掉分数过低的令牌
    
    double cutoff = std::numeric_limits<BaseFloat>::infinity();
    // 对prev_toks_即上一帧的全部带令牌的状态进行遍历
    for (unordered_map<StateId, Token*>::iterator iter = prev_toks_.begin();
           iter != prev_toks_.end();
           ++iter) {
        StateId state = iter->first;
        Token *tok = iter->second;    //获取当前状态的令牌 
        KALDI_ASSERT(state == tok->arc_.nextstate);
        // 遍历从当前状态出发的每一个跳转 
        for (fst::ArcIterator<fst::Fst<StdArc> > aiter(fst_, state);
             !aiter.Done();
             aiter.Next()){
              const StdArc &arc = aiter.Value();
              if (arc.ilabel != 0) {  // propagate..只处理输出标签不为<eps>的情况
              // 调用Decoderable的LogLikelihood()函数计算声学分 
            BaseFloat acoustic_cost = -decodable->LogLikelihood(frame, arc.ilabel);
            // 代价=历史代价+图权重-声学分 
            double total_cost = tok->cost_ + arc.weight.Value() + acoustic_cost;
            // 如果代价过大,则剪掉该路径 
            if (total_cost >= cutoff) continue;
            // 更新界限值,使剪枝阈值在一个合理的范围内 
            if (total_cost + beam_  < cutoff)
                  cutoff = total_cost + beam_;
            // 基于当前令牌,建立新令牌 
            Token *new_tok = new Token(arc, acoustic_cost, tok);
            unordered_map<StateId, Token*>::iterator find_iter
                = cur_toks_.find(arc.nextstate);
            if (find_iter == cur_toks_.end()) {
                // 下一个状态如果还没有令牌,那么将此令牌放到下一个状态上 
              cur_toks_[arc.nextstate] = new_tok;
            } else {
                  if ( *(find_iter->second) < *new_tok ) {
                      // 如果下一个状态令牌不如新令牌代价小,则用新令牌替换下一个状态的令牌 
                    Token::TokenDelete(find_iter->second);
                    find_iter->second = new_tok;
                  } 
                else {
                      // 如果下一个状态的令牌比新令牌代价小,则删除新令牌 
                    Token::TokenDelete(new_tok);
                }
            }
          }
        }
    }
    num_frames_decoded_++;
}
 
复制代码

 

posted @   智人心  阅读(131)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
历史上的今天:
2020-09-11 linux kaldi
点击右上角即可分享
微信分享提示