Riva (WFST 解码器) 中基于类的 n-gram 语言模型支持#

语言模型用于语音识别任务,以帮助消除歧义,判断在给定词序列之后,哪个词更可能出现。传统的 n-gram 模型对在给定 (n-1) 个词序列之后出现某个词的概率进行建模。

但是,在许多领域中,很可能存在性质相似的词序列。

例如,考虑短语“我想从纽约飞往西雅图”“我想从伦敦飞往巴黎”,这两个句子的概率通常仅取决于人们在这些地方之间飞行的频率
地方。 否则,在涉及航班预订的领域中,这两个句子出现的概率是相等的。

这就需要支持构建考虑词类的 n-gram 模型。 词类也可以被视为实体或实体类型(如在 NER 中),但在本质上更通用。

WFST 解码#

使用 n-gram 支持词类并非易事。 一种替代方法可能是使用 BNF 语法生成。 但是,这很容易增加 LM 的大小,并且仍然可能导致多词词类出现问题。

另一种方法是使用加权有限状态转换器 (WFST)。 语音识别中使用的 WFST 由三个主要组件组成

  • 语法 WFST (G.fst) - 语法 WFST 对语言/领域中的词序列进行编码。 一般来说,这基本上是表示为加权有限状态接受器的语言模型。

  • 词典 WFST (L.fst) - 词典 WFST 对标记序列(音素/BPE/WPE 或其他 CTC 单元)到相应词的映射进行编码。

  • 标记 WFST (T.fst) - 标记 WFST 将帧级 CTC 标签序列映射到单个词典单元(音素/BPE/WPE 或其他 CTC 单元)。

这三个 WFST 与其他操作组合在一起以形成 TLG.fst。 操作顺序为 T min ( det ( L G ) ),其中

  • 指的是组合操作

  • min 指的是最小化

  • det 指的是确定化

有关更多信息,请参阅 Mohri、Pereira 和 Riley 的“使用加权有限状态转换器的语音识别”(载于 Springer SpeechProcessing and Speech Communication 手册,2008 年)。

在 WFST 框架中支持类语言模型#

WFST 框架中对类语言模型的支持可以概括为修改 G.fst 以支持接受器中引用词类的路径。 这要求

  • 词典包含来自语言模型和每个词类中的条目。 这很重要,因为否则词类中的词将无法被识别。

  • n-gram 模型应具有从词类语法构建的相关短语。 例如,在上面的示例中,词类语法将是“我想从 #entity:city 飞往 #entity:city。 其中 #entity:city 是对应于有机场的城市的词类的标签。 这可以通过以下两种方式实现

    • 从包含标准文本以及词类标签的文本构建语言模型

    • 两个 LM 的 n-gram LM 插值/混合,一个来自标准文本,另一个来自特定领域的语法。

后一种选择可以在领域内和领域外 LM 之间提供更好的加权。 有关使用 KenLM 进行 LM 模型插值的教程,请参阅“如何训练、评估和微调 n-gram 语言模型”。 或者,SRILM(需要许可证)也可用在此处。

在 WFST 框架中支持词类的过程基本上涉及将表示类标签的弧替换为从词类中存在的实体创建的 FST。 给定包含词类标签 (#entity:<class>) 的 G.fst 和包含类实体列表的文件(文件名 <class>.txt)。 实体列表不限于词,也可以是短语。

例如,在上面的示例中,cities.txt 至少应包含以下内容

$> cat city.txt
london
new york
paris
seattle

创建支持词类的 TLG.fst 的过程#

从 https://github.com/anand-nv/riva-asrlib-decoder/tree/class_lm 检出 class_lm 分支。 以下脚本在 src/riva/decoder/scripts/prepare_TLG_fst 目录路径中可用。

  • 从 arpa 文件生成词典、标记/单元列表和实体列表。 这是使用 lexicon_from_arpa.py 脚本完成的。 命令的语法如下

lexicon_from_arpa.py --asr_model <nemo_模型路径> --lm_path <arpa_文件路径> --grammars <包含语法的文件夹路径> <units_txt_path:output> <lexicon_path:output> <classlabels_path:output>

这将生成单元(标记)列表、词典和词类列表(用作消除歧义符号)。

  • 生成 FST、T.fstL.fstG.fst,扩展并组合以形成 TLG.fst

mkgraph_ctc_classlm.sh --units <units_txt_path> --extra_word_disamb <classlabels_path> <lexicon_path>  <arpa_文件路径> <lang_folder_path:output>

成功运行时,上述命令将在 <lang_folder_path> 中生成一个图形文件夹,名称为 graph_CTC_<lm_name>,其中包含所有与使用 WFST 解码相关的文件。

评估#

evaluate_nemo_wfst.py 脚本可以帮助评估 WFST 解码器,然后再在 Riva ServiceMaker 构建中使用。 这对于调试 TLG.fst 的任何问题非常有用。

该脚本可以按如下方式运行: ./evaluate_nemo_wfst.py <model_path> <graph_path> <path_containing_audio_files> <results_txt_file:output>

在 Riva 中部署#

生成的 TLG.fst 可以与 Riva 中的 Kaldi 解码器一起使用。 要使用生成的 TLG.fst 构建 Riva ASR 服务,请运行

# Syntax: riva-build <task-name> output-dir-for-rmir/model.rmir:key dir-for-riva/model.riva:key
! docker run --rm --gpus 0 -v $MODEL_LOC:/data $RIVA_CONTAINER -- \
    riva-build speech_recognition \
        /data/rmir/asr_offline_conformer_ctc.rmir:$KEY \
        /data/$MODEL_NAME:$KEY \
        --offline \
        --name=asr_offline_conformer_wfst_pipeline \
        --ms_per_timestep=40 \
        --chunk_size=4.8 \
        --left_padding_size=1.6 \
        --right_padding_size=1.6 \
        --nn.fp16_needs_obey_precision_pass \
        --featurizer.use_utterance_norm_params=False \
        --featurizer.precalc_norm_time_steps=0 \
        --featurizer.precalc_norm_params=False \
        --featurizer.max_batch_size=512 \
        --featurizer.max_execution_batch_size=512 \
        --decoder_type=kaldi \
        --decoding_language_model_fst=/data/graph/TLG.fst \
        --decoding_language_model_words=/data/graph/words.txt \
        --kaldi_decoder.asr_model_delay=5 \
        --kaldi_decoder.default_beam=17.0 \
        --kaldi_decoder.max_active=7000 \
        --kaldi_decoder.determinize_lattice=true \
        --kaldi_decoder.max_batch_size=1  \
        --language_code=en-US \
        --wfst_tokenizer_model=<far_tokenizer_file> \
        --wfst_verbalizer_model=<far_verbalizer_file> \
        --speech_hints_model=<far_speech_hints_file>