西工大 ASLP 实验室在 WeNet 中开源基于 CPPN 的神经网络热词增强语音识别方案

news2024/9/21 4:31:30

语境偏置(Contextual biasing)旨在将语境知识集成到语音识别(ASR)系统中,以提高在相关领域词汇(俗称“热词”)上的识别准确率。在许多ASR场景中,待识别语音中可能会包含训练数据中数量很少或完全没出现的短语,例如一些领域专有名词、用户通讯录中的人名等,这些短语的识别准确程度对用户体验或下游任务的影响很大,但对于在通用数据上训练ASR系统来说又难以完全正确识别。因此语境偏置方法具有重要价值,旨在提升在这些“热词”上的识别准确率。

西工大音频与语音处理研究组(ASLP@NPU)近期在语音研究顶级会议 INTERSPEECH2023发表了论文题目为“Contextualized End-to-End Speech Recognition with Contextual Phrase Prediction Network”。该论文提出了一种基于热词短语预测网络的深度热词增强方法,该网络利用热词编码来预测语音中的热词,并通过计算偏置损失来辅助深度偏置模型的训练。所提出的方法能够应用在多种主流端到端ASR模型上,显著改进模型在热词数据上的识别准确率。

该方案的代码主要由该论文的一作黄凯勋同学完成,目前已开源在WeNet社区,详见:https://github.com/wenet-e2e/wenet/pull/1982

基于规则的热词增强

WeNet 之前实现的热词方案为基于规则的热词增强,即在解码过程中匹配到热词列表中的词时,给予该解码路径一定的奖励,这样含热词的搜索路径概率更大,更容易被识别出来。详见:

WeNet 热词增强 2.0 强势来袭

WeNet 更新:支持热词增强

虽然该方案在一般情况下也能有不错的处理能力,但对于训练中少见或没有见过的词即 rare word 的识别效果却非常很差。本质上因为该方法为浅融合(shadow fusion,或者后融合)的热词方案,在训练中没有见过,很难预测出来,在解码候选路径中根本没有出现,所以再怎么奖励也无济于事。而下文介绍的神经网络的热词则为深融合(deep fusion,或者前融合)则可以非常有效的解决 rare word 的问题,同时在常见热词识别也有更好的效果。

神经网络热词增强

基于神经网络的热词增强在端到端ASR模型中引入了一组独立的偏置模块来建模、集成热词信息,将热词增强的过程放到了神经网络模型推理的过程中。相比于传统的基于解码图的热词增强方案,神经网络热词增强使用上十分灵活,对于较小的热词列表可以取得优于解码图增强方案的效果,并且对于训练集中从未出现的罕见词也有着良好的增强效果。

近年来,神经网络热词增强方法得到了快速的发展。在2018年,谷歌首先提出了 CLAS 模型 [2],在 LAS 模型上通过全神经网络的方式集成热词信息。CLAS 的模型结构如下图所示,其中包含的两个偏置模块为:

  • 热词编码器(Bias Encoder):通过 RNN 对热词信息进行编码,将不等长的热词编码为相同维度的热词嵌入。

  • 热词偏置层(Attention):包含一个多头注意力层,使用音频编码作为 Query,热词编码作为 Key 和 Value,查询与当前音频相关的热词,提取热词感知编码。

图片

后续的神经网络热词增强研究基本沿袭自 CLAS,分为“编码热词、查询音频相关热词并集成信息”两步。在其他 ASR 模型上,提出了适用于 RNNT [3] 以及 CIF [4] 模型的神经网络热词增强模型,在神经网络增强方法上也产生了许多变体,如 TCPGen [5] 和 NAM [6] 等。

CPPN 论文介绍

