矢量量化
声明
本文章只用于本人的自我学习和研究,文章内容来自网络和本人的理解。
文章将不会用于商业用途或其他非学习交流用途,未经本人允许,不得转载。
前言
首先,我们应该先明白矢量量化这个词是什么含义
VQ是基于香农的速率失真理论的一种有效的有损压缩技术
基本原理
矢量量化是标量量化的托广和延申
1.通俗的语言阐述
矢量量化的本质是一种“估计”的思想,有点类似于信号处理里面的将连续信号进行采样得到离散信号,或者说将“模拟”的事物(本身存在着大量的信息)提取成“数字"的事物(部分有用的信息),我们提取的越精细,“数字”事物就越接近"模拟“事物。
2. 偏数学化的语言来阐述
假设存在一个N维的矢量空间,空间内存在K个矢量
分别为X1,X2,…,XK。
类似于一维矢量由一个坐标确定,二维矢量由两个坐标确定
任意N维矢量表示为Xi={Xi1,Xi2,…,Xin), i=1, 2…, K
然后我们可以对矢量空间进行划分
我们将N维空间RN无遗漏的划分为J个互补相交的子空间 R1,R2,…,RJ
子空间满足
R1∪R2∪…∪RJ=RN
Ri∩Rj=空集, i≠j。
这些子空间称为cell(胞腔)
此时就可以开启我们的"估计"之旅了
我们从每一个cell中找出一个代表矢量
Yi={yi1, yi2, …, yiN}, i=1, 2…, J
这些代表矢量的集合称为码书或码本
代表矢量称为码字或码矢
J称为码书长度
矢量量化的过程就是对任意输入矢量X∈RN, 在Y中找到一个与X最接近的Yi代替X, Yi就是X的量化值。
矢量量化的过程可以看成是从N维欧氏空间RN到其中一个有限子集Y的映射。这个映射可为:
Q:RN→Y={Y1, Y2, …, YJ}。
问题分析
对于VQ问题我们可以这样归纳:
对于一个给定的已知统计属性的矢量源(训练样本集)和一个给定的失真测度
在给定码矢的前提下,我们该如何对空间进行划分并且找到一个具有最小平均失真度(本文暂不解释)的码书
优化算法_LBG算法
要优化问题的解法,就要从空间划分(后文用P代替)和能使D(平均失真度)最小的码书(后文用C代替)
此类优化问题个人觉得有点类似于回归方程的思想,找到最近的距离
要介绍LBG算法首先要介绍两个优化准则
1.最近邻条件
意思是任意一子空间应该包含所有与此空间选择的码矢最接近的矢量(和其他码失比较)
对于子空间和子空间的交界处的矢量,要采取一些决策方法
2.质心条件
要求码失应该是其所在子空间内的所用向量的平均向量,且需保证每一个子空间都存在一个向量
LBG算法是一种迭代算法,通过不断的求解上述两个准则,从而不断逼近局部最小值。
对于确定码书,首先我们应该确定一个初始码书
初始码书可以通过分裂得到
分裂思想如下
将初始码书的码失置为所有训练样本的平均值
把这个码矢分裂成两个
把这两个码矢作为初始的码书
不断重复
不断分裂
3.BLG算法步骤
1)给定训练集,选定一个失真阈值L(正数)
2)码失数量为1,值为所有训练样本(矢量)的算术平均值,计算总失真度D(计算欧式距离求和取平均,不多赘述)
3)计算扰乱系数
此时码失的数量有1变为2,码失分裂,得到两个扰乱系数 1+L和1-L
4) 得到新码失
两个码失分别在原来码失的基础上乘以两个扰乱系数
5)迭代
初始失真度D0=D
设置迭代计数器i,置零
(1)样本近似
对于每一个样本,计算其和所有码失的欧式距离的最小值,并用这个码失来代替近似这个样本
(2)更新码失
仍然是用当前子空间的所有训练样本的平均作为这个子空间的新码失
(3)i=i+1
(4)计算新的D
(5)失真度比较
失真度和阈值L进行比较,如果大于L,继续迭代,否则此时的失真度即为最终的失真度,此时的码失即为确定的码失
代码分析
说了半天属实没啥用,还得看代码,这个代码的功能是为了对声纹锁的编码和解码
function r = vqlbg(c,k) %vq算法函数
e = 0.01;%分解系数,即分裂参数;
r = mean(c,2); % 返回c中每一行的平均值,构成一个列向量\\形成第一个码字,即所有帧的特征矢量的形心;
dpr = 10000; % dpr是平均初始失真D0,可以自由设置 很大就行
for i = 1:log2(k)%log2(k)表示当要求质心数为K时,所需分裂的次数;
r = [r*(1+e), r*(1-e)];%分解成两倍列数,即将当前的码书R按括号内的规则分裂,形成2M个码字;
while (1 == 1)
z = disteu(c, r);%d与r的欧氏距离,即待训练的矢量与矢量量化后的码书之间的距离;
[m,ind] = min(z, [], 2);
% 找出z中每一行中最小的数返回到m,并把每个数的列号返回到ind
% 行数即为d中的行数(列数),列数为r中的列数
t = 0; % t表示平均失真D;
for j = 1:2^i
r(:, j) = mean(c(:, find(ind == j)), 2);%
% 找出当ind==j时,数j在z中的所有列数
% 即z中第j列至少有一个元素在它所在的行是最小的
% 求这些列的行平均
% 有可能ind!=j,则r(:,j)会是一个空向量
x = disteu(c(:, find(ind == j)), r(:, j));%x
for q = 1:length(x)
t = t + x(q); % x(q)
end
end
%若相对失真小于某一数值,则停止计算;
if (((dpr - t)/t) < e)
break;
else
dpr = t;
end
end
end