关于语音识别的一些入门理解
引入
1969年, 贝尔实验室的john peers在一封公开信中, 做出了一个悲观到刻薄的评论, 他将语音识别技术比作把水转化为汽油, 而他认为, 当时人们研究这项技术唯一的动机就是搞钱, 但现在我们知道已经不必再讨论能不能做, 而是怎么做的。
想要知道机器如何识别语音, 首先我们要理解什么是声音?
声源振动挤压空气产生声波进入耳朵, 带动耳膜震动, 感知到声音。
机器的耳朵是麦克风, 声波带动麦克风上的膜片振动, 膜片带动套在磁铁上的线圈震动, 产生的声音的模拟信号。
而计算机是数字系统, 需要对模拟信号进行采样。
人耳能听到的频率范围, 在20HZ到20KHZ。
根据香农奈奎斯特采样定理, 采样频率大于等于最大频率的两倍即可, 一般是44.1KHZ。
这样我们就得到了一段声音, 在计算机中的数字化格式,也就是我们经常看见的声波图。
语音识别就是把一段声波识别为对应的文字。
频率、频谱图和特征提取
这是一个频率为261.625Hz的正弦波,发出的声音是1。
而这是一个频率为293.6648Hz的正弦波,发出的声音是2。
当我们在听声音,我们在听什么呢?
我们可以把振幅变大或变小,声音的大小发生了变化,但do还是do re还是re。
所以我们在听声音时,实际上在听其中的频率。
换句话说,声音的信息蕴含在频率之中。
但问题是从波形图中很难看出频率的信息,这是哆来咪发唆拉西七个音的波形,或许还能区分得开。
同时发出哆咪嗦的音,也就是C和弦。同时发出嗦发拉的是DM和弦。从波形图中看频率的事情就变得困难起来。
但我们可以换一种描述声音的方式,横坐标表示频率值,纵坐标表示频率的强度。那么这些声音信号所蕴含的频率信息,便可以一眼看出,即使是同时包含三个频率的和弦音,也能一眼看出。这样表示声音的图像成为频谱图。
而完成这种转换的就是信号处理领域,非常常用的傅立叶变换,工程实践中一般使用快速傅立叶变换FFT。
反过来说,傅立叶变换告诉了我们这样一个事实:一个信号可以表示为许多不同频率和强度信号的叠加,即使是这样一个非周期不规则的信号。
所以在做语音识别之前,为了更好地分析一段语音的信息,需要把波形图转化为频率相关的频谱图。
当然,一般不会直接对整段语音做傅立叶变换,而是把它截成小段,以确保不会错过其中的细节信息(语音是短时平稳信号)。一般用一个长度为25ms的窗口,从头开始截取25ms的语音信息,成为第一帧,然后向后滑动10ms,再截取第二帧,再向后滑动10ms,截取第三帧,以此类推,这样一个一秒的语音就被截成了100帧。
截取出所有帧后,接下来就是对每一帧的波形信号进行FFT变为频谱图。
当然人们向来是好奇的,他们想要看看把所有真的频谱放在一起,诊断语音在转换后是什么样子。方法也很简单,比如第一帧横坐标表示频率,纵坐标表示该频率信号分量的强度,那强度除了用纵坐标的值来表示,用不同的颜色似乎也可以。比如我们用从黑到黄表示不同大小的值,对应到一个颜色,这样就可以把曲线上每个频率对应的强度都转化成一个颜色,得到一个色条。其他帧也是如此。
我们再建立一个坐标系,把第一帧的色条放在第一帧的位置,把第二帧的色条放在第二帧的位置,以此类推。
最后就形成了一个叫做语谱图的东西,横坐标表示第几帧,纵坐标表示这一帧中蕴含哪些频率,而颜色则表示这些频率信号的强度。
不过到此还未结束,根据人类发声和听觉的特性,还需要对原始频谱进行三角滤波,然后取对数,再经过DCT变换,这个过程被称之为MFCC特征提取。
最终的效果就是,把每一帧的频谱转化为一个39维的特征向量。
一段语音信号最终也就被转化成了一个特征向量序列,最后的特征向量序列才是要识别的数据。
语音识别的思想
当我们设计一个只能识别”hi”、”hello”和”world”的系统时,首先录制了一些这些单词的语音。经过MFCC提取出特征向量序列,作为模板放进这个系统中。这样,对一个新的信号做预测时,就和模板做对比。也就是求解带预测语音的特征向量序列和这些模板中的向量序列的距离,从而得到相似度。相似度最大的便是识别的结果。
但直接和模板进行比较,一看就很不高级啊,不是主要是效果不好。不过这个想法的意义在于,虽然那些真正可用的识别模型和算法很复杂,但基本思路与此并无区别。而把这个想法用一个精简的数学公式来表达,就是给定一个X出现W的概率。X表示声音的特征,W表示某个词,P表示概率。
$W^{*}=argmax P(W|X)$
利用概率统计学中的贝叶斯公式。因为我们要找W和X无关,所以分母P(X)的可以直接忽略。就可以把这个问题转化为两个子问题:
P(X|W)表示一个单词发出某段语音信号的概率,称为声学模型。P(W)表示一个词出现的概率,称之为语言模型。这两个模型就构成了一个语音识别系统。
声学模型
从上个世纪80年代开始,一直到本世纪初,一种被称之为Gmm-Hmm的方案始终占领着升学模型的主导地位。以识别”hi”、”hello”和”world”这三个词为例。首先我们采集这些词大量的语音数据,但不再作为比较的模板,而是把它们作为训练数据。给每个词训练一个p of x given w模型(P(X|W))。训练完成后,当我们将这三个模型中输入一段新的语音信号,每个模型就会给出一个概率值。
以”hi”这个词举例,我们来详细地研究这些特征向量。
39维的向量并不便于作图和理解,所以从现在开始到最后,我们都假设这些向量是二维的。如果我们把这些特征向量都绘制在一张平面直角坐标系上,你会发现有的地方密集,有的地方稀疏。这样我们就可以使用一个高斯模型,去拟合这些数据的分布,得到一个概率密度函数。第三个维度就表示这段语音是”hi”这个词产生的概率高低。
在由”hi”的训练数据形成的模型中,如果一段带预测语音的特征向量,在这些密集的区域,则大概率是”hi”,如果在稀疏的区域,则小概率是”hi”。
但事情往往不会这样简单,比如”hello”,这个词在训练数据上的分布是这样的,肉眼可见的是有两个密集区域。一个高斯分布可能不太合适,那就再加一个高斯,做出两个鼓包的模型,这就是高斯混合模型。当然也有可能是三个、四个或者五个等等。这个模型的训练方法,在训练数据上使用聚类算法就好。
在利用训练数据得到每个词的GMM模型之后,现在要识别一段新的语音。首先通过MFCC把这段语音转成特征向量序列,然后再把特征向量丢进每个词的GMM模型中,计算出每个词发出这段语音的概率,找到概率最大的即可。
不过你可能已经发觉得蹊跷,每门语言中的字词数量太多了。
以英文举例,现代英语的词汇量已经达到了几十万,给每个词都建立模型显然不现实,而且一个词的发音时间很长,发出的音也很多变,所以直接对词建立GMM模型往往效果很差。
但我们在英语课上学过一种叫做音标的东西。虽然英语词汇的数量几十万,但发音音素的数量却是固定的48个。
所以我们可以把单词”hi”拆分为”h”和”i”;”hello”拆分为/h/,/ə/,/l/,/əʊ/。
这样我们只需要给这些因素建立GMM模型,来识别一段语音中有哪些因素就好。
不过人们往往把音素分为更小的单位,因为人们发现,不同音素后面接其他不同的音素时有一点不同。同样前面结合也会影响它的发音。所以把它前后的因素都考虑进去,形成一个更小的识别单位称为三音素。
不过实际上在做识别时,每个三音素还是被拆成了若干个更小的单位,这个单位称之为状态。
下面的例子是三个状态,我们给每个状态建立GMM模型。
然后用识别出来的状态拼接成三音素,用三音素拼接成音素,再把音素拼接成词的音标。
而对于中文,汉语拼音的23个声母和24个韵母,相当于音素的角色。
到此似乎万事俱备,但思考一个问题,每个状态之间真的就像图像画的那样毫无关系吗?
声音作为一个序列信息,前后之间必然会有某种联系,也就是说一个三音素中,每个状态之间也会有一定的转移概率,当然也有可能转移到自己,而原地打转。
那这些概率值是多少呢,不知道需要通过大量的语音数据训练出来,这实际上就是模型中的隐马尔可夫模型。
HMM的细节以及在连续语音识别中的过程,这里用单个因素为例,简单的描述一下大致的流程。
这些是隐藏状态,它们之间存在转移概率,而下面的GMM仍旧在计算,每个状态产生某阵语音信号特征向量的概率。不过不再直接用来预测,而是作为HMM模型需要的发射概率,用大量的语音数据完成。
以马尔可夫模型和高斯混合模型的训练之后,预测时搜索语音的特征向量序列,经过高斯混合模型,计算出以马尔可夫模型的发射概率。
而后以马尔可夫模型,利用状态转移概率和发射概率,搜索出概率值最大的因素。
所以以马尔可夫模型为何适合语音识别问题呢,我们举个例子。
比如有人语速快,有人语速慢。在引入隐马尔可夫模型之后,因为状态转移概率可以原地打转,所以即使是拖长音状态,多驻留一会儿就可以应对,也就增强了不同发音风格的解析能力。
这就是流传许久的GMM-HMM模型。
当然这只是一个声学模型,最后识别出来的结果只是音标或者中文的拼音,但一个拼音可能对应很多个字。
语言模型
比如一段语音经过GMM-HMM声学模型之后,识别结果是”LAO YUE HAN NIU BI”。
那如何得到最终的文字呢,这就要利用语言模型部分。所谓语言模型就是分析一句话像不像话。
比如把它识别为”捞月汉扭臂”,这就不像人话,语言模型可能给出0.001的概率值。
而”老约翰牛逼”则很像人话模型,可能给出0.99的概率值。
结合语言模型最后得到识别的结果。
这就是从上个世纪80年代开始到本世纪初,语音识别主流的技术线路。
深度学习带来的改变
但随着深度学习的兴起,逐渐出现了只要能用上深度学习的最后就一定会用上深度学习这个现象。
这件事情在语音识别领域中发挥的淋漓尽致。
一开始深度学习还很保守,只想取代前面的部分,也就是MFCC。
既然MFCC是在把一段声音信号转化成特征向量,而且MFCC里的手段都是人们手工建立的,那训练一个深度神经网络,让它自己提取出特征向量不香吗?
再然后深度学习的触角又升到了GMM。既然GMM是一个因素发出某个语音的概率模型,那么训练一个深度神经网络,让它自己拟合出概率值不香吗?这样原来的GMM-HMM模型就变成了DNN-HMM模型。
另一方面,除了声学模型、语言模型这边,像n-gram这样传统的语言模型也在被取代。
以循环神经网络为代表的深度学习模型正在飞速的取代传统方式。
最后深度学习彻底摊牌,不装了。
隐马尔可夫模型也别留着了,直接all in deep learning。
这样整个语音识别系统,就变成了深度学习的天下,比如基于循环神经网络的LAS模型,以及CTC,RNN-T等等。
我们说基于GMM-HMM模型的传统语音识别系统中有声学模型、语言模型。
实际上在因素拆解时还要有语言学的音素词典,这些部分各自独立训练,优化目标各不相同,所以把它们连接在一起,必然会导致识别精度的损失。而深度学习可以直接在神经网络上训练P of W given X这个模型,最终的输出不再需要先划分为音素,再组成拼音,再转化成文字,而是直接输出文字结果。
这就是所谓的端到端的识别框架,输入语音经过模型直接识别出文字,甚至不局限于识别。
比如输入一段英文直接输出中文的翻译结果,也就是说,把翻译功能也在深度神经网络中给训练出来。
端到端的框架,直接针对最终的目标优化模型,省略了中间的转换和连接,有更好的表现。
而深度学习作为一种强大的方法论,使用起来也极具想象力。这里有一个比较有意思的想法,把语音识别问题转化为图像识别问题。
我们再来看看语谱图,这些是理解万岁的语谱图,而这些是你好世界的语谱图。
而这是图像识别中经典的猫狗识别问题。
想必你已经看出了端倪所在。既然语谱图已经很好地体现了一段语音的特征,有经验的语言学家甚至能直接从其中看出说话的内容,那么为什么不能像识别一只猫或者一只狗那样,直接去识别这些语谱图呢?
细细说来,它们之间相似的地方非常多。比如这是一只中华田园猫,这是一只加菲猫,这是一段男性产生的理解万岁的离谱图,而这是女性产生的同一类识别对象,都可能有不同的个体特征。这是在草地上的猫,这是在室内的猫,而这是在商场噪音下的理解万岁,这是在火车站环境噪音下的理解万岁,同一类识别对象都可能有不同的噪音背景。
所以把语音识别问题转化为图像识别问题是一个很妙的想法。比如科大讯飞在2010年提出的DFCNN,利用了图像识别领域中非常流行的卷积神经网络,并借鉴了在图像识别中表现最好的网络配置,搭建了一个很深的全序列卷积神经网络,直接对语音的语谱图发起识别。
实验证明,DFCNN比当时在学术界和工业界最好的BLSTM的识别率提升了15%以上。
那么最后语音识别技术究竟走到了哪一步呢?听说已经超越了人,因为近些年总有媒体这么说,是也不是。
这些对语音识别成果的震撼报道似乎不太喜欢提及一个事实,训练和测试数据中的声音多是在理想环境下录制,比如在安静的办公室,甚至是专业的录音室。
但在被称为史上最难语音识别任务的CHIME6比赛中,数据集中的语音是充满环境噪音的。
这看起来就不像是现在的AI能搞定的问题。
科大讯飞采用了一种基于空间,说话人同步感知的迭代掩码估计算法,简单来说就是使用麦克风阵列,在复杂环境中综合考虑空间和说话人的信息,对声音做进一步的处理,最后把错误率从46.1%降低到了30.5%,在这项国际赛事上完成了三连冠。
对于语音人工智能的思考
不过领先归领先,30.5%的错误率却远远达不到好用的程度。所以我们到底该不该报以理解万岁的态度呢?可以但不完全的可以。
人们一般把人工智能的能力分为三个层次, 运算智能, 感知智能和认知智能。
运算智能人类已经一败涂地,而感知智能近些年已经开始追求,甚至超越了人类,比如特定场景下的图像识别和语音识别,机器越来越聪明。
然而对于认知智能,也就是像人一样,能够自主应对复杂多变的现实场景,我们到现在甚至没有找到正确的方向,这种尴尬是语音识别乃至整个人工智能领域,从感知智能进入到认知智能之前的常态。所以可以理解,但不完全可以理解的是,那些试图超越技术发展阶段的产品逻辑。
找对语音识别的应用场景往往很重要。
参考文献
评论区大神补充
最近开源了一个端到端框架,speechbrain。他们的目标是打造最牛批语音框架。我自己用过,还挺灵活,有兴趣的可以试试。
cnn的前身是tdnn,对于dnn hmm来说效果确实不错,单手源代码使用c++写的,网上有来源的pytorch版本。
流行的Transformer也可以用在语音识别里面,配合ctc解码,效果相当不错。不过google又搞出来了conformer,又进一步提高了正确率。
我写论文用的是Tedlium,就是ted演讲的内容。语音和文本都是现成的,后期校对一下就好。还有中文的aishell数据库是中文语音库,国内的一家公司特地值作然后开源出来的。更多开源的库,可以去看看openasr