之前的神经网络热词增强研究大多探索在如 RNNT 等 ASR 模型上实现或提升热词增强的效果,缺少在 AED 模型上有效的纯神经网络热词增强方法。因此,我们最初的动机就是寻找 AED 模型上有效的神经网络热词增强方案,并且由于我们使用 WeNet 框架进行实验,基于 attention rescore 解码依靠 CTC 后验的特点,我们希望能够在 Encoder 部分就能进行神经网络热词增强。

在实验最初阶段,我们尝试将一个基础的包含热词编码器以及热词偏置层的热词增强模块加入 AED 模型的 Encoder 中进行训练,但是模型却完全没有学习到热词增强的能力,推理过程中加入热词信息几乎不会对结果产生任何影响。我们分析认为这很可能是由于对 AED 模型而言,热词增强模块更难学习到热词编码与音频编码之间的联系。如果仅依靠 ASR 的损失函数进行训练,在没有对热词增强任务给出明确的监督的情况下,模型就会倾向于直接放弃热词增强模块的输出。因此我们研究的重心便转移到了寻找一个对于热词增强任务有效的监督损失上。

最直观的想法就是让热词增强模块直接预测出语句中包含的热词,但热词模块的输入输出长度与音频编码长度相同,这就存在编码长度与语句中包含的热词短语长度之间的不匹配。我们实验发现 CTC 损失可以很好的解决这个问题,并且由于 WeNet AED 模型的实现中 Encoder 本身也依靠 CTC 损失进行辅助训练,在预测热词任务上同样使用 CTC 损失可以让热词增强模块更好的契合 Encoder 的输出。在此基础上,我们提出了基于热词短语预测网络(Contextual Phrase Prediction Network, CPPN)的热词语音识别方案。热词增强模型结构如下图所示。

图片

图(c)是我们在 AED 模型基础上实现的热词增强模型结构,由于仅对模型 Encoder 部分进行了修改,因此没有画出 Decoder 部分的结构,这样的热词增强方案同样适用于仅包含一个 Encoder 的 CTC 模型。在 AED 热词增强模型中,热词增强相关的模块有:

  • 热词编码器(Context Encoder):我们使用 BLSTM 作为热词编码器对热词短语进行编码。

  • 热词偏置层(Biasing Layer):如图(b)所示,查询与当前音频相关的热词,提取热词感知编码。

  • 组合器(Combiner):拼接音频编码与热词感知编码,并通过一个线性层集成信息。

  • 热词短语预测网络(CPP Network):如图(a)所示,包含两个线性层,其中第二个线性层与 Encoder 的 CTC 线性层共享参数。热词短语预测网络使用热词感知编码作为输入,对语句中包含的热词短语进行预测,并使用 CTC 损失监督训练。例如对于语句标签为“我想去西工大学习语音识别”,如果“西工大”和“语音识别”是热词,则热词短语预测网络的标签为“西工大语音识别”。

图(d)是在 RNNT 模型基础上实现的热词增强模型结构,我们在 CATT [7] 热词增强方案的基础上添加了热词短语预测网络,相比于 AED 模型,在标签编码器(Label Encoder)后也添加了热词偏置层。

基于神经网络的热词增强方案还存在对于热词短语列表的大小较为敏感的问题,由于模型依靠注意力机制查找与音频关联的热词短语,当给出的热词列表过大时,注意力就会较为分散,影响热词增强的效果。因此,我们引入了一种两阶段的热词短语筛选算法[8],首先在不计算热词增强模块的情况下计算模型encoder部分的输出,使用 CTC 后验分别计算后验和置信度(PSC)和序列顺序置信度(SOC)以筛选出最可能出现在音频中的热词,然后构建成更小的热词列表再进行神经网络热词增强。

更多方案细节可参考推文:

Interspeech2023 | 基于热词短语预测网络的热词语音识别

