2019-04-24 09:37:17 whale52hertz 阅读数 86
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5918 人正在学习 去看看 杨波

来源:ATYUN AI平台 

技术的进步推动了语音界面的发展,通过机器学习工具的普及,使得更多的互联网连接产品能够比以往任何时候都更能倾听和回应我们的声音。许多人将会体验到新的语音设备带来的便利。

语音识别取得了两个里程碑进展 Mozilla发布开源语音识别模型和语音数据集

Mozilla(缩写MF或MoFo)全称Mozilla基金会,是为支持和领导开源的Mozilla项目而设立的一个非营利组织。Mozilla对语音识别的潜力感到兴奋。他们相信这项技术能够并且将会带来一波创新产品和服务的浪潮,并且应该对所有人开放。

上个月29日,Mozilla的机器学习小组的语音识别工作取得了两个重要的里程碑进展。其中之一是Mozilla的开源语音识别模型首次发布,该模型的准确性接近人类在听同样的录音时的感知。其次,Mozilla还发布了世界上第二大公开的语音数据集,这是全球近2万名用户的贡献。

一个接近用户期望性能的开放源码的语音文本引擎
目前只有少数几家大公司的商业质量语音识别服务是可行的。这就减少了用户的选择,也减少了初创公司、研究人员甚至更大的公司的可用功能,这些公司想要为他们的产品和服务提供支持。

这就是为什么Mozilla将DeepSpeech作为一个开放源码项目。Mozilla和一群志同道合的开发人员、公司和研究人员组成的社区一起,应用了复杂的机器学习技术和各种各样的创新,在LibriSpeech的测试数据集上构建了一个语音到文本的引擎,出错率仅为6.5%。

在发布的第一个版本中,引擎包含了Python、NodeJS和一个命令行二进制代码的预构建包,开发者可以马上使用它来进行语音识别。

构建世界上最多样化的公开语音数据集,为训练语音技术最优化
如此少的服务在商业上可用的一个原因是缺乏数据。创业公司、研究人员或任何想要建立语音技术的人都需要高质量的、转录的语音数据来训练机器学习算法。现在,他们只能访问相当有限的数据集。

为了解决这一障碍,Mozilla在今年7月启动了Common Voice项目。目标是让人们可以很容易地把他们的声音捐赠给一个公开的数据库,这样就可以建立一个语音数据集,每个人都可以用它来训练新的语音应用程序。

语音识别取得了两个里程碑进展 Mozilla发布开源语音识别模型和语音数据集

到目前为止,Mozilla已经发布了第一批捐赠者的声音:近40万种录音,相当于500小时的演讲。任何人都可以下载这些数据。

Mozilla收到了来自全球范围内的2万多人提供的不同的声音。通常,现有的语音识别服务无法理解不同的口音,而且大多数情况,比起女性更善于理解男性的语音——这是语音识别服务接受训练的数据中存在的偏见结果。Mozilla希望说话者的数量和他们的不同的口音能够创造出一个全球性的代表数据集,从而带来更具包容性的技术。

为此,Mozilla开始使用英语,并且正在努力确保从2018年上半年开始,Common Voice项目能够支持多种语言的语音捐赠。最后,当经历了寻找可公开的语音数据集的挑战时,Mozilla还收集了所有其他我们所知道的大型语音收集的链接。

Mozilla认为,技术应该是开放的,所有人都可以访问,包括语音。Mozilla开发这种技术的方法是由设计开放的,他们非常欢迎更多的合作者和贡献者与之一起工作。

本文转自ATYUN人工智能媒体平台,原文链接:语音识别取得了两个里程碑进展 Mozilla发布开源语音识别模型和语音数据集

更多推荐

达观数据荣获上海市软件企业核心竞争力评价,推动上海软件行业发展

云从科技 | 从初创企业上位AI“国家队”,看看背后都干了些什么?!

智行者蜗小白“无人清扫车”南翠屏上岗(图)

裤子变裙子,GAN图像转换新进展

欢迎关注ATYUN官方公众号,商务合作及内容投稿请联系邮箱:bd@atyun.com
欢迎关注ATYUN官方公众号,商务合作及内容投稿请联系邮箱:bd@atyun.com

 

2018-10-17 17:28:52 SrdLaplace 阅读数 575
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5918 人正在学习 去看看 杨波

