算法基础(6)| 语音识别DTW算法小讲

时间:2022-07-22
本文章向大家介绍算法基础(6)| 语音识别DTW算法小讲,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1. 语音识别概况

时至今日,语音识别已经有了突破性进展。2017年8月20日,微软语音识别系统错误率由5.9%降低到5.1%,可达到专业速记员的水平;国内语音识别行业的佼佼者科大讯飞的语音听写准确率则达到了95%,表现强悍。国内诸如阿里、百度、腾讯等大公司,也纷纷发力语音识别,前景一片看好。

并且,语音识别系统也不只仅仅用于之前提到的手机交互、智能音箱命令,在玩具、家具家居、汽车、司法、医疗、教育、工业等诸多领域,语音识别系统将发挥不可忽视的作用。毕竟在当下人工智能刚刚起步的时代,在设备无法便捷的探知人类想法之前,语音交互都是最高效的人机交互方式。

现在庞大的语言数据库难以放置于移动端,这也是几乎所有手机语音助手使用时需要联网的原因。语音识别发展到现在也不是没有离线版,但我们不难发现,离线版的准确率是要远远低于在线版的。

另外,刚才我们提到不少语音厂商都宣称准确率达到90%以上,这可以说是十分了不起的,不夸张的说,这时候每提升1个百分比的准确率,都是质的飞跃。这不仅要相当完善的数据库,满足这样的准确率还得效率较高的识别提取算法和自学习系统。

但然这样的数据我们要以辨证的眼光来看,俗话说,一句话百样说,汉语言可谓博大精深;而且厂商给出的准确率数据的测试很难具备广泛性,所以有些用户在使用语音识别功能时发现它还很“弱智”,实属正常。

识别提取算法和自学习系统,在这里我们不妨简单了解一下它们的工作过程:首先语音识别系统对收集到的目标语音进行预处理,这个过程就已经十分复杂,包含语音信号采样、反混叠带通滤波、去除个体发音差异和设备、环境引起的噪声影响等等。然后,对处理的语音进行特征提取。

2. 语音识别基本原理

声音的本质是震动,它可以由波形表示,识别则需要对波进行分帧,多个帧构成一个状态,三个状态构成一个音素。英语常用音素集是卡内基梅隆大学的一套由39个音素构成的音素集,汉语一般直接用全部声母和韵母作为音素集,另外汉语识别还分有调和无调。之后通过音素系统合成单词或者汉字。

当然,之后的匹配和后期内容处理也需要相应算法来完成。自学习系统则更多的是针对数据库来说。将语音转换成文本的语音识别系统要有两个数据库,一是可与提取出的信息进行匹配的声学模型数据库,二是可与之匹配的文本语言数据库。这两个数据库需要提前对大量数据进行训练分析,也就是所说的自学习系统,从而提取出有用的数据模型构成数据库;

另外,在识别过程中,自学习系统会归纳用户的使用习惯和识别方式,然后将数据归纳到数据库,从而让识别系统对该用户来说更智能。

更进一步总结一下整个识别过程:

  • 对采集的目标语音进行处理,获取包含关键信息的语音部分
  • 提取关键信息
  • 识别最小单元字词,分析规定语法排列
  • 分析整句语义,将关键内容断句排列,调整文字构成
  • 根据整体信息修改出现轻微偏差的内容

3. DTW(动态时间弯折)算法

在语音识别中比较简单的是基于DTW算法。DTW(动态时间弯折)算法原理:基于动态规划(DP)的思想,解决发音长短不一的模板匹配问题。相比HMM模型算法,DTW算法的训练几乎不需要额外的计算。所以在孤立词语音识别中,DTW算法仍得到广泛的应用

在训练和识别阶段,首先采用端点检测算法确定语音的起点和终点。对于参考模板{R(1),R(2),…,R(m),…,R(M)},R(m)为第m帧的语音特征矢量。对于测试模板{T(1),T(2),…,T(n),…,T(N)},T(n)为测试模板的第n帧的语音特征矢量。参考模板与测试模板一般采用类型的特征矢量、相同的帧长、相同的窗函数和相同的帧移。

对于测试和参考模板T和R,它们之间的相似度之间的距离D[T,R],距离越小则相似度越高。在DTW算法中通常采用欧氏距离表示。对于N和M不相同的情况,需要考虑T(n)和R(m)对齐。一般采用动态规划(DP)的方法将实现T到R的映射。

将测试模板的各个帧号n=1~N在一个二维直角坐标系中的横轴上标出,参考模板的各帧号m=1~M在纵轴上标出,通过这些表示帧号的整数坐标画出一些纵横线即可形成一个网格,网格中的每一个交叉点(n,m)表示测试模式中某一帧与训练模式中某一帧的交汇点。DP算法可以归结为寻找一条通过此网格中若干格点的路径,路径通过的格点即为测试和参考模板中进行距离计算的帧号。

4. Matlab代码

function dist = dtw( t,r )
n=size(t,1);
m=size(r,1);
%%帧匹配距离距阵
d=zeros(n,m);

for i=1:n
    for j=1:m
        d(i,j)=sum((t(i,:)-r(j,:)).^2);
    end
end

%%累积距离矩阵
D=ones(n,m)*realmax;
D(1,1)=d(1,1);
%%动态规划
for i=2:n
    for j=1:m
        D1=D(i-1,j);
        if j>1
            D2=D(i-1,j-1);
        else
            D2=realmax;
        end
               if j>2
            D3=D(i-1,j-2);
        else
            D3=realmax;
        end
        D(i,j)=d(i,j)+min([D1,D2,D3]);
    end
end
dist=D(n,m);
end
测试程序:
disp('正在计算参考模板的参数...')
for i=1:10
    fname=sprintf('test1\�.wav',i-1);
    [x fs]=wavread(fname);
    [x1 x2]=vad(x,fs);
    m=mfcc(x);
    m=m(x1-2:x2-2,:);
    ref(i).mfcc=m;
end
disp('正在计算测试模板的参数...')
for i=1:10
    fname=sprintf('train1\�.wav',i-1);
    [x fs]=wavread(fname);
    [x1 x2]=vad(x,fs);
    m=mfcc(x);
    m=m(x1-2:x2-2,:);
    test(i).mfcc=m;
end
disp('正在进行模板匹配...')
dist=zeros(10,10);
for i=1:10
    for j=1:10
        dist(i,j)=dtw(test(i).mfcc,ref(j).mfcc);
    end
end

disp('正在计算匹配结果...')
for i=1:10
    [d,j]=min(dist(i,:));
    fprintf('测试模板%d的识别结果为:%dn',i,j);
end