模型实现

  1. 大部分热词增强模块的实现都位于 transformer/context_module.py 中,我们在 ContextModule 类中分别声明了热词编码器、热词偏置层、组合器、热词短语预测网络,以及增强任务的 CTC 损失。相比于论文中的实现,在此处我们将组合器替换为了更加简单的通过一个线性层后直接与音频编码相加的形式,这样能使 ASR 模型与热词模块更加解耦,并且经测试效果基本没有区别。并且我们还额外设置了一个热词增强权重用于控制热词增强的程度,热词感知编码先会与该权重相乘后再与音频编码相加。

class ContextModule(torch.nn.Module):
    """Context module, Using context information for deep contextual bias

    During the training process, the original parameters of the ASR model
    are frozen, and only the parameters of context module are trained.

    Args:
        vocab_size (int): vocabulary size
        embedding_size (int): number of ASR encoder projection units
        encoder_layers (int): number of context encoder layers
        attention_heads (int): number of heads in the biasing layer
    """
    def __init__(
        self,
        vocab_size: int,
        embedding_size: int,
        encoder_layers: int = 2,
        attention_heads: int = 4,
        dropout_rate: float = 0.0,
    ):
        super().__init__()
        self.embedding_size = embedding_size
        self.encoder_layers = encoder_layers
        self.vocab_size = vocab_size
        self.attention_heads = attention_heads
        self.dropout_rate = dropout_rate
        # 热词编码器
        self.context_extractor = BLSTM(self.vocab_size, self.embedding_size,
                                       self.encoder_layers)
        self.context_encoder = nn.Sequential(
            nn.Linear(self.embedding_size * 4, self.embedding_size),
            nn.LayerNorm(self.embedding_size)
        )
        # 热词偏置层
        self.biasing_layer = MultiHeadedAttention(
            n_head=self.attention_heads,
            n_feat=self.embedding_size,s
            dropout_rate=self.dropout_rate
        )
        # 组合器
        self.combiner = nn.Linear(self.embedding_size, self.embedding_size)
        self.norm_aft_combiner = nn.LayerNorm(self.embedding_size)
        # 热词短语预测网络
        self.context_decoder = nn.Sequential(
            nn.Linear(self.embedding_size, self.embedding_size),
            nn.LayerNorm(self.embedding_size),
            nn.ReLU(inplace=True),
        )
        self.context_decoder_ctc_linear = nn.Linear(self.embedding_size,
                                                    self.vocab_size)
        # 热词 CTC 损失
        self.bias_loss = torch.nn.CTCLoss(reduction="sum", zero_infinity=True)
  1. 我们将热词短语筛选部分的代码放到了 /utils/context_graph.py 中实现,该文件原本负责实现基于解码图的热词增强,包含有解码时所用的热词列表的信息,因此适合在此处进行热词短语筛选并将 tensor 形式的热词列表传递给热词增强模块。

class ContextGraph:
    
    def get_context_list_tensor(self, context_list: List[List[int]]):
        """Add 0 as no-bias in the context list and obtain the tensor
           form of the context list
        """

    def two_stage_filtering(self,
                            context_list: List[List[int]],
                            ctc_posterior: torch.Tensor,
                            filter_window_size: int = 64):
        """Calculate PSC and SOC for context phrase filtering,
           refer to: https://arxiv.org/abs/2301.06735
        """
  1. 训练时热词采样的代码位于 /dataset/processor.py 的 context_sampling 与 context_label_generate 方法中。在训练时,我们从每条话语中随机抽取数个长度随机的短语作为该条话语的热词,每个 batch 抽取出的热词短语再加上一些干扰短语(来自之前 batch 的热词)共同构成该 batch 的热词列表。

def context_sampling(data,
                     symbol_table,
                     len_min,
                     len_max,
                     utt_num_context,
                     batch_num_context,
                     ):
    """Perform context sampling by randomly selecting context phrases from the
       utterance to obtain a context list for the entire batch

        Args:
            data: Iterable[List[{key, feat, label}]]

        Returns:
            Iterable[List[{key, feat, label, context_list}]]
    """

def context_label_generate(label, context_list):
    """ Generate context labels corresponding to the utterances based on
        the context list
    """