CTC是一种端到端的语音识别技术,他避免了需要字或者音素级别的标注,只需要句子级别的标注就可以进行训练,感觉非常巧妙,也很符合神经网络浪潮人们的习惯。特别是LSTM+CTC相较于之前的DNN+HMM,LSTM能够更好的捕捉输入中的重要的点(LSTM随着状态数目增加参数呈线性增加,而HMM会平方增加),CTC打破了隐马尔科夫的假设,把整个模型从静态分类变成了序列分类。

语音识别的评价指标

在语音识别中,在数据集SS上评价模型hh的好坏一般用标签错误率(Label Error Rate): LER(h,S)=1S(x,z)SED(h(x),z)zLER(h,S)=\frac{1}{|S|}\sum_{(x,z)\in S}\frac{ED(h(x),z)}{|z|}ED(p,q)ED(p,q)表示ppqq两个序列的编辑距离。

语音识别模型

在语音识别中,提取语音信号的MFCC特征xx,经过神经网络或者GMM处理后经过一个softmax层得到一个每个音素的后验概率yyyy的类别有L+1|L|+1种,LL是可能出现的字符,加1为建个符。定义BB为简单的压缩变换,把路径π\pi(路径就是一种音素出现的路线)中相邻相同的音素合并,空音素去掉,再特征xx下定序列ll出现的条件概率为:

p(lx)=π=B1(l)p(πx)p(l|x)=\sum_{\pi=\in B^{-1}(l)}p(\pi|x)

前向后向算法(Forward-Backward Algorithm)

