编者按:环信开源国内首本免费深度学习理论和实战专著《深度学习理论与实战:提高篇 》,内容涵盖听觉,视觉,语言和强化学习,七百多页详尽的理论和代码分析。本文节选自《深度学习理论与实战:提高篇 》一书,原文链接http://fancyerii.github.io/2019/03/14/dl-book/ 。作者李理,环信人工智能研发中心vp,有十多年自然语言处理和人工智能研发经验,主持研发过多款智能硬件的问答和对话系统,负责环信中文语义分析开放平台和环信智能机器人的设计与研发。

深度学习.jpg

我们可以根据说话的过程把语音识别的各个单元(unit)分成如下图所示的层次结构。这是一个生成的过程。最上面是utterance,也就是一句话(不一定是语言学上的完整一句话),比如这里的”No right”。往下一层是词(word),比如这里是两个词”No”和”right”。再往下是subword(比如因子),单词”No”根据发音词典可以分解为两个因子[“n”, “oh”]。再往下就是因子的HMM(比如用三状态的HMM来表示一个因子)。最后一层是声学模型,它根据状态生成观察。

发声过程从上到下输入是utterance W,输出是声学特征X。而识别的过程正好反过来,我们需要寻找:

潮科技行业入门指南 | 深度学习理论与实战:提高篇(4)——基于HMM的语音识别

上式中P(W)P(W)就是语言模型,而P(X|W)P(X|W)就是声学模型,通常会包括发音模型,HMM-GMM模型,当然也可以用DNN来替代GMM变成HMM-DNN模型。


潮科技行业入门指南 | 深度学习理论与实战:提高篇(4)——基于HMM的语音识别图:语音单元的层次结构

连续语音识别

简介

前面介绍的HMM和GMM可以用来做孤立词的识别,比如识别0-9十个数字,每个数字对应一个3状态的HMM,发射概率可以是GMM模型。通过训练数据我们可以使用前向后向算法训练HMM-GMM的参数,而预测的时候我们可以对十个模型分别计算后验概率:

P(O|Mi)∝P(O|Mi)P(Mi),i=0,1,..,9


其中P(O|Mi)P(O|Mi)可以通过前向算法计算出来,而P(Mi)P(Mi)就是10个数字的先验概率,可以简单的认为它们是等概率的。然后我们选择概率最大的i作为识别的结果。

那么怎么处理包含多个词的句子呢?当然最简单的是先进行词的切分,然后分别识别每一个词。但是这显然不好,首先我们说话不是一个词一个词来说的,要正确切分每一个词是很困难的;其次同音或者发音类似的词很多,我们需要考虑整个句子根据上下文才能正确的识别每一个词。

为了实现连续的识别,我们可以把每个词的HMM拼接成大的HMM,训练的时候我们是知道句子的每一个词的,因此我们可以用词的HMM拼接成句子的HMM。预测的时候也是类似的,根据语言模型,遍历所有可能的句子,拼接得到这些句子的HMM。然后用HMM-GMM计算声学模型概率,再加上语言模型的概率得到句子的最终概率,最后选择概率最大的那个句子。当然这个搜索空间是非常大的,我们需要近似的搜索算法,后面的解码器部分会介绍。这里我们先只考虑声学模型的训练部分。

但是每个词都使用一个HMM来建模有很多缺点:词很多,这需要很多个HMM模型;很多词在训练数据中出现很少,也就是数据稀疏的问题;为了识别一个新词需要重新训练声学模型,比如加入一个新的人名。

音子模型

为了解决上面的问题,我们通常对更细粒度的子词单元进行HMM建模。虽然词很多,但是组成词的因素是不多的,比如英语的音素也就是四五十个左右。因此我们可以对每一个phone建立一个HMM模型,而词的HMM就可以使用它的phone的HMM拼接起来。当然这就需要知道每个词由哪些phone组成,最常见的是人工来编纂发音词典,比如下面是CMU发音词典的两个词:

潮科技行业入门指南 | 深度学习理论与实战:提高篇(4)——基于HMM的语音识别

这样给定一个词,我们就知道它的音子序列,然后我们通过把每个音子的HMM拼接起来就可以得到这个词的HMM,类似的我们把很多词的HMM拼接起来就可以得到一个句子的HMM。

