分享

干货总结 | 58同城语音识别技术的探索和实践

 520jefferson 2020-08-01

导读

语音是58同城用户之间的重要沟通媒介,58同城C端用户和B端用户之间可以通过网络音视频通话、电话建立连接,58同城数千名销售和客服人员会通过呼叫中心与客户进行电话沟通,这些场景下会产生大量的语音数据,这些语音数据可以通过语音识别技术转换为文本,并做进一步挖掘,以提取有价值的数据。本次议题将首先介绍语音识别在58同城的应用场景以及语音数据采集标注,然后详细介绍基于Kaldi的Chain Model模型的原理和实践,最后介绍我们在端到端语音识别方面的探索。

嘉宾介绍:周维,58同城AI Lab算法资深工程师,2018年5月加入58,目前主要负责语音识别算法研发,曾先后从事智能客服、智能外呼、智能写稿中的NLP算法研发。2016年硕士毕业于中国科学院大学,曾就职于菱歌科技,从事自动问答和社媒舆情相关的算法研发。

目录

1、58同城场景下的语音识别

2、Chain Model实践

3、端到端语音识别探索

 1   58同城场景下的语音识别

上图是58平台和语音相关的整体业务流程。首先b端商家会在平台相应的板块发布帖子,c端用户浏览这些帖子,如果有意向就会通过帖子上的联系方式联系 b端商家。此外,58有大量的销售和客服,销售会去联系平台的潜在客户,邀请他们来使用58平台发帖,客服人员会为这些商家和客户提供服务。

58同城的呼叫中心支撑着数千名销售客服人员的工作,每年的通话量是上亿的,通话的时长有数百万小时。基于这些数据,我们的一个很重要的应用就是销售客服的智能质检。

另外一个场景就是c端用户和b端商家之间的隐私通话,这里面列举了一些例子,包括二手车、租房、二手房。二手房详情页上有电话按钮,用户可以直接与商家沟通,我们拿到这个电话录音之后,可以分析用户的意图、意向。除了电话之外,58平台的一个很重要的沟通渠道是微聊,微聊是一款聊天交互工具,用户可以和商家进行文字的沟通,也可以进行语音和语音短消息的沟通,这也是我们的主要分析对象。

总结一下,我们语音数据的主要来源有三个方面:呼叫中心(销售客服通话)、电话平台(隐私通话)、微聊平台(语音消息)。基于这些庞大的语音数据我们会进行很多的标签的挖掘和语音分析工作。为此,我们打造了两套语音分析的系统:灵犀语音分析平台和智能外呼平台。

灵犀语音分析平台,是基于语音分析技术和自然语言处理技术,实现智能质检、情绪识别、性别识别和用户画像构建等功能,从而为用户打标和分类;智能外呼平台,是用外呼机器人按照话术给用户拨打电话,用户的语音以流式的方式进入到我们的系统,然后分别经过VAD、ASR、NLU和对话管理,从而实现机器人以语音交互的方式完成销售、通知、回访等功能。

而语音识别的效果是下游任务能够顺利完成的前提,所以我们打造这样一个语音识别的引擎是至关重要的。接下来简单介绍下我们语音识别服务的大概流程。

首先现阶段的语音识别引擎解决的主要是录音文件识别的问题,我们拿到一个录音文件之后,先经过预处理进行一些合法性的检查,接下来会进行音频转换、采样率转换和声道判断等。之后对转换后的录音做VAD和说话人分离,得到切割之后的语音片段,然后解码服务分别对这些短语音片段进行解码,就得到了对应每个片段的文本内容。拿到文本内容之后,会经过后处理模块,因为ASR的结果通常是没有标点的,所以需要后处理来打标点。打标点之后的文本内容,会交给下游的NLP的任务。

58场景下的语音识别存在着很多困难。首先我们的场景非常复杂,包含招聘、黄页、汽车、房产等业务,每一种业务场景的通话信道、专有词汇、表述方式都是不同的,所以需要我们的模型具有很强的泛化能力。