实验结果

我们在 Librispeech test other 测试集上进行测试,使用 [9] 中给出的热词列表,热词列表可以从该链接获取:https://github.com/facebookresearch/fbai-speech/tree/main/is21_deep_bias

我们使用 WeNet 开源的 Librispeech 预训练 AED 模型进行实验,冻结原本 ASR 模型的参数,仅对热词增强模块训练 30 epoch 后取 3 个 epoch 平均得到的模型作为结果。在训练时,需要关闭 use_dynamic_chunk 流式训练选项,开启该选项会使得热词增强效果变差。经过测试非流式训练得到的模型对非流式和流式解码具有基本一致的热词增强性能。训练好的热词增强模型可以从该链接下载:https://huggingface.co/kxhuang/Wenet_Librispeech_deep_biasing/tree/main

除了词错误率 (WER) 之外,我们分别使用 U-WER 和 B-WER 来评估非热词部分与热词部分的字错误率,实验的结果如下。

非流式推理:

MethodList sizeGraph scoreBiasing scoreWERU-WERB-WER
baseline///8.775.5836.84
context graph38383.0/7.755.8324.62
CPPN3838/1.57.935.9225.64
context graph + CPPN38382.01.07.666.0821.48
context graph1003.0/7.325.4523.70
CPPN100/2.07.085.3322.41
context graph + CPPN1002.51.56.555.3317.27

表中 context graph 表示 WeNet 中基于解码图的热词增强方法。在使用较大热词列表(3838)的情况下,基于解码图的方法效果较好,而使用较小热词列表(100)的情况下,CPPN 的增强效果则更好。而无论热词列表大小,以合理的增强权重和分数同时使用两种方法时都能够取得比单一方法更好的效果。

热词列表(3838)的情况下,基于解码图的方法效果较好,而使用较小热词列表(100)的情况下,CPPN 的增强效果则更好。而无论热词列表大小,以合理的增强权重和分数同时使用两种方法时都能够取得比单一方法更好的效果。

小热词列表实验同时还表现出了非热词部分 WER 下降的情况,这是由于经过热词增强,模型在波束搜索时能够选择到包含正确热词并且非热词部分更加准确的路径。

流式推理 (chunk 16):

MethodList sizeGraph scoreBiasing scoreWERU-WERB-WER
baseline///10.477.0740.30
context graph1003.0/9.066.9927.21
CPPN100/2.08.866.8726.28
context graph + CPPN1002.51.58.176.8519.72

在流式推理的结果中,使用CPPN也有显著的 B-WER 改进,与非流式推理热词增强效果基本一致。

参考文献

[1] Kaixun Huang, Ao Zhang, Zhanheng Yang, Pengcheng Guo, Bingshen Mu, Tianyi Xu, Lei Xie: Contextualized End-to-End Speech Recognition with Contextual Phrase Prediction Network. INTERSPEECH 2023

[2] Golan Pundak, Tara N. Sainath, Rohit Prabhavalkar, Anjuli Kannan, Ding Zhao: Deep Context: End-to-end Contextual Speech Recognition. SLT 2018

[3] Mahaveer Jain, Gil Keren, Jay Mahadeokar, Geoffrey Zweig, Florian Metze, Yatharth Saraf: Contextual RNN-T for Open Domain ASR. INTERSPEECH 2020

[4] Minglun Han, Linhao Dong, Shiyu Zhou, Bo Xu: Cif-Based Collaborative Decoding for End-to-End Contextual Speech Recognition. ICASSP 2021

[5] Guangzhi Sun, Chao Zhang, Philip C. Woodland: Tree-Constrained Pointer Generator for End-to-End Contextual Speech Recognition. ASRU 2021

[6] Tsendsuren Munkhdalai, Khe Chai Sim, Angad Chandorkar, Fan Gao, Mason Chua, Trevor Strohman, Françoise Beaufays: Fast Contextual Adaptation with Neural Associative Memory for On-Device Personalized Speech Recognition. ICASSP 2022

