语音识别的全程是自动语音识别(Automatic Speech Recognition,ASR),说得多了,就把“自动”省去了,认为“自动”是理所当然的了。语音识别属于序列转换技术,它将语音序列转换为文本序列。大体来说,这是一次搬运,是吧一段话的表现形式从语音编程了文本,所以语音应用开始时是分工明确的,但这显然不符合人类对语音的感知和理解,所以后来的技术也有了不同程度的整合和联合学习。如何实现有效的语音识别,无非是,先确定问题,然后找个模型,最后训好它。
2.1 总体思路
已知一段语音信号,处理成声学特征向量(Acoustic Feature Vector,而不是 Eigenvector)后表示为X= [x1, x2, x3, ...],其中xi表示一帧(Frame)特征向量;可能的文本序列表示为W= [w1, w2, w3, ...],其中wi表示一个词,求W∗= argmaxwP(W|X),这便是语音识别的基本出发点。由贝叶斯公式可知

其中,P(X|W)称之为声学模型(Acoustic Model,AM),P(W)称之为语言模型(LanguageModel,LM),二者对语音语言现象刻画得越深刻,识别结果越准确。化整为零,逐个击破,很符合逻辑惯性,所以大多数研究都把语音识别分作声学模型和语言模型两部分,即分别求取P(X|W )和P(W),并把很多精力放在声学模型的改进上。后来,基于深度学习和大数据的端对端(End-to-End)方法发展起来,它直接计算 P(W|X ),把声学模型和语言模型融为了一体。
对于不同的候选文本来说,待解码语音的概率保持不变,是各文本之间的不变量,所以公式 2.1 中的 P(X) 可以省去不算。
一段语音,经历什么才能变成它所对应的文本呢?语音作为输入,文本作为输出,第一反应是该有一个函数,自变量一代入,结果就出来了。可是,由于各种因素(如环境、说话人等)的影响,同一段文本,读一千遍就有一千个模样,语音的数字化存储也因之而不同,长短不一,幅度不一,就是一大堆数字的组合爆炸,想要找到一个万全的规则将这些语音唯一地对应到同一段文本,这是演算逻辑所为难的;而且常用的词汇量也很庞大,能够拼成的语句不计其数,面对一段语音,遍历搜寻所有可能的文本序列必然无法负担。这样,定义域和值域都是汪洋大海,难以通过一个函数一步到位地映射起来。
如果我们能够找到语音和文本的基本组成单位,并且这些单位是精确的、规整的、可控的,那么二者之间的映射关系会单纯一些。语音,选择的基本单位是帧(Frame),一帧的形式就是一个向量,整条语音可以整理为以帧为单位的向量组,每帧维度固定不变。一帧数据是由一小段语音经由 ASR 前端的声学特征提取模块产生,涉及的主要技术包括离散傅里叶变换和梅尔滤波器组(Mel Filter Bank)等。一帧的跨度是可调的,以适应不同的文本单位。对于文本,字(或字母、音素)组成词,词组成句子,字词是首先想到的组成单位。

至此,语音的基本组成单位有了统一的格式,文本的基本组成单位又是有限集合,问题便在于如何将二者对应起来,图 2.1 归纳了当下常用的路数,不同方法的差别可以简单归结为文本基本组成单位的选择上,语音的建模粒度也随之而改变,图 2.1 中文本基本组成单位从大到小分别是:
• 整句文本,如“Hello World”,对应的语音建模尺度为整条语音。
• 词,如孤立词“Good”、“World”,对应的语音建模尺度大约为每个词的发音范围。
• 音素,如将“World”进一步表示成“/wərld/”,其中的每个音标(类比于音素,语音识别系统中使用的音素与音标有所区别)作为基本单位,对应的语音建模尺度则缩减为每个音素的发音范围。
• 三音素,即考虑上下文的音素,如将音素“/d/” 进一步表示为“{/l-d-sil/, /u-d-l/,...}”,对应的语音建模尺度是每个三音素的发音范围,长度与单音素差不多。
• 隐马尔可夫模型状态,即将每个三音素都用一个三状态隐马尔可夫模型表示,并用每个状态作为建模粒度,对应的语音建模尺度将进一步缩短。
图 2.1 中从“语音”到“文本”的任一路径都代表语音识别的一种实现方法,每种实现方法都对应着不同的建模粒度,这里先做个概览,其中“DNN-HMM”表示深度神经网络-隐马尔可夫模型结构,“CTC”表示基于CTC损失函数的端对端结构,“Attention”表示基于注意力机制的端对端结构,下文将对这几个方法及相关概念进行讲解。
2.2 声学模型 GMM-HMM
2.2.1HMM
声学模型解决的问题是如何计算 P(X|W ),它是语音识别的“咽喉”之地,学好了发音,后面的事才能顺理成章。首先要考虑的是,语音和文本的不定长关系使得二者的序列之间无法一一对应,常规的概率公式演算就不适宜了。隐马尔可夫模型(Hidden Markov Model,HMM) 正好可以解决这个问题。比如P(X|W) =P(x1, x2, x3|w1, w2) 可以表示成如图 2.2 隐马尔可夫链的形式,图中w是 HMM 的隐含状态,x是 HMM 的观测值,隐含状态数与观测值数目不受彼此约束,这便解决了输入输出的不定长问题,并有