另外用户在打电话的时候,周围的通话环境是多变的。有些是在工厂打电话,能听到很多敲击的声音,有些是在地铁站或者公交车站,能听到站台播报的声音,有些在商场,还有些在打电话的过程中,能听到背景有电视剧声音,台词也会被识别进来,这也是我们识别用户语音带来很大的困难。

最后一个难点就是我们的服务是针对全国各地用户,这些数据覆盖了全国各地的口音,这就需要我们的模型来适应这样的情况。而最好的解决方式,就是对于我们自己的数据进行采集和标注,所以我们开发了语音识别的标注系统。

我们标注各个业务场景的数据,让模型尽量适应多变的信道和复杂的口音。此外,对于标注文本,我们会做新词挖掘和语言模型的训练,以让模型可以掌握各个业务特定的表达方式。这些标注数据在实际业务中起到了大约10~20点的提升,可见场景数据标注的作用是非常大的。

 2   Chain Model实践

语音识别的任务是输入一段录音,输出录音内容对应的文字。通常我们会先对录音或音频分帧处理,输入语音信号就变成了一段音频的帧序列。因此语音识别的本质其实就是输入一个帧序列,输出一段文字序列这样一个Seq2Seq任务。语音识别相对于其他机器翻译这样的NLP的任务,它本身是有一定难度的。比如同样一个人在同样环境下说同样的话,它的音频的信号是完全不一样的。图上右边这两句“您好”它的信号的波形是完全不同的。还有同样的文字,它在音频当中所覆盖的帧的长度以及位置也是不相同的。另外输入帧序列的长度通常要远远大于输出文字的长度。这些都是语音识别模型要解决的基本问题。

语音识别通常可以用右侧的公式来描述,w表示单词序列,x表示声学特征序列。语音识别所解决的就是给定x,找到让条件概率最大的的w序列。我们使用贝叶斯定理将它分成两部分:第一部分是给定w求 x的条件概率,这部分是由声学模型来建模的。第二部分是w序列本身的概率分布,这部分是由语言模型来建模。

传统的语音识别是以HMM为基础来建模的,整个流程如图所示。我们先拿到一段音频,进行分帧加窗等步骤。然后对每一帧提取一个声学特征,可以使用mfcc或者fbank,得到声学特征序列。声学模型把声学特征序列作为输入进行打分。此外我们会事先准备好语言模型和发音词典,以此构建解码图,将语言模型、发音词典的分数和声学模型打分结合起来,在解码图上运行解码算法。

语音识别的目的是为了得到当前语音信号的文字描述。语言模型所描述的本质上是一句话当中词和词之间共现的概率。为了让语音识别系统知道每个单词的发音,需要将文字表示为音素,将单词逐个去发音词典中查找,就得到每个单词的音素序列,从而将单词序列转化为音素序列。中文的音素其实就是拼音的声母、韵母和声调。刚才说到的音素序列其实是单音素序列,在实际情况中每个音素的发音是会受到前后音素的影响而改变的。因此我们会将每三个音素作为一个整体,作为一个三音素来建模。而每个三音素又可以表示为三个发音状态(HMM状态),分别表示这个三音素的发音前期、中期和后期。这样我们的句子就可以和HMM模型的状态序列映射在一起了。HMM模型的观测序列是分帧之后的声学特征序列,这里我们使用声学模型来对 HMM的发射概率进行建模。

最经典语音识别模型就是GMM-HMM模型,HMM的每个状态会对应一个GMM模型,GMM模型用于模拟状态序列到观测序列的发射概率。因为帧通常要比这个状态序列长,所以首先要做对齐,即要确定哪个帧对应的是哪个状态。对齐后,根据这个状态对应的GMM模型来对这帧的发射概率建模。然后在解码图上运行解码,将解码结果和标注结果比较,从而不断更新GMM模型以及对齐方式。