定义符号lp:ql_{p:q}表示符号序列KaTeX parse error: Expected '}', got 'EOF' at end of input: …..l_{q-1},l_{q},容易得知,要想使得路径B(π)B(\pi')满足一定的llπ\pi路线上的状态跳转需要满组ll'的先后顺序,不同的符号之间可以插入blank。

定义前向变量α(t,u)\alpha(t,u)αt(t,u)=πNT,B(π1:t)=11:ut=1tyπtt\alpha_t(t,u)=\sum_{\pi\in N^T,B(\pi_{1:t})=1_{1:u}}\prod_{t'=1}^ty_{\pi_{t'}}^{t'}

α(t,s)\alpha(t,s)可以递推的用α(t1,s)α(t1,s1)\alpha(t-1,s),\alpha(t-1,s-1)计算。

为了方便起见,我们在ll相邻标签之间插入了空白(blank),在开始和末尾也加入了空白,这样我们用ll'表示这个新的标记,ll'的长度就为2l+12|l|+1。在计算ll'前缀的概率中,我们允许空白和非空白标签之间转移,那么我么有动态规划的初始条件:

α(1,1)=yb1\alpha(1,1)=y_b^1

α(1,2)=yl11\alpha(1,2)=y_{l_1}^1

α(1,u)=0,u>2\alpha(1,u)=0,u>2

α(t,0)=0\alpha(t,0)=0

α(t,u)=0,u<U2(Tt)1\alpha(t,u)=0,u<U'-2(T-t)-1

UU'表示序列2l1:u+12|l_{1:u}|+1

递归算式:

α(t,u)=yluti=f(u)uα(t1,i)\alpha(t,u)=y_{l'_u}^t\sum_{i=f(u)}^u\alpha(t-1,i)

f(u)={u1if lu=blank or lu2=luu2otherwisef(u)=\{\begin{array}{} u-1 & if~l'_u=blank~or~l'_{u-2}=l'_u\\u-2 & otherwise \end{array}

简单地说就是现在如果状态是blank,那么上一个状态有可能是blank或者是上一个字符,如果现在的状态是字符,那他上一个状态可能是相同的字符,可能是blank,也可能是上一个非blank字符,但如果现在的字符与上一个非空字符相同,那意味着现在的状态不能直接从上一个非空字符跳过来,必须隔一个blank,所以只能从blank和相同的字符跳过来。

相似的定义后向变量β(t,u)\beta(t,u)αt(t,s)=πNT,B(πt:T)=1u:Ut=t+1Tyπtt\alpha_t(t,s)=\sum_{\pi\in N^T,B(\pi_{t:T})=1_{u:U}}\prod_{t'=t+1}^{T}y_{\pi_{t'}}^{t'}

依然用动态规划来求解,动态规划的初始条件:

β(T,U)=1\beta(T,U')=1

β(T,U1)=1\beta(T,U'-1)=1

β(T,u)=0,u<U1\beta(T,u)=0,u<U'-1

β(t,u)=0,u>2t\beta(t, u)=0,u>2t

递归算式:

β(t,u)=i=ug(u)β(t+1,i)yltut+1\beta(t,u)=\sum_{i=u}^{g(u)}\beta(t+1,i)y^{t'+1}_{l^u_t}

g(u)={u+1if lu=blank or lu+2=luu+2otherwiseg(u)=\{\begin{array}{} u+1 & if~l'_u=blank~or~l'_{u+2}=l'_u\\u+2 & otherwise \end{array}

在实际中,上述递归很快就会导致计算机出现下溢。避免下溢的一种好方法是先取对数,在计算结束时仅取幂以找到真实概率。在这种情况下,一个有用的等式是

ln(a+b)=ln a+ln(1+eln bln a)ln(a+b)=ln~a+ln(1+e^{ln~b-ln~a})

这样就允许前向和后向变量相加,同时保留取对数。但是这种方法的稳定性较差,并且对于很长的序列可能会失效。

Loss Function

the CTC loss函数L(S)L(S)被定义为训练集SS种正确标签的negative log probability:

L(S)=ln(x,z)S=(x,z)Sln p(zx)L(S)=-ln\prod_{(x,z)\in S}=-\sum_{(x,z)\in S}ln~p(z|x)

这个损失函数是可微的,方便加入到神经网络中进行反向传播。我们定义example loss为

L(x,z)=ln p(zx)L(x,z)=-ln~p(z|x)

那么:

L(S)=(x,z)SL(x,z)L(S)=\sum_{(x,z)\in S}L(x,z)

L(S)w=(x,z)SL(x,z)w\frac{\partial L(S)}{\partial w}=\sum_{(x,z)\in S}\frac{\partial L(x,z)}{\partial w}

上一小节中,我们得到了前向后向变量,我们令l=zl=z,易知:

α(t,u)β(t,u)=πt=zu,B(π)=zt=1Tyπtt=πt=zu,B(π)=zp(πx)\alpha(t,u)\beta(t,u)=\sum_{\pi_t=z_u,B(\pi)=z}\prod_{t=1}^Ty_{\pi_t}^t=\sum_{\pi_t=z_u,B(\pi)=z}p(\pi|x)

那么对于任意时刻t[1,T]t\in [1,T],我们有

p(zx)=u=1zα(t,u)β(t,u)p(z|x)=\sum_{u=1}^{|z'|}\alpha(t,u)\beta(t,u)

也就是说

L(x,z)=ln u=1zα(t,u)β(t,u)L(x,z)=-ln~\sum_{u=1}^{|z'|}\alpha(t,u)\beta(t,u)

Loss Gradient

从前面的推导可得:

L(x,z)ykt=ln p(zx)ykt=1p(zx)p(zx)ykt\frac{\partial L(x,z)}{\partial y_k^t}=-\frac{\partial ln~p(z|x)}{\partial y_k^t}=-\frac{1}{p(z|x)}\frac{\partial p(z|x)}{\partial y_k^t}

因为网络输出不会相互影响,求解p(zx)ykt\frac{\partial p(z|x)}{\partial y_k^t}我们只需要考虑那些在时间tt经过标签kk的路径。因为kk有可能没有出现在zz中,对于这些kk,我们令p(zx)ykt=0\frac{\partial p(z|x)}{\partial y_k^t}=0。对于kk也可能多次出现在zz中,我们定义B(z,k)=uzu=kB(z,k)={u|z'_u=k},易得:

p(zx)ykt=1yktuB(z,k)α(t,u)β(t,u)\frac{\partial p(z|x)}{\partial y_k^t}=\frac{1}{y_k^t}\sum_{u\in B(z,k)}\alpha(t,u)\beta(t,u)

那么:

L(x,z)ykt=1p(zx)yktuB(z,k)α(t,u)β(t,u)\frac{\partial L(x,z)}{\partial y_k^t}=-\frac{1}{p(z|x)\cdot y_k^t}\sum_{u\in B(z,k)}\alpha(t,u)\beta(t,u)

那么对于softmax之前模型的输出akta_k^t的反向传播梯度为:

L(x,z)akt=kL(x,z)yktyktakt\frac{\partial L(x,z)}{\partial a_k^t}=-\sum_{k'}\frac{\partial L(x,z)}{\partial y_{k'}^t}\frac{\partial y_{k'}^t}{\partial a_k^t}

我们知道:

ykt=eaktkeakty_k^t=\frac{e^{a_k^t}}{\sum_{k'}e^{a_{k'}^t}}

yktakt=yktδkkyktykt\frac{\partial y_{k'}^t}{\partial a_k^t}=y_{k'}^t\delta_{kk'}-y_{k'}^ty_{k}^t

综上可得:

L(x,z)akt=ykt1p(zx)uB(z,k)α(t,u)β(t,u)\frac{\partial L(x,z)}{\partial a_k^t}=y_k^t-\frac{1}{p(z|x)}\sum_{u\in B(z,k)}\alpha(t,u)\beta(t,u)

可以理解为现在的输出ykty_k^t与根据前向后向概率求出的现在应该出现的概率之差。

实验中我们可以得知输出总是spike的形式出现,大部分被blank间隔。

decoder

分类器的输出应该是在给定输入序列下的最可能的标记输出

h(x)=argmaxlp(lx)h(x)=argmax_{l}p(l|x)

这是一个NP问题,下面是两个近似的算法,在实践中给出了良好的结果。

最佳路径解码(best path decoding)

基于的假设是最可能的路径会对应最可能表标签

h(x)=B(π),s.t.,π=argmaxπp(πx)h(x)=B(\pi^*),s.t.,\pi^*=argmax_{\pi}p(\pi|x)

最佳路径解码非常容易计算(计算方法如下图),但是它不能保证找到最有可能的ll(因为不同的π\pi有可能对应相同的ll,加起来可能与最佳路径结果不同)。

前缀查找解码(prefix search decoding)

通过修改前向后向算法(forward-backward algorithm),我们可以高效的计算出标记前缀的后继拓展的概率。前缀查找解码(prefix search decoding)是一种剪枝的算法,剪枝主要在两个方面,一是同路径不重复计算,二是不可能状态不再搜索。算法流程如下:

翻译一下:
ll^*表示当前找到最好的的序列,pp^*表示以pp^*为开头的序列可能性最高,当pp^*为开头的序列可能性小于表示当前找到最好的的序列ll^*出现的可能性时停止循环,认为ll^*就是最有可能的序列。循环过程中,对于最有可能的前缀尝试后面加入每一个可能的字符,然后计算加入这个字符之后新的字符串出现的概率和以新的字符串为前缀的概率,当新的字符串出现的概率大于ll^*时更新ll^*,把以新的字符串为前缀的概率大于ll^*出现的概率的前缀加入带备选集合,循如果发现剩下字符搭配pp^*做前缀的概率之和小于ll^*出现的概率,停止循环,节约计算。循环完毕后把旧的pp^*从备选集合中剔除,再把集合中概率最大的前缀作为pp^*
γ(pn,t)\gamma(p_n,t)表示序列pptt个输出非blank,γ(pb,t)\gamma(p_b,t)表示序列pptt个输出为blank。

实验结果

tensorflow中的CTC

tf.nn.ctc_loss(labels, inputs, sequence_length)

labels: 标签,一个稀疏矩阵
inputs:模型输出的logits

decoded, _ = tf.nn.ctc_beam_search_decoder(logits, sequence_len, merge_repeated=False)
decoded, _ = tf.nn.ctc_greedy_decoder(logit, sequence_len, merge_repeated=False)

logits:模型输出的logits
sequence_len:实际的长度(tensorflow静态图模型,告诉他实际的音频长度多长)
merge_repeated:把连续输出相同的合并,不同于ctc_merge_repeated,ctc_merge_repeated是把中间没有blank的合并。

音识别模型小型综述

上古时期的方法:元音部分频率共振峰匹配来识别(1952年贝尔实验室的Davis等人发明的特定说话人孤立数字识别系统)

深度神经网络之前的方法:mfcc/plp/fbank->GMM+HMM->DTW(dynamic time warping)

深度学习下的方法(参考了百度语音识别技术负责人的文章):

  • 2011-2012年:发现把GMM换成DNN有30%的提升
  • 2013年:发现调整激活函数Maxout对数据量较少的情况有所改善,对大数据量不一定有显著帮助
  • 2013-2014年:浅层DNN升级为浅层CNN
  • 2014年:开始尝试开始做RNN,尤其是LSTM
  • 2014年底2015年初:Hinton 的博士后 Alex Graves,把以前做手写体识别的LSTM 加 CTC 的系统应用在了语音识别领域,在 TIMIT 上做了结果,紧接着谷歌认为这个很有前途,就开始把这些技术推广在大数据上面。
  • 2015年:研究者发现 CNN 在时间上做卷积和 LSTM 有很多相似之处但各有特点。LSTM 更擅长做整个时间域的信息整合,因为 CNN 有很强的平移的不变性,那么鲁棒性更强
  • 2016年:Deep CNN,WaveNet 等深层 CNN

工程上的一般方法是先用模型 first-pass decoding,再用语言模型 second-pass rescoring 来提高准确率。

实现的乞丐版语音识别模型

dataset: VCTK[https://datashare.is.ed.ac.uk/download/DS_10283_2651.zip]
model: 三层lstm模型
loss function: ctc loss
feature: 13阶mfcc系数+2阶动态因子(39)

git: https://github.com/RDShi/Speech2Text

速度很慢,希望有缘人指点提升数度的方法

参考文献

Graves A, Fernandez S, Gomez F, et al. Connectionist temporal classification: labelling unsegmented sequence data with recurrent neural networks[C] Proceedings of the 23rd international conference on Machine learning. ACM, 2006: 369-376.

2018-11-06 11:53:57 valada 阅读数 2320
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5918 人正在学习 去看看 杨波

阿里巴巴 2018 年开源的语音识别模型 DFSMN,将全球语音识别准确率纪录提高至 96.04%。DFSMN 模型,是阿里巴巴的高效工业级实现,相对于传统的 LSTM、BLSTM 等声学模型,该模型具备训练速度更快、识别更高效、识别准确率更高和模型大小压缩等效果。

本场 Chat 的主要内容包括:

  1. 语音识别流程简介;
  2. Kaldi 的部署使用;
  3. 如何训练基于中文的 DFSMN 声学模型;
  4. 语音特征提取 MFCC 算法源码解读;
  5. 语音识别工具对比。

阅读全文: http://gitbook.cn/gitchat/activity/5bcc8f9b0920511ab0ff412b

您还可以下载 CSDN 旗下精品原创内容社区 GitChat App ,阅读更多 GitChat 专享技术内容哦。

FtooAtPSkEJwnW-9xkCLqSTRpBKX

2019-04-07 15:37:37 asrgreek 阅读数 22448
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5918 人正在学习 去看看 杨波

虽然现在端到端语音识别模型可以直接对后验概率建模,可以不需要HMM结构了。但实际上目前很多state-of-the-art模型还是以HMM结构为主,比如chain model。而且掌握HMM-GMM结构,对于深入理解语音识别过程是由有一定好处的。

但对于外行或者刚接触语音识别的人来说,要弄懂HMM-GMM结构还是要花不少时间的,特别是被一大推公式整懵了。语音识别任务有些特殊,比如语音识别中,标注只是针对整段音频的,而不是针对每一帧;语音识别是针对每个音素都建立一个HMM模型,而不是所有音素用一个HMM模型描述。

当时为了弄懂HMM-GMM,看了不少资料,但感觉都不适合很初级的学习者。于是就萌生了写一个通俗易懂版的HMM-GMM教程,从一个音频实例说起,给大家一个感性的认识,也着重讲下作为初学者可能会感同身受的问题,不涉及到具体公式。公式的推断会给出参考资料,后续大家在研究,相信有了感性的认识之后,对这些公式的理解就不成问题了。

我们从下面这段音频说起。

在这里插入图片描述
我们把上面2秒的音频分帧,以帧长100ms,帧移100ms为例进行切分,这样上面的音频就被我们分成20帧。(ps:这里主要是为了方便说明,正常情况下帧长是25ms,帧移是10ms)

一、得到这段音频的标注

这里的标注可以是两种:
1、音素级别的标注。这是训练HMM-GMM模型所需要的标注,也就是说可以直接拿来训练的数据。
2、字节别的标注。实际上我们更多时候拿到是的字级别的标注,因为音素级别的标注工作量很大。但我们可以通过发音词典,将字级别的标注转换成音素级别的标注。这种转换没办法消除多音字的影响,但实际上不会对结果产生太大影响(这一部分可以参考kaldi的compile-train-graphs过程:http://kaldi-asr.org/doc/graph_recipe_train.html)

假设上面这段音频的标注是”你好“,那么对应的发音就是”n i2 h ao3“这四个声韵母。这里为了方便说明,我们就是用声韵母作为建模单元(ps:实际应用中是使用音素作为建模单元)。

二、对”n“、”i2“、”h“、”ao3“这4个声韵母分别使用HMM-GMM建模,使用3状态建模,如下图

在这里插入图片描述
为了方面说明,我们给每个状态加了编号。从上图我们可以看到,对于HMM的发射概率,我们是使用高斯分布函数建模的。为了方便说明,这里我们使用单高斯分布函数(虽然上图写的是GMM)
理解自环很重要,比如④这个状态,因为有了自环,它可以出现多次,因此我们可以对任意长的音频建模,这也是连续语音识别的基础。

三、对”n“、”i2“、”h“、”ao3“对应的HMM-GMM模型进行训练,得到模型参数

这一步属于HMM三个问题中的学习问题,需要用到EM算法。在开始训练之前,我们需要明确每个HMM模型的参数、模型的输入和模型的输出。

  • HMM-GMM模型的参数

    1、转移概率
    2、发射概率:因为我们使用GMM对发射概率建模,所以实际参数就是高斯分布中的均值和方差(这也是初学者容易迷糊的一个地方)。
    总结:模型参数就是转移概率、高斯分布的均值、方差

  • 模型的输入

    输入:每帧信号的MFCC特征(也可以是fbank,plp等)。具体应用中,我们通常取39维的MFCC特征。这里为了方便说明,我们取2维的MFCC特征,也就是说输入的特征空间分布是这样的:
    在这里插入图片描述

    上图中,每个黑点对应某一帧信号的MFCC特征。我们需要使用这些特征值来更新GMM的参数,具体怎么更新后续会讲。

  • 模型的输出

    输出:每一帧属于"n"、“i2”、“h”、"ao3"中的某一个状态(3状态)的概率。

同时,需要额外说明的是:虽然我们有了每段音频对应的标注,但实际上HMM-GMM模型的学习过程并不是”有监督的“。因为监督学习任务应该是:“对于每一个输入,都有对应的label”。而语音识别的任务比”传统的监督学习“复杂一点。因为我们拿到的标注是音素级别的。比如上面那段音频,它只告诉我们对应的标注是"n"、“i2”、“h”、“ao3”,并没有告诉我们每一帧(即每一个输入)对应的label是啥?那么应该怎么训练呢,相信是很多初学者的困惑。

对于这种无监督的任务,我们EM算法来进行训练(更专业的术语叫嵌入式训练,embedding training。也就是说把“n”、“i2”、“h”、“ao3”对应的HMM模型嵌入到整段音频中进去训练,因为我们不知道音频的哪一段是对应“n”、“i2”、“h”、“ao3”。嵌入式训练本质还是EM算法的思想):

  • step1:初始化对齐。以上面的20秒音频为例,因为我们不知道每一帧对应哪个声韵母的某个状态,所以就均分。也就是说1-5帧对应"n",6-10帧对应"i2",11-15帧对应"h",16-20帧对应"ao3"。同时"n"又有三个状态,那么就把1-2帧分给状态①,3-4帧分给状态②,第5帧分给状态③。“i2”、“h”、"ao3"亦如此。这里每个状态只是用单高斯描述,如果是混合高斯,还需要进一步用k-means算法来对每个高斯分量初始化。
    初始化完成后,该段音频对应的HMM模型如下:
    在这里插入图片描述

  • step2:更新模型参数。
    1、转移概率:通过上图,我们可以得到①->①的转移次数,①->②的转移次数等等。然后除以总的转移次数,就可以得到每种转移的概率,这是一个统计的过程,无他。
    2、发射概率:即均值和方差。以状态①的均值和方差为例,由上图我们可以知道第1帧和第2帧对应状态①。假设第1帧的MFCC特征是(4,3),第2帧的MFCC特征的MFCC特征是(4,7)。那么状态①的均值就是(4,5),方差是(0,8)

  • step3:重新对齐。根据step2得到的参数,重新对音频进行状态级别的对齐。这一步区别于step1的初始化,step1的初始化我们是采用粗暴的均匀对齐,而这一步的对齐是根据step2的参数进行对齐的。这里的对齐方法有两种:a、硬对齐:采用维特比算法;b、软对齐:采用前后向算法。
    经过重新对齐后,可能变成这样(第2帧已经不对应状态①了):
    在这里插入图片描述

  • step4:重复step2和step3多次,直到收敛。

这一个过程就是EM算法。step1和step3对应E步,step2对应M步。

这一过程涉及到的公式可以参考爱丁堡的语音识别课件http://59.80.44.98/www.inf.ed.ac.uk/teaching/courses/asr/2018-19/asr03-hmmgmm-handout.pdf

到这里,我们就从宏观层面把语音识别的HMM-GMM建模过程讲完了。为了方便讲解,我们这里是用单音素为例。实际应用中,通常使用三音素,但过程几乎是一样的,只是三音素多了一步决策树聚类,具体可以参考我之前的博文:kaldi中基于决策树的状态绑定

欢迎转载,转载请注明出处,谢谢!

2018-11-06 05:22:38 kahncc 阅读数 182
  • C++语音识别开篇

    本篇mark老师将教大家使用第三方库的调用来简单的实现语音识别。随着机器学习和人工智能的热闹,国内语音行业也可谓是百花齐放。 语音识别一个伟大的时代已在我们身边悄悄走来。

    5918 人正在学习 去看看 杨波

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

本文简明讲述GMM-HMM在语音识别上的原理,建模和测试过程。这篇blog只回答三个问题:

1. 什么是Hidden Markov Model

 HMM要解决的三个问题:

 1) Likelihood

 2) Decoding

 3) Training

2. GMM是神马?怎样用GMM求某一音素(phoneme)的概率?

 

3. GMM+HMM大法解决语音识别

 3.1 识别

 3.2 训练

  3.2.1 Training the params of GMM

  3.2.2 Training the params of HMM



首先声明我是做视觉的不是做语音的,迫于**需要24小时速成语音。上网查GMM-HMM资料中文几乎为零,英文也大多是paper。苦苦追寻终于貌似搞懂了GMM-HMM,感谢语音组老夏(http://weibo.com/ibillxia)提供资料给予指导。本文结合最简明的概括还有自己一些理解应运而生,如有错误望批评指正。


====================================================================



1. 什么是Hidden Markov Model


ANS:一个有隐节点(unobservable)和可见节点(visible)的马尔科夫过程(见详解)。

隐节点表示状态,可见节点表示我们听到的语音或者看到的时序信号。

最开始时,我们指定这个HMM的结构,训练HMM模型时:给定n个时序信号y1...yT(训练样本), 用MLE(typically implemented in EM) 估计参数:

1. N个状态的初始概率

2. 状态转移概率a

3. 输出概率b

--------------

  • 在语音处理中,一个word由若干phoneme(音素)组成;
  • 每个HMM对应于一个word或者音素(phoneme)
  • 一个word表示成若干states,每个state表示为一个音素


用HMM需要解决3个问题:

1). Likelihood: 一个HMM生成一串observation序列x的概率< the Forward algorithm>

其中,αt(sj)表示HMM在时刻t处于状态j,且observation = {x1,...,xt}的概率

aij是状态i到状态j的转移概率,

bj(xt)表示在状态j的时候生成xt的概率,







2). Decoding: 给定一串observation序列x,找出最可能从属的HMM状态序列< the Viterbi algorithm>

在实际计算中会做剪枝,不是计算每个可能state序列的probability,而是用Viterbi approximation:

从时刻1:t,只记录转移概率最大的state和概率。

记Vt(si)为从时刻t-1的所有状态转移到时刻t时状态为j的最大概率

为:从时刻t-1的哪个状态转移到时刻t时状态为j的概率最大;

进行Viterbi approximation过程如下:


然后根据记录的最可能转移状态序列进行回溯:





3). Training: 给定一个observation序列x,训练出HMM参数λ = {aij, bij}  the EM (Forward-Backward) algorithm

这部分我们放到“3. GMM+HMM大法解决语音识别”中和GMM的training一起讲







---------------------------------------------------------------------


2. GMM是神马?怎样用GMM求某一音素(phoneme)的概率?

2.1 简单理解混合高斯模型就是几个高斯的叠加。。。e.g. k=3



fig2. GMM illustration and the probability of x



2.2 GMM for state sequence 

每个state有一个GMM,包含k个高斯模型参数。如”hi“(k=3):

PS:sil表示silence(静音)

fig3. use GMM to estimate the probability of a state sequence given observation {o1, o2, o3}


其中,每个GMM有一些参数,就是我们要train的输出概率参数


fig4. parameters of a GMM

怎么求呢?和KMeans类似,如果已知每个点x^n属于某每类 j 的概率p(j|x^n),则可以估计其参数:

 , 其中 


只要已知了这些参数,我们就可以在predict(识别)时在给定input sequence的情况下,计算出一串状态转移的概率。如上图要计算的state sequence 1->2->2概率:


fig5. probability of S1->S2->S3 given o1->o2->o3








---------------------------------------------------------------------

3. GMM+HMM大法解决语音识别

<!--识别-->

我们获得observation是语音waveform, 以下是一个词识别全过程:

1). 将waveform切成等长frames,对每个frame提取特征(e.g. MFCC), 

2).对每个frame的特征跑GMM,得到每个frame(o_i)属于每个状态的概率b_state(o_i)



fig6. complete process from speech frames to a state sequence


3). 根据每个单词的HMM状态转移概率a计算每个状态sequence生成该frame的概率; 哪个词的HMM 序列跑出来概率最大,就判断这段语音属于该词


宏观图:


fig7. Speech recognition, a big framework

(from Encyclopedia of Information Systems, 2002)




<!--训练-->

好了,上面说了怎么做识别。那么我们怎样训练这个模型以得到每个GMM的参数和HMM的转移概率什么的呢?




①Training the params of GMM

GMM参数:高斯分布参数:

从上面fig4下面的公式我们已经可以看出来想求参数必须要知道P(j|x),即,x属于第j个高斯的概率。怎么求捏?


fig8. bayesian formula of P( j | x )

根据上图 P(j | x), 我们需要求P(x|j)和P(j)去估计P(j|x). 

这里由于P(x|j)和P(j)都不知道,需要用EM算法迭代估计以最大化P(x) = P(x1)*p(x2)*...*P(xn):

A. 初始化(可以用kmeans)得到P(j)

B. 迭代

    E(estimate)-step: 根据当前参数 (means, variances, mixing parameters)估计P(j|x)

    M(maximization)-step: 根据当前P(j|x) 计算GMM参数(根据fig4 下面的公式:)

 , 其中 





②Training the params of HMM

前面已经有了GMM的training过程。在这一步,我们的目标是:从observation序列中估计HMM参数λ;

假设状态->observation服从单核高斯概率分布:,则λ由两部分组成:




HMM训练过程:迭代

    E(estimate)-step: 给定observation序列,估计时刻t处于状态sj的概率 

    M(maximization)-step: 根据重新估计HMM参数aij. 

其中,


E-step: 给定observation序列,估计时刻t处于状态sj的概率 

为了估计, 定义: t时刻处于状态sj的话,t时刻未来observation的概率。即

这个可以递归计算:β_t(si)=从状态 si 转移到其他状态 sj 的概率aij * 状态 i 下观测到x_{t+1}的概率bi(x_{t+1}) * t时刻处于状态sj的话{t+1}后observation概率β_{t+1}(sj)

即:


定义刚才的为state occupation probability,表示给定observation序列,时刻t处于状态sj的概率P(S(t)=sj | X,λ) 。根据贝叶斯公式p(A|B,C) = P(A,B|C)/P(B|C),有:



由于分子p(A,B|C)为


其中,αt(sj)表示HMM在时刻t处于状态j,且observation = {x1,...,xt}的概率

: t时刻处于状态sj的话,t时刻未来observation的概率;

finally, 带入的定义式有:


好,终于搞定!对应上面的E-step目标,只要给定了observation和当前HMM参数 λ,我们就可以估计了对吧 (*^__^*) 






M-step:根据重新估计HMM参数λ:

对于λ中高斯参数部分,和GMM的M-step是一样一样的(只不过这里写成向量形式):


对于λ中的状态转移概率aij, 定义C(Si->Sj)为从状态Si转到Sj的次数,有


实际计算时,定义每一时刻的转移概率为时刻t从si->sj的概率:


那么就有:


把HMM的EM迭代过程和要求的参数写专业点,就是这样的:


PS:这个训练HMM的算法叫 Forward-Backward algorithm。





一个很好的reference:点击打开链接





欢迎参与讨论并关注本博客和微博Rachel____Zhang, 后续内容继续更新哦~






           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

语音识别初探

阅读数 3373

Sphinx语音识别

阅读数 1238

没有更多推荐了,返回首页