参考:

1、语音信号处理之(三)矢量量化(Vector Quantization)
这篇真的是非常厉害,在CSDN很多矢量量化的文章都是参考了这篇文章

2、矢量量化
百度文库的PPT,详细的描述了矢量量化

矢量量化说明:

1、其实矢量量化和k-mean 差不多,区别在于矢量量化是从一个码矢开始分裂的,而k-mean一开始就给你N个聚类中心
2、LBG算法是实现矢量量化的一个算法
3、LBG算法码矢分裂过程:
c++ VQ矢量量化 LBG算法 代码实现 详细注释

矢量量化压缩传输过程:

1、输出端把输入数据在码书中寻找欧氏距离的最小值的码矢来代表它,并在传输中传输该码矢在码书中的下标
2、输入端接收到下标则按下标索引码书的到码矢,该码矢就是压缩的原数据

LBG算法步骤:

1、给定训练集T。固定ɛ(失真阈值)为一个很小的正数。

2、让N=1(码矢数量),将这一个码矢设置为所有训练样本的平均值:

c++ VQ矢量量化 LBG算法 代码实现 详细注释
X为数据集,M为样本个数,m为第m个样本数据,C1为码书C的第一个码矢
计算总失真度(这时候的总失真很明显是最大的):
c++ VQ矢量量化 LBG算法 代码实现 详细注释
D*ave 是一个double类型的数,表示所有数据点与他所属的码矢(第一次为C1)的欧氏距离的和的均值
.
我的代码没有相对失真度小于阈值e跳出,因为相对失真度不稳定,我的跳出设置为码矢增长为码书的大小时停止。

3、分裂:对i=1,2,…,N,他们的码矢分别为:

c++ VQ矢量量化 LBG算法 代码实现 详细注释
Ci表示第i个码矢,e为扰乱系数,nums为当前码矢的数量
.
让N=2N,就是每个码矢分裂(乘以扰乱系数1+ɛ和1-ɛ)为两个,这种每一次分裂后的码矢数量就是前一次的两倍。

4、迭代

步骤:

  • 1)对于训练集T中的每一个训练样本m=1,2,…,M。在所有码矢中寻找欧氏距离的最小值,也就是看这个训练样本和哪个码矢距离最近。我们用n*记录这个最小值的索引。然后用这个码矢来近似这个训练样本:
    c++ VQ矢量量化 LBG算法 代码实现 详细注释
    Xm表示第m个数据 该公式表示Xm“属于”第i个码矢
    .
  • 2)对于n=1,2,…,N,通过以下方式更新所有码矢:
    c++ VQ矢量量化 LBG算法 代码实现 详细注释
    也就是将所有属于Cn所在的编码区域Sn的训练样本取平均作为这个编码区域的新的码矢。
    .
  • 3)迭代计数器加1:i=i+1.
    .
  • 4)计算在现阶段的C和P基础上的总失真度:
    c++ VQ矢量量化 LBG算法 代码实现 详细注释
  • 5)如果失真度相比上一次的失真度(相对失真改进量)还大于可以接受的失真阈值ɛ(如果是小于就表明再进行迭代运算失真得减小是有限的以停止迭代运算了),那么继续迭代,返回步骤1)。
    c++ VQ矢量量化 LBG算法 代码实现 详细注释
  • 6)否则最终失真度为
    c++ VQ矢量量化 LBG算法 代码实现 详细注释
    (最终失真度等于当前的失真度)
    .
    对n=1,2,…,N,最终码矢为
    c++ VQ矢量量化 LBG算法 代码实现 详细注释
    (最终码矢等于当前的码矢) (Cn其实就是码书,有n个码矢,每个码矢维度是原始数据的维度)

5、重复步骤3和4至到码矢的数目达到要求的个数。

.

.

.

源代码及数据集下载:

c++ 矢量量化 LBG算法 源码以及数据集

代码使用说明:

  • 1、你需要设置输入数据的个数、维数以及码书大小
    码书大小要设置成2的n次方(重要!)
    c++ VQ矢量量化 LBG算法 代码实现 详细注释
  • 2、你需要把数据集 input.txt 放在源代码所在的文件目录下
  • 3、 如果要修改数据集,那么注意数据集的格式:
    c++ VQ矢量量化 LBG算法 代码实现 详细注释
    每行数据前有行数
    或者修改输入代码 Individual() 函数

输出结果:

控制台:
c++ VQ矢量量化 LBG算法 代码实现 详细注释

相关文章: