本文旨在帮助大家理解语音是如何转换成文字的。希望通过本文的介绍,大家能够轻松理解这一过程。
首先,我们需要明白声音本质上是一种波。常见的音频格式如MP3和WMV都是经过压缩的格式,为了便于处理,通常需要将其转换为非压缩的纯波形文件,例如Windows PCM文件(即我们常说的WAV文件)。WAV文件中存储的除了文件头外,主要是声音波形的各个采样点。下面是一张波形示例图。
在进行语音识别之前,有时需要去除开头和结尾的静音部分,以减少对后续步骤的影响。这个静音切除的过程被称为VAD(Voice Activity Detection),需要用到一些信号处理技术。为了分析声音,需要将声音分割成一个个小片段,每个片段称为一帧。这种分帧操作通常不是简单的切割,而是通过移动窗函数来实现。帧与帧之间通常会有重叠,如下图所示:
图中,每帧的长度为25毫秒,相邻两帧之间有15毫秒的重叠。这意味着我们采用的是以25毫秒为帧长,10毫秒为帧移的方式进行分帧。这样处理后,声音就被分成了许多小段。
然而,波形在时域上的描述能力有限,因此需要对其进行变换。一种常见的变换方法是提取MFCC(Mel频率倒谱系数)特征。根据人耳的生理特性,每帧波形会被转换成一个多维向量,这个向量包含了该帧语音的内容信息。这个过程被称为声学特征提取。在实际应用中,声学特征不仅限于MFCC,但本文不详细讨论其他方法。
经过上述处理,声音被转换成一个12行(假设声学特征是12维)、N列的矩阵,称之为观察序列。N为总帧数。观察序列如下图所示,每帧都用一个12维的向量表示,颜色的深浅反映了向量值的大小。
接下来,我们要介绍如何将这个矩阵转换成文本。首先,需要解释两个重要概念: - 音素:单词的发音由音素组成。对于英语,一种常用的音素集是卡内基梅隆大学的39音素集。汉语则直接使用全部声母和韵母作为音素集。 - 状态:一个比音素更细致的语音单位,通常一个音素划分为3个状态。
语音识别的工作原理并不复杂,主要分为以下几个步骤:
具体来说,如下图所示:
图中,每个小竖条代表一帧,若干帧语音对应一个状态,每三个状态组合成一个音素,多个音素组合成一个单词。也就是说,只要确定了每帧语音对应的状态,语音识别的结果也就明确了。
那么,如何判断每帧语音对应哪个状态呢?一个直观的方法是找出每帧语音对应概率最大的状态。例如,如果某帧语音对应S3状态的概率最大,那么就将这帧语音归为S3状态。
这些概率从哪里获得呢?这就需要用到“声学模型”,它存储了大量的参数,通过这些参数可以计算出帧和状态之间的概率。获取这些参数的过程称为“训练”,需要大量语音数据支持,训练方法较为复杂,本文不详细讨论。
但是,这样做存在一个问题:每一帧都会得到一个状态编号,最终可能会得到一堆混乱的状态编号,相邻两帧的状态编号基本不同。假设语音有1000帧,每帧对应一个状态,每3个状态组合成一个音素,那么大约会组合成300个音素,但这段语音实际并没有这么多音素。因此,相邻帧的状态编号应该大部分相同才合理。
为了解决这个问题,通常会使用隐马尔可夫模型(HMM)。虽然HMM听起来很高深,但实际上用起来非常简单:
这样就能将结果限制在预先设定的网络中,避免了之前提到的问题。当然,这也带来了另一个局限性,即如果你设定的网络中只包含几个特定句子的状态路径,那么识别出的结果只能是这些句子之一。
如果想识别任意文本怎么办?那就需要构建一个足够大的状态网络,包含任意文本的路径。但网络越大,识别准确率越难以保证。因此,需要根据实际需求,合理选择网络大小和结构。
状态网络的构建是从单词级网络扩展到音素网络,再到状态网络。语音识别的过程就是在状态网络中搜索最佳路径,这条路径的概率最大,这被称为“解码”。路径搜索的算法是一种动态规划剪枝算法,称为Viterbi算法,用于寻找全局最优路径。
上述累积概率由三部分构成: 1. 观察概率:每帧与每个状态对应的概率; 2. 转移概率:每个状态转移到自身或下一个状态的概率; 3. 语言概率:根据语言统计规律得到的概率。
其中,前两种概率从声学模型中获取,最后一种概率从语言模型中获取。语言模型是通过大量文本训练出来的,可以帮助提升识别正确率。语言模型非常重要,如果不使用语言模型,当状态网络较大时,识别出的结果会非常混乱。
以上介绍了传统的基于HMM的语音识别方法。HMM的实际内涵远不止上述描述的“状态网络”那么简单。上述内容只是为了便于理解,不追求严格性。