来学校已经快一个月了,看语音识别依然有些吃力,HMM,GMM,DNN似懂非懂,也许多一些实践和时间,会慢慢好一些。最近终于对一个很小的知识点有一些理解,赶紧写下来,也算是一个月以来有了一些小小的成果。难免有错,热烈欢迎喷我,会及时改正!
---------------------------------------------------
语音识别的模型训练当中,损失函数是一个经常出现的概念,那么什么是损失函数,是用来干什么的呢?
理解一个东西,搞清楚脉络,对于理解是很有好处的,所以从头开始说。
语音识别的大致过程是这样的(并不是很准确,按照个人理解)。语音信号按照音素识别,因此先对信号分帧,同时加窗处理,然后进行频域转换,再提取语音信号的特征,最后将特征输入识别模型得出结果。
语音信号是一种短时平稳长时时变的信号,一般的认为语音信号在 20ms - 30ms 左右可以认为变化很小,这样切分出来的一小段语音,微观上变化很大,大概就可以标示一个音素,而宏观上几乎没有变化,这一过程就是分帧。我们平时录音时候看到最多的那种形式是语音信号的时域表现形式,语音识别的单位并不是一个单词,更多使用的是音素。我们可以按照这种类似于积分的思想来处理语音信号,音素在语音信号中是一段非常短的信号区域。当然分帧并不是简单的切分,为了保证信号平滑和方便处理,帧与帧之间会有重叠。同时还会对信号进行加窗处理。
时域信号的表现其实并不利于我们的处理并提取需要的信号特征,因此我们利用短时傅里叶变换,将时域信号抽取频率特征,转化成频域信号,这一个过程同时也是一个降维过程。至此,信号的特征提取变得比较容易。但是我们对语音信号的识别并不是直接识别语音信号,而是统一的提取信号里面的一部分特征,这样不仅降低维度便于处理,而且输入识别模型的数据是统一的,提取特征的方法一般是MFCC(梅尔倒谱系数),具体内容可以参见网络上大神帖子,讲的非常好,这里不深究,只需要知道这是一种提取语音信号特征的方法。至此语音信号由一串不规则的波形,变成了一个 M*N 的矩阵,表示提取了 M 种特征,语音信号被分成了 N 帧,每一帧作为矩阵的一列。
至此语音识别的准备工作就做好了大部分,下面就开始识别模型。模型暂时可以简单看作是一个函数,把上面的 M*N 矩阵输入到模型,经过模型的处理,就能输出结果。当然一般情况下,并不是我们认为的输入语音信号就直接得出文字,语音模型的输出一般会是一个概率,模型的输入假设有 M 个节点,输出有 K 个节点,每个输出节点代表一个音素,而节点输出的值是一个概率,当概率超过一定的阈值,就认为当前节点所代表的的音素被选中。
那么问题来了,模型是怎么来的?模型既然可以看做一个函数,那么函数里面的参数又是怎么来的?模型和模型参数,都是使用大量的训练数据训练得来的。
那么训练之前,模型的参数是怎么来的,他又是怎么通过训练,慢慢得到一个合适的参数,用于真正的语音识别呢?这里就用到的损失函数的概念。
语音识别的模型有很多,以前很多使用的隐马尔科夫模型(HMM),混合高斯模型(GMM),现在很火的深度神经网络(DNN),卷积神经网络(CNN)等。这些模型里面都有参数。其实一开始在训练模型之前,我们只是对参数进行很简单的随机初始化。作为训练数据,数据输入到模型,我们其实是预先知道应该输出什么结果的,而实际上对于一个参数是随机初始化的模型,输出结果总是不会完全正确的,那么实际数据结果和应该输出的结果之间的差距(或者说距离),就可以看做是一种度量,度量我们的初始化参数是不是合适,这种距离就可以用损失函数来表示。
所以总结一下,损失函数并不神秘。就像我们一开始学习方程一样,一开始我们并不知道方程到底是个什么东西,后来慢慢的知道方程并不神秘,原来方程就是一个等式,只不过这个等式里面有未知数。损失函数也是这样,它就是一种度量,用于表示当前参数下的模型与我们理想的模型到底有多大的差距,以便对模型参数进行合适的调整,下一次输入训练数据,还会有一个输出,这个输出与预计结果的差距仍然用损失函数度量,依据这一次 的损失函数,再一次调整参数大小。经过很多次循环,实际输出与预计结果的差距不断缩小,我们的模型也就越来越好,直至可以用于实际,用来识别测试数据。