【语音识别】基于矢量量化(VQ)说话人识别matlab源码
2021/4/17 20:25:39
本文主要是介绍【语音识别】基于矢量量化(VQ)说话人识别matlab源码,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一、简介
矢量量化方法,即vector quantization,其具体定义为:将一个向量空间中的点用其中的一个有限子集来进行编码的过程。在矢量量化编码中,关键是码本的建立和码字搜索算法。比如常见的聚类算法,就是一种矢量量化方法。而在ANN近似最近邻搜索中,向量量化方法又以乘积量化(PQ, Product Quantization)最为典型。在之前的博文基于内容的图像检索技术的最后,对PQ乘积量化的方法做过简单的概要。在这一小节里,小白菜结合自己阅读的论文和代码对PQ乘积量化、倒排乘积量化(IVFPQ)做一种更加直观的解释。
1 PQ乘积量化
PQ乘积量化的核心思想还是聚类,或者说具体应用到ANN近似最近邻搜索上,K-Means是PQ乘积量化子空间数目为1的特例。PQ乘积量化生成码本和量化的过程可以用如下图示来说明:
在训练阶段,针对N个训练样本,假设样本维度为128维,我们将其切分为4个子空间,则每一个子空间的维度为32维,然后我们在每一个子空间中,对子向量采用K-Means对其进行聚类(图中示意聚成256类),这样每一个子空间都能得到一个码本。这样训练样本的每个子段,都可以用子空间的聚类中心来近似,对应的编码即为类中心的ID。如图所示,通过这样一种编码方式,训练样本仅使用的很短的一个编码得以表示,从而达到量化的目的。对于待编码的样本,将它进行相同的切分,然后在各个子空间里逐一找到距离它们最近的类中心,然后用类中心的id来表示它们,即完成了待编码样本的编码。
正如前面所说的,在矢量量化编码中,关键是码本的建立和码字的搜索算法,在上面,我们得到了建立的码本以及量化编码的方式。剩下的重点就是查询样本与dataset中的样本距离如何计算的问题了。
在查询阶段,PQ同样在计算查询样本与dataset中各个样本的距离,只不过这种距离的计算转化为间接近似的方法而获得。PQ乘积量化方法在计算距离的时候,有两种距离计算方式,一种是对称距离,另外一种是非对称距离。非对称距离的损失小(也就是更接近真实距离),实际中也经常采用这种距离计算方式。下面过程示意的是查询样本来到时,以非对称距离的方式(红框标识出来的部分)计算到dataset样本间的计算示意:
具体地,查询向量来到时,按训练样本生成码本的过程,将其同样分成相同的子段,然后在每个子空间中,计算子段到该子空间中所有聚类中心得距离,如图中所示,可以得到4*256个距离,这里为便于后面的理解说明,小白菜就把这些算好的距离称作距离池。在计算库中某个样本到查询向量的距离时,比如编码为(124, 56, 132, 222)这个样本到查询向量的距离时,我们分别到距离池中取各个子段对应的距离即可,比如编码为124这个子段,在第1个算出的256个距离里面把编号为124的那个距离取出来就可,所有子段对应的距离取出来后,将这些子段的距离求和相加,即得到该样本到查询样本间的非对称距离。所有距离算好后,排序后即得到我们最终想要的结果。
从上面这个过程可以很清楚地看出PQ乘积量化能够加速索引的原理:即将全样本的距离计算,转化为到子空间类中心的距离计算。比如上面所举的例子,原本brute-force search的方式计算距离的次数随样本数目N成线性增长,但是经过PQ编码后,对于耗时的距离计算,只要计算4*256次,几乎可以忽略此时间的消耗。另外,从上图也可以看出,对特征进行编码后,可以用一个相对比较短的编码来表示样本,自然对于内存的消耗要大大小于brute-force search的方式。
在某些特殊的场合,我们总是希望获得精确的距离,而不是近似的距离,并且我们总是喜欢获取向量间的余弦相似度(余弦相似度距离范围在[-1,1]之间,便于设置固定的阈值),针对这种场景,可以针对PQ乘积量化得到的前top@K做一个brute-force search的排序。
2 倒排乘积量化
倒排PQ乘积量化(IVFPQ)是PQ乘积量化的更进一步加速版。其加速的本质逃不开小白菜在最前面强调的是加速原理:brute-force搜索的方式是在全空间进行搜索,为了加快查找的速度,几乎所有的ANN方法都是通过对全空间分割,将其分割成很多小的子空间,在搜索的时候,通过某种方式,快速锁定在某一(几)子空间,然后在该(几个)子空间里做遍历。在上一小节可以看出,PQ乘积量化计算距离的时候,距离虽然已经预先算好了,但是对于每个样本到查询样本的距离,还是得老老实实挨个去求和相加计算距离。但是,实际上我们感兴趣的是那些跟查询样本相近的样本(小白菜称这样的区域为感兴趣区域),也就是说老老实实挨个相加其实做了很多的无用功,如果能够通过某种手段快速将全局遍历锁定为感兴趣区域,则可以舍去不必要的全局计算以及排序。倒排PQ乘积量化的”倒排“,正是这样一种思想的体现,在具体实施手段上,采用的是通过聚类的方式实现感兴趣区域的快速定位,在倒排PQ乘积量化中,聚类可以说应用得淋漓尽致。
倒排PQ乘积量化整个过程如下图所示:
在PQ乘积量化之前,增加了一个粗量化过程。具体地,先对N个训练样本采用K-Means进行聚类,这里聚类的数目一般设置得不应过大,一般设置为1024差不多,这种可以以比较快的速度完成聚类过程。得到了聚类中心后,针对每一个样本x_i,找到其距离最近的类中心c_i后,两者相减得到样本x_i的残差向量(x_i-c_i),后面剩下的过程,就是针对(x_i-c_i)的PQ乘积量化过程,此过程不再赘述。
在查询的时候,通过相同的粗量化,可以快速定位到查询向量属于哪个c_i(即在哪一个感兴趣区域),然后在该感兴趣区域按上面所述的PQ乘积量化距离计算方式计算距离。
二、源代码
function mfc=my_mfcc(x,fs) %MY_MFCC:获取Speaker recognition的参数 %x:输入语音信号 fs:采样率 %mfc:十二个mfcc系数和一个能量 以及一阶和二阶差分 共36个参数 每一行为一帧数据 %clc,clear %[x,fs]=audioread('wo6.wav'); N=256;p=24; bank=mel_banks(p,N,fs,0,fs/2); % 归一化mel滤波器组系数 bank=full(bank); bank=bank/max(bank(:)); % 归一化倒谱提升窗口 w = 1 + 6 * sin(pi * [1:12] ./ 12); w = w/max(w); % 预加重滤波器 x=double(x); x=filter([1 -0.9375],1,x); % 语音信号分帧 sf=check_ter(x,N,128,10); x=div_frame(x,N,128); %sf=sp_ter(x,4,16); %m=zeros(size(x,1),13); m=zeros(1,13); % 计算每帧的MFCC参数 for i=1:size(x,1) if sf(i)==1 % j=j+1; y = x(i,:); y = y' .* hamming(N); energy=log(sum(y.^2)+eps);%能量 y = abs(fft(y)); y = y.^2+eps; c1=dct(log(bank * y)); c2 = c1(2:13).*w';%取2~13个系数 %m(i,:)=[c2;energy]'; m1=[c2;energy]'; %m1=c2'; m=[m;m1]; end end %差分系数 dm = zeros(size(m)); dmm= zeros(size(m)); for i=2:size(m,1)-1 dm(i,:) = (m(i,:) - m(i-1,:)); end for i=3:size(m,1)-2 dmm(i,:) = (dm(i,:) - dm(i-1,:)); end %dm = dm / 3; function v=lbg(x,k) %lbg:完成lbg均值聚类算法 % lbg(x,k) 对输入样本x,分成k类。其中,x为row*col矩阵,每一列为一个样本, % 每个样本有row个元素。 % [v1 v2 v3 ...vk]=lbg(...)返回k个分类,其中vi为结构体,vi.num为该类 % 中含有元素个数,vi.ele(i)为第i个元素值,vi.mea为相应类别的均值 [row,col]=size(x); %u=zeros(row,k);%每一列为一个中心值 epision=0.03;%选择epision参数 delta=0.01; %u2=zeros(row,k); %LBG算法产生k个中心 u=mean(x,2);%第一个聚类中心,总体均值 for i3=1:log2(k) u=[u*(1-epision),u*(1+epision)];%双倍 %time=0; D=0; DD=1; while abs(D-DD)/DD>delta %sum(abs(u2(:).^2-u(:).^2))>0.5&&(time<=80) %u2~=u DD=D; for i=1:2^i3 %初始化 v(i).num=0; v(i).ele=zeros(row,1); end for i=1:col %第i个样本 distance=dis(u,x(:,i));%第i个样本到各个中心的距离 [val,pos]=min(distance); v(pos).num=v(pos).num+1;%元素的数量加1 if v(pos).num==1 %ele为空 v(pos).ele=x(:,i); else v(pos).ele=[v(pos).ele,x(:,i)]; end end for i=1:2^i3 u(:,i)=mean(v(i).ele,2);%新的均值中心 for m=1:size(v(i).ele,2) D=D+sum((v(i).ele(m)-u(:,i)).^2); end end end end
三、运行结果
四、备注
完整代码或者代写添加QQ1575304183
往期回顾>>>>>>
【信号处理】基于HMM的睡眠状态检测matlab源码
【语音识别】基于BP神经网络的语音情感识别matlab源码
【情感识别】基于改进KNN语音情感分类识别malab源码含GUI
【语音识别】基于高斯混合模型(GMM)的语音识别matlab源码
【语音识别】基于动态时间规整(DTW)的孤立字语音识别matlab源码
【语音识别】基于隐马尔可夫模型(HMM)的孤立字语音识别matlab源码
这篇关于【语音识别】基于矢量量化(VQ)说话人识别matlab源码的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-01后台管理开发学习:新手入门指南
- 2024-11-01后台管理系统开发学习:新手入门教程
- 2024-11-01后台开发学习:从入门到实践的简单教程
- 2024-11-01后台综合解决方案学习:从入门到初级实战教程
- 2024-11-01接口模块封装学习入门教程
- 2024-11-01请求动作封装学习:新手入门教程
- 2024-11-01登录鉴权入门:新手必读指南
- 2024-11-01动态面包屑入门:轻松掌握导航设计技巧
- 2024-11-01动态权限入门:新手必读指南
- 2024-11-01动态主题处理入门:新手必读指南