聚类,也可以称为向量量化(vector quantization,VQ),可以看作稀疏表示的一种特殊情况,反过来,稀疏表示则可以当成广义的聚类。在聚类中,每个样本(信号)都被表示成与之最近的码字(codeword),且系数为1;gain-shape VQ的系数可以使任意的,但是表示的codeword的数目也是一个,即也只能用一个codeword表示样本;而稀疏表示则是用原子字典中原子的线性组合来表示样本,即原子个数是任意的(但是是有限制的,否则稀疏表示没有意义),且系数也是任意的。当用于表示样本的原子数目为1时,则稀疏表示相当于gain-shape VQ,若原子的系数也为1,此时,稀疏表示就相当于聚类。
构造聚类码书(codebook)最常用的算法是K-means算法,K-means算法的目的是求得一个codebook使得逼近误差最小,即
其中, 是样本集合, 是由codeword组成的codebook矩阵, 是系数矩阵, 是自然基。
K-means算法构造聚类codebook时,首先初始化一个随机的codebook,即从样本集中随机抽取K个样本作为codebook,然后根据最近邻分配将每个样本分配到与之最近的codeword,聚成K个类,每个codeword就是一个类的聚簇中心;接着,对每个类中的样本坐标取平均值,作为新的codeword,从而完成对codebook的更新。也就是说,K-means算法构造聚类codebook是一个迭代更新的过程,每次迭代主要的步骤有:
1)稀疏编码,即固定codebook矩阵C,求样本集Y的系数矩阵X;
2)更新codebook,即对每个类的样本坐标取平均,求得新的codeword;
K-means算法求聚类codebook的流程图,如图1所示,
图1 K-means算法求聚类码书流程图
可以保证的是,在每次迭代中MSE值减小或者没有变化,,算法保证了MSE的值是单调减少的,且至少收敛到局部最优值。
构造稀疏表示过完备字典的算法有最大似然估计(maximum likelihood method)、最优方向算法(method of optimal directions,MOD)、最大后验概率(maximum a-posteriori probability)、联合标准正交基(unions of orthonormal bases)以及K-SVD等,这些算法都可以看成是广义的K-means算法。K-SVD由于其有效的稀疏编码以及高斯·赛德尔似的加速字典更新过程,使得K-SVD算法非常高效。K-SVD与前几种广义K-means算法明显不同之处是,K-SVD是逐列更新字典的,一次只更新字典的一列,除了要更新的列之外,固定字典中的其他列,而且更新列的同时还更新相应的系数,这使得K-SVD收敛得更快。在某种意义上,K-SVD是K-means更直接的推广,因为K-SVD和K-means一样,都是逐列更新的。还有人建议省去稀疏编码阶段,只保留更新字典阶段,但是这是不可取的,因为如果只有更新字典的步骤,表示系数的支撑集不变,算法必然陷入局部最优。
与K-means算法类似,K-SVD算法的目的也是找到一个原子字典使得逼近误差最小,K-SVD算法的目标函数为:
K-SVD算法跟K-means算法一样,每次迭代只有两个主要的步骤:
1)稀疏编码,固定字典D,求系数矩阵X;
2)逐列更新字典的列以及相应的系数;
在第一个步骤中,相当于对每个样本应用某种追踪算法,求得表示系数的逼近,因为在实际中,一般很难求得全局最优解;在第二个步骤中,将惩罚项中的乘积DX分解为K个秩为1矩阵的和,进一步地,只保留要更新的字典原子 的那一项,即
其中, 为没有 的情况下所有样本的误差矩阵。
至此,可以对 进行SVD分解,得到 和 的近似值,从而更新字典的原子以及相应的系数。但是,如果直接对 进行SVD分解,得到的 的近似值的项全部是非零的,这样的话,不满足目标函数(式(2))稀疏度的限制,从而需要对 做一定的处理后再进行SVD分解。
假设需要当前更新原子 表示的样本为 和 ,用 表示样本的索引, 表示集合 的势,即 , .取 中与 相对应的列组成新的误差矩阵 ,则相当于误差矩阵 右乘相应的变换矩阵 ,其中, 是 的矩阵,除了 项为1外,其余的项都为0.对系数 右乘 效果是一样的,只保留原子 表示样本 和 的系数,此时,惩罚项变为
这样做能保证SVD分解后得到的系数 与原来的系数 有相同的支撑集。对 进行SVD分解,即 ,将U的第一列作为新的原子 ,V的第一列与 相乘作为新的 ,对每个原子进行上述的过程实现字典的更新。K-SVD算法求稀疏表示字典的流程图如图2所示,
图2 K-SVD求稀疏表示字典流程图
聚类只使用一个codeword来表示样本且系数为1,而稀疏表示则使用原子的线性组合来表示样本, 可以将聚类看成是稀疏表示的一种特殊情况,而把稀疏表示当成是广义的聚类 。聚类中是采用K-means算法来求得聚类所用的codebook的,由于二者直接的相似性,我们自然想到了用类似K-means的算法来求得稀疏表示所用的原字字典,从而有了K-SVD算法。聚类与稀疏表示的比较如图3所示,
图3 聚类与稀疏表示的比较