[7] Feng-Ju Chang, Jing Liu, Martin Radfar, Athanasios Mouchtaris, Maurizio Omologo, Ariya Rastrow, Siegfried Kunzmann:

Context-Aware Transformer Transducer for Speech Recognition. ASRU 2021 [8] Zhanheng Yang, Sining Sun, Xiong Wang, Yike Zhang, Long Ma, Lei Xie: Two Stage Contextual Word Filtering for Context bias in Unified Streaming and Non-streaming Transducer. INTERSPEECH 2023

[9] Duc Le, Mahaveer Jain, Gil Keren, Suyoun Kim, Yangyang Shi, Jay Mahadeokar, Julian Chan, Yuan Shangguan, Christian Fuegen, Ozlem Kalinli, Yatharth Saraf, Michael L. Seltzer: Contextualized Streaming End-to-End Speech Recognition with Trie-Based Deep Biasing and Shallow Fusion. INTERSPEECH 2021

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1005645.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

双系统ubuntu20.04(neotic版本)从0实现Gazebo仿真slam建图

双系统ubuntu20.04(neotic版本)从0实现Gazebo仿真slam建图 昨晚完成了ROS的多机通讯,还没来得及整理相关操作步骤,在进行实际小车的实验之前,还是先打算在仿真环境中进行测试,熟悉相关的操作步骤,计划通过虚拟机&…

写好技术书籍

写好技术书籍 目录概述需求: 设计思路实现思路分析1.如何写好对应的书籍 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,chal…

多模态情感学习技术

近年来随着深度学习的发展,多种模态的语义表示的壁垒被打破,计算机可以处理和理解的向量形式成为多模态的主要表示形式。 多模态学习技术不是自然语言处理领域独有的技术,在图像处理、视频处理以及智能语音等领域中都能找到多模态相关技术的…

数字电源常用传递函数

文章目录 PID控制器二阶广义积分器PR谐波抑制器陷波器全通滤波器重复控制器连续域离散化的几种方法 有S域和Z域 PID控制器 传递函数: bode图: m代码 %% PID控制器 % 连续域 kp 100; ki 10; kd 10; Ts 1/50000; num [kd kp ki]; den [1 0]; Gpi…

在使用 gson 时,数字被自动转为 double 类型

背景 在将一个 JsonObject 转成 Map<String, Object> 的时候&#xff0c;数字全部被转成了 double 类型&#xff0c; 如下所示&#xff0c;年龄从 2 变成了 2.0&#xff0c;身高正常显示 98.2&#xff0c;登记时间成了 1.694533284627E12 /*** name小红* record_time1.6…

UG\NX二次开发 复制3元素的double数组到另一个数组 UF_VEC3_copy

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 简介: UG\NX二次开发 复制3元素的double数组到另一个数组 UF_VEC3_copy。仔细看第二段代码 。 效果: 代码: #include "me.hpp"void ufusr(char* param, …

pandas 筛选数据的 8 个骚操作

日常用Python做数据分析最常用到的就是查询筛选了&#xff0c;按各种条件、各种维度以及组合挑出我们想要的数据&#xff0c;以方便我们分析挖掘。 东哥总结了日常查询和筛选常用的种骚操作&#xff0c;供各位学习参考。本文采用sklearn的boston数据举例介绍。 from sklearn …

3基于MATLAB的齿轮啮合仿真,可根据需要调节齿轮参数,实现齿轮啮合转动动态过程。程序已调通,可直接运行。

基于MATLAB的齿轮啮合仿真&#xff0c;可根据需要调节齿轮参数&#xff0c;实现齿轮啮合转动动态过程。程序已调通&#xff0c;可直接运行。 3matlab齿轮啮合仿真动态啮合 (xiaohongshu.com)

动态负荷对电力系统摆幅曲线的影响研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