使用发音词典有新词的问题,比如词典里没有”balisong”这个词,那么我们无法识别这个词。但是对于表音的语言(比如英语),我们是可以”猜测”出未知词的发音的。这个时候我们可以使用一个模型来学习怎么把词变成因子序列,这个模型通常被成为Grapheme-to-Phoneme (G2P)模型。我们可以根据发音词典来学习发音规律,这样新词来了之后就可以猜测可能的发音。这显然可以使用我们熟悉的Seq2seq模型来解决,有兴趣的读者可以试试g2p-seq2seq

对于每个音子,我们通常使用三个状态的HMM来建模。如下图所示,音子/ih/可以用三状态的HMM建模。这样一个词,比如six,我们就可以把4个音素/s ih k s/拼接得到一个大的HMM,如下图所示。


潮科技行业入门指南 | 深度学习理论与实战:提高篇(4)——基于HMM的语音识别图:音子ih的HMM模型

潮科技行业入门指南 | 深度学习理论与实战:提高篇(4)——基于HMM的语音识别图:词six的HMM模型

上下文相关的(Context Dependency/CD)音子模型

但是一个音子在不同的上下文会有不同的发音,这就是所谓的协同发音(Coarticulation)。为了解决这个问题,我们通常建立上下文相关的音子模型,最常见的就是考虑一个音子的左右两个音子,这就是triphone模型。我们通常使用类似l-x+r来表示当前考虑的音子是x,它左边的音子是l而右边是r。根据triphone是否跨越词的边界又可以分类为词内的(word-internal) triphones和跨词的(cross-word) triphone。比如句子”don’t ask”,如果使用词内的triphone,则可以表示为:

潮科技行业入门指南 | 深度学习理论与实战:提高篇(4)——基于HMM的语音识别

sil表示silence,我们可以理解为一个特殊的词,它不考虑上下文。n-t表示当前音子是t而左边是n,ah+s表示当前音子是ah而右边是s。

如果使用跨词的triphone,则应该可以表示:

潮科技行业入门指南 | 深度学习理论与实战:提高篇(4)——基于HMM的语音识别

那么有多少个triphone呢?假设音子有40个,那么理论上可能有403=64,000403=64,000,实际上英语可能出现的triphone会有50,000左右。假设我们使用3状态的HMM,每个状态使用10个分量的GMM模型,那么总共有1.5M个高斯分布。再假设我们使用39维的MFCC特征,高斯分布的协方差矩阵是对角阵,那么每个高斯有39(均值)+39(协方差矩阵)=78个参数。78 * 10+10(GMM的混合参数)=790个参数。那么总共有50,000 * 3 * 790=118M参数。

我们的训练数据很难覆盖这么多的参数,很多参数对应的训练数据没有或者很少,因此很难准确的估计其参数。为了解决这个问题,我们会使用参数共享(Parameter Sharing)的方法。通常有两种参数共享方法:共享模型(Sharing models)和共享状态(Sharing states)。

共享模型就是把比较类似的triphone聚类在一起,得到的triphone通常叫做Generalized triphone,如下图所示。


潮科技行业入门指南 | 深度学习理论与实战:提高篇(4)——基于HMM的语音识别图:共享模型

共享状态就是更加细粒度的共享,它是把每个triphone的每个状态进行聚类,如下图所示。

潮科技行业入门指南 | 深度学习理论与实战:提高篇(4)——基于HMM的语音识别

图:共享状态

聚类通常使用语音决策树(Phonetic Decision Tree)算法,这是一种自顶向下(分裂)的方法。刚开始同一个音素的所有triphone都在根节点,然后每个节点都会根据问题进行分类,常见的问题类似于:

  • 左边是不是一个鼻音?

  • 右边是不是摩擦音?

下图是语音决策树的一个示例。

潮科技行业入门指南 | 深度学习理论与实战:提高篇(4)——基于HMM的语音识别图:语音决策树示例

决策树可以一直分裂下去直到每个节点只包含一个triphone,这显然没有意义。我们需要有一个停止分裂的标准,一种标准就是分裂之后要比分裂前得到的模型要好?什么叫好呢?那就是新模型在训练数据上的似然概率要比分裂前好,而且增量ΔΔ越大越好,如果没有增量那么就停止分裂。另外就是问这些问题的顺序,我们会选择似然增量最大的那个问题。