其中,HMM 的初始状态概率(P(w1))和状态转移概率(P(w2|w1)、P(w2|w2))可以用常规的统计方法从样本中计算出来,主要的难点在于 HMM 发射概率(P(x1|w1)、P(x2|w2)、P(x3|w2))的计算,所以声学模型问题进一步细化到HMM 发射概率(Emission Probability)的学习上。

另一个问题是,基本单位的粒度大小。对于语音,帧的粒度可通过调节处理窗口的宽窄来控制。对于文本,字词级别的粒度过于宽泛笼统,于是我们往下分解,如图 2.1 所示:字词是由音素(Phone)组成的;音素的上下文不同,同一个音素就有了不同的变异体,比如 /l-d-sil/ 与 /u-d-l/ 是一对亲兄弟却是两家子,记为三音素(Triphone);每个三音素又可以用一个独立的三状态 HMM 建模,这样,文本方面的基本单位降解为微小的 HMM 状态(与图 2.2 中的 HMM 不同,其每个状态对应一个词)。由于很多三音素并未在语料中出现或数量不多,并且可以通过决策树(Decision Tree) 共享三音素的状态,所以对于共有 N 个音素的语言,最终保留下来的三音素状态数量远小于3N3,一般为几千,并把他们叫做 Senones, 而每一帧与每一个Senone的对应关系表示为三音素 HMM 的发射概率P(xi|sj),其中sj表示第j个 Senone,与之对应的帧(xi)的跨度通常取为 25ms,帧间步移常取为 10ms,由于跨度大于步移,相邻帧的信息是冗余的,这是跳帧训练和解码的一个出发点。图 2.3 进一步展示了Phone、Triphone、Senone三者之间的关系,其中Senone是借助数学模型定义出来的音素变种,没有直接的听觉感受,音素“/sil/”无实际发音,仅表示静音、字间停顿或无意义的声音,#N 是Phone 的个数,#N3、#3N3分别是 Triphone、Senone 的可能数量级(真实有效数量远少于数量级)。

文本 Sentence 到 Word,Word 到 Phone,Phone 到 Triphone,每个 Triphone 都用一个HMM建模,将所有相关的HMM按发音顺序首尾相连组成的HMM 长链则表示Sentence,所以 P(X|W) 就是这条HMM长链产生观测序列 X 的概率。因为 Phone 个数是固定的,系统中所有的 Triphone HMM 所构成的基本集合也是固定的,不同 W 对应的长链不同则在于长链所包含的 Triphone 不同,但它们所使用的“字典”是相同的。用 p 表示 Phone、c 表示Triphone,可知一个 p 可以对应多个 c, P(X|W) 有类似如下的转换关系:

从公式 2.5 转到 2.6中,p1的上下文音素分别是“/sil/”和p2,p2的上下文音素分别是p1和p3,以此类推。虽然声学模型的建模粒度细化了,但问题仍是给定 HMM,求产生某个观测序列的概率,只是 HMM 更长一些而已,归根结底仍需要对发射概率P(xi|sj)建模( HMM 的转移概率也需要学习,但相对于发射概率影响小得多,甚至可以使用预设值)。
逐层分解一件事物直至根本,把握住每个关键节点之后,拼装回去,整体又回来了,但理解得更透彻了。上述语音识别系统声学模型的设计正是一个从大到小、从宏观到微观的拆解过程,而语音识别系统的解码是要回去的:从 Frame 到 Senone,从 Senone 到Triphone ,再到Phone ,最后到Word 直至Sentence。
文章来源微信公众号清语赋,作者:汤志远
