1、Vector Quantization介绍
Vector Quantization(VQ)是一种基于块编码规则的有损数据压缩方法。在诸多领域有广泛应用,比如语音和图像编码或压缩,语音识别等领域。VQ 的 主要优点在于可以减少计算量和存储,缺点就是为了减少计算量和存储所付出的的代价,损失精度。
以二维向量为例,一个二维向量对应坐标上的一个点,所有二维向量的集合就构成了坐标平面。然后通过聚类算法将平面划分成N个区域,满足
如图所示,R代表整个特征空间,划分N个区域,每个区域称作Voronoi Region(包腔), 每个区域有个代表矢量,叫码字(Codewords)。所有码字(Codewords)的集合称作码本(Codebook)。N称为码本的长度或容量。
2、Vector Quantization 在孤立词语音识别的应用
由于后续采用基于DHMM(离散隐马尔科夫)的孤立词识别,所以必须将语音特征参数MFCC向量序列转换成整数序列作为DHMM的观察序列。这个过程就是矢量量化。这样大大地减少了存储量和计算量。
3、Vector Quantization 最优码本的训练—LBG Algorithm
3.1 传统LBG Algorithm
Vector Quantization 最优码本的建立常用算法是K-means和LBG算法。LBG算法是由Linde、Buzo和Gray 三人在1980年提出。LBG算法核心思想通过训练矢量集和一定的迭代算法来逼近最优的再生码本。LBG算法过程描述如下:
标准的LBG算法C语言实现:
#include "stdio.h"
#include "math.h"
struct VQ_VECTOR
{
double* Data; //Input vector
int nDimension; //Dimension of input vector
int nCluster; //Class the vector belong to during clustering
//Value may changed every epoch
char* pFileName;
};
struct VQ_CENTER
{
double* Data; //Clustering center vector
int nDimension;//Dimension of center vector
int Num; //Number of vectors belong to the clustering
};
/******************************************************************************
/* Name: LBGCluster
/* Function: Clustering input vectors using LBG algorithm
/* Using Euclidean distance
/* Parameter: X -- Input vecters
/* N -- Number of input vectors
/* Y -- Clustering result
/* M -- Number of clustering center
/* Return: 0 -- Correct
/* 1 -- Error
/*
/******************************************************************************/
int LBGCluster(VQ_VECTOR *X, int N, VQ_CENTER *Y, int M)
{
if(N<M) return -1;
int L=1000, m=1, nCenter, i, j, k;//L,µü´úµÄ´ÎÊý
int nDimension = X[0].nDimension;
double D0, D;
struct VQ_CENTERINFO
{
double* Data;
int nDimension;
double* SumData;
int Num;
};
VQ_CENTERINFO *Center = (VQ_CENTERINFO*)malloc(M*sizeof(VQ_CENTERINFO));
if(Center == NULL) return -1;
double *Distance = (double*)malloc(N*sizeof(double));
if(Distance == NULL) return -1;
for( i=0; i<M; i++)
{
Center[i].nDimension = nDimension;
Center[i].Data = (double*)malloc(sizeof(double)*nDimension);
Center[i].SumData = (double*)malloc(sizeof(double)*nDimension);
if( Center[i].Data == NULL || Center[i].SumData == NULL )
{
AfxMessageBox( "Memory used up!" );
return -1;
}
for( j=0; j<nDimension; j++ )
{
Center[i].Data[j] = X[i*N/M].Data[j];
Center[i].SumData[j] = 0;
}
Center[i].Num = 0;
}
D0=1; D=1e+10;
while(m<L && fabs(D0-D)/D0>1e-5)
{
for(i=0; i<M; i++)
{
for( j=0; j<nDimension; j++ )
Center[i].SumData[j] = 0;
Center[i].Num = 0;
}
D0 = D; D = 0; m++;
for(i=0; i<N; i++)
{
Distance[i] = 1e+10;
for(int j=0; j<M; j++)
{
double Dist = 0;
for( k=0; k<nDimension; k++ )
Dist += (X[i].Data[k]-Center[j].Data[k])*(X[i].Data[k]-Center[j].Data[k])