springboot使用freemarker导出word

springboot使用freemarker导出word 一、需求说明二、制作模板文件1.修改word留下占位符并另存为.xml文件2.将xml文件后缀名改为.ftl3.打开ftl文件格式化内容4.将占位符替换成变量 三、代码实现1.引入依赖2.将模板引入resource下3.编写word导出工具包4.创建接口调用 一、需求说明…

eslint写jsx报错

eslint写jsx报错 ChatGPT提示 在写JSX时&#xff0c;ESLint可能会报出一些语法错误&#xff0c;这些错误通常是由于ESLint默认配置中不支持JSX语法导致的。为了解决这些错误&#xff0c;我们需要在ESLint配置文件中启用对JSX语法的支持。 首先&#xff0c;需要安装eslint-pl…

100道基于Android毕业设计的选题题目,持续更新

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 大家好&#xff0c;我是程序员徐师兄、今天给大家谈谈基于android的app开发毕设题目&#xff0c;以及基于an…

苹果数据恢复软件:Omni Recover Mac

Omni Recover是一款十分实用的Mac数据恢复软件&#xff0c;为用户提供了简单、安全、快速和高效的数据恢复服务。如果您遇到了Mac或iOS设备中的数据丢失和误删情况&#xff0c;不要着急&#xff0c;不妨尝试一下Omni Recover&#xff0c;相信它一定会给您带来惊喜。 首先&…

【Bun1.0】使用 Bun.js 构建快速、可靠和安全的 JavaScript 应用程序

bun.js Bun 是一个现代的JavaScript运行环境&#xff0c;如Node, Deno。主要特性如下: 启动速度快。更高的性能。完整的工具&#xff08;打包器、转码器、包管理&#xff09;。 官网 https://bun.sh 优点 与传统的 Node.js 不同&#xff0c;Bun.js 提供了一些新的特性和功…

第8章_freeRTOS入门与工程实践之内存管理

本教程基于韦东山百问网出的 DShanMCU-F103开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id724601559592 配套资料获取&#xff1a;https://rtos.100ask.net/zh/freeRTOS/DShanMCU-F103 freeRTOS系列教程之freeRTOS入…

《Linkerd 2.0:下一代服务网格的探索》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

C++下基于模拟退火算法解决TSP问题

一、原理 首先明确TSP问题的目标是什么&#xff0c;假设当前有3个城市&#xff0c;需要你从第一个城市开始&#xff0c;遍历所有城市&#xff0c;然后回到初始位置&#xff0c;要求总路径最短。这个时候就需要计算每个城市之间的两两距离&#xff0c;然后按顺序确定一条最短路…

【Unity】2D 对话模块的实现

对话模块主要参考 【Unity教程】剧情对话系统 实现。 在这次模块的构建将基于 unity ui 组件 和 C#代码实现一个从excel 文件中按照相应规则读取数据并展示的逻辑。这套代码不仅能实现正常的对话&#xff0c;也实现了对话中可以通过选择不同选项达到不同效果的分支对话功能。 …

机器视觉康耐视visionpro-CogFitLineTool拟合直线错误上的理解

视频详细解答&#xff1a;康耐视VisionPro高级脚本系列教程-2.拟合指教脚本遍历编写 什么是直线&#xff1f; 直线&#xff1a;那么直线是由无线的点组成的。特点是无端点&#xff1b;不能度量&#xff0c;两边无限延长。错误示例子如下&#xff1a; 首先上面是错误的理解&…

UG\NX CAM二次开发 设置工序切削区域 UF_CAMGEOM_append_items

文章作者:代工 来源网站:NX CAM二次开发专栏 简介: UG\NX CAM二次开发 设置工序切削区域 UF_CAMGEOM_append_items 效果: 代码: static int init_proc(UF_UI_selection_p_t select, void* user_data) { int errorCode = 0; int num_triples = 1;//UF_UI_mas…