上图的例子是在单音素情况下的解码过程。纵轴是解码空间,每个点是一个HMM状态。本例中解码空间是由“你”“好”两字的单音素的三状态构成,比如“好”的h包含 h_s1、h_s2、h_s3三个状态。横轴是声学特征帧序列,每个帧驱动一次解码。解码从左下角start开始,对于第一个帧,有两个状态可以选择,分别是两个声母的1状态;当接收到第二帧时,当前状态可以自跳,也可以跳转到下一个状态。当一个字或音素结束后,会跳转到下一个字的声母1状态,直到所有的帧都看过后,就得到了多个解码路径,通过评估这些路径,找到得分最高的对应的词序列,就是解码结果。

在解码之后,本质上可以拿到每个帧对应的状态。因为在做声学模型时的一个重要任务就是对齐,要确定哪些帧和哪些状态是相对应的。解码过程之后,就拿到了帧和状态之间的对齐关系,所以整个训练的过程就是不断进行解码,来调整对齐的方式,同时更新GMM模型。

以上是单音素解码过程,在实际中会用到比较多的是三音素(triphone,chain 中使用biphone),还要考虑到语言模型中的概率和发音概率,因此需要将他们整合在一起得到解码图,这一整合的过程使用wfst实现,组合后的解码图称为HCLG。

实际的解码图是很大的,不方便做精细的解码,所以会在第一次解码时,用beam search 保留n-best路径,构成小解码图,再用小解码图做rescore等操作,这个小解码图称为lattice。

前面说的都是基于GMM的声学模型,现在都在使用深度学习来做声学模型;我们知道GMM-HMM是生成模型,发射概率是生成概率,也就是给定状态求特征的条件概率,而DNN输入是特征,输出状态,他得到的是判别概率,这里使用贝叶斯公式做变换,将生成概率用判别概率来表示,这样就可以在声学模型里面使用DNN网络。因为搜索空间比较大,所以我们会做状态绑定,即多个发音相似的状态会共用同一个GMM模型。对于 DNN我们会把有相似发音的状态作为同一个输出节点,因此,绑定后的状态数就是DNN输出层维度。

Kaldi里面所有的DNN模型都是使用了这种渐进式的模型迭代方式。首先在训练数据中抽取一部分训练一个GMM单音素模型,然后用这个小模型来进行强制对齐。再利用对齐结果去训练一个比较大的三音素的模型。再用三音素模型的强制对齐结果作为DNN的标注样本,使用交叉熵损函数训练DNN模型。

实际上在训练DNN-HMM的过程中,我们使用比较多的训练思想是序列区分性训练。

左图是一个极大似然训练的过程,是在标注数据的图中解码,最大化标注路径的似然度。比如标注文本的路径是A,它的概率是P(A),它的似然度就是logP(A)。因为渐进式的训练,一些假设未必是对的,所以最大似然很难得到最优解。

区分性训练的目标函数分成两部分,分子和分母。在最大化分子标注路径的同时,尽可能的减小容易混淆的其他路径的得分,所以将解码图中所有路径作为分母,去优化比值。而使用整个解码图的复杂度是很高的,一种优化是lattice-based的方法,即分子不变,分母变成当前数据的解码lattice。

上图列出了交叉熵损失函数和几种常见的区分性训练损失函数。

Lattice-based训练方式有一个缺点,就是没办法保证模型一定是训练比较好的。而我们拿到的分母的Lattice一旦生成之后,它其实是固定化的,也就是说我们可能用了一个不太好的假设去做它的目标函数。

Lattice-free和Chain Model

为了解决这个缺陷问题,就有了Lattice-free这样一个训练方式。Lattice-free在分母上是有变化的,lattice-based是用标注数据解码之后的Lattice当作分母,而这里是训练一个音素级别的语言模型,再用这个语言模型来构造一个小的基于音素级别的小的解码图HCP。HCP本身是一个完整的解码图,所以把它作为分母,就避免了基于一个不太好的模型去解码的问题。

我们使用的Chain model就是基于这样的Lattice-free训练思想来实现的,流程如上图所示。

Chain model中的模型通常是TDNN,如左图所示。在TDNN里面也有一个下采样的机制,就是可以在层与层之间进行跳帧,就是可以只用红色的这部分来进行模型的裁剪,而忽略掉蓝色这部分。在实际操作过程中也可以用一个前置的CNN来进行一个下采样的过程。

Chain Model有两个目标函数:Lattice free和CE交叉熵。这里如果只用Lattice free这种方式是比较容易过拟合的,所以Chain model采用了一种多任务训练方式,将两种目标函数进行融合,同时进行训练。

Chain model用到跳帧的策略,即每3帧来作为一个输入,如果帧移是10ms,跳帧后相当于变成30ms的帧移。这样可以优化网络的训练速度,同时优化识别性能。

在发音词典和语言模型中的优化工作

新词挖掘和语言模型的优化流程如图所示,首先拿到标注数据的文本,先进行新词挖掘。挖掘出来的新词会经过人工审核,然后做数字和英文标准化。其中,数字标准化是将阿拉伯数字表示成汉字的形式,如“100”作为电话号读是“一零零”,作为金额读的是“一百”,我们会根据上下文进行数字的标准化。此外,我们训练了一个 Seq2Seq的g2p的模型,实现多音字情况的单词转音素序列的功能。

语言模型方面,我们在拿到标注文本之后会进行去标点、断句等工作。然后,训练两个模型,第一个分词语言模型,第二个是分字语言模型,在使用时,对他们做插值融合。实验表明,分字语言模型的使用,对整体效果提升是比较大的。在发音词典当中,很难去覆盖我们很多业务场景的专有名词,所以很多情况下它可以是以字来进行输出。而我们如果只用分词去训练语言模型的话,这样的词在解码图当中是没有新词作为输出的,所以它是发不出这个单词的音的,所以我们用分字语言模型去做优化。

下图是我们自研语音识别的效果对比。

 3   端到端语音识别探索

端到端语言模型通常是有两种套路,一个是Seq2Seq,我们前面说语音识别的任务本质上就是一个Seq2Seq的任务。我们用一个编码器-解码器的结构建模。流程是编码器先把所有的声学特征都读进来得到编码向量表示,编码结果经过Attention进行逐字的输出,可见其编码和解码的过程是不同步的。

Seq2Seq是依靠Attention的权重分布来对齐的。这就带来了单调对齐的问题。我们知道人在读一句话的时候,一定是从左到右按照顺序去读的,所以我们在Attention的时候,在解码y1的时候不可能去参考后面y2、y3的发音,因为它还没有读出来。所以一个好的Attention对齐图案是一条斜线。但是 Seq2Seq本身不是这样的,它在解码y1的时候可以考虑整个声学特征序列。基于 Seq2Seq比较典型的一个模型就是LAS模型。

另外一种端到端的思路就是CTC的方法,CTC是和声学特征序列同步进行解码,就是每输入一个特征,就输出一个 label,所以它的输入和输出序列长度是相同的。但是我们前面说输入输出的长度明显差别是很大的,所以在CTC里面引入了一个 blank的符号,带有blank的文本序列称为CTC的一个对齐结果。拿到对齐之后,首先对进行符号去重,再删掉blank,就恢复到标注的文本了。

CTC的训练比较巧妙,如上图所示,定义了三种跳转方式,根据前后向算法,构造目标函数,然后使用梯度下降更新模型参数。

我们实验使用的端到端模型是基于Transformer+CTC结构。它的主体部分是一个Seq2Seq的模型,编码器部分前面会加两层的卷积CNN层来做下采样。Seq2Seq的主要问题就是对齐问题,该模型使用Attention和CTC进行多任务解码,然后将两个解码器的解码结果进行融合,共同的训练Seq2Seq模型,以利用CTC的对齐优势帮助模型训练。解码时,模型以Shallow Fusion的方式实现外挂RNN语言模型,以提升解码性能。

端到端的实验结果如下图所示。

AI Lab 招聘信息

58同城AI Lab 社招/校招/实习生 招聘,欢迎加入

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多