问题描述
假设已有N张稀疏的图像,大小为800*800。请问如何通过稀疏表达的方式对原有图像数据进行压缩,同时保证图像尽量不失真。y向量代表原有的图像(640000维),A是字典矩阵(K*640000),x是稀疏表示向量(K维),因为K远远小于N,我们认为,稀疏表示后的数据获得了大幅的压缩。求A的过程通常称为字典学习。已知A,求x的过程称为稀疏表示。通常这两者可以等同。在实际训练的过程中,为了减少计算量,通常将图像切割为小的patch(8*8或16*16),然后针对这些patch进行训练获得patch字典。另外,值得一提的是,还有一个很火的概念叫压缩感知,和稀疏表示有些关联,但主要是关注在如何减少采样点上。
模型建立
可以将该问题看成一个优化问题,第一项是确保A和xi能够很好地重构yi(失真少),第二项是确保xi尽量稀疏(字典构建耦合性小)。正则项本该用L0范数(非零项的个数),但因为比较难求解,这里用L1范数代替,L1范数代表的是绝对值的和。
模型求解
输入是yi,需要求解的是A和xi。刚开始的时候,A是一个由部分yi构成的初始矩阵,然后求解xi,xi确定后,可以再求优化后的A,如此反复迭代获得最优的结果。这种求解方式称为KSVD,速度比较快。这是两步求解的算法:先固定A,求x,再固定x更新A,交替进行。K-SVD和K-means方法本质上都属于一种压缩的思想,都主要包含以下两个步骤:(1)稀疏编码;(2)字典更新。K-SVD中,稀疏编码可使用OMP方法,然后字典更新使用SVD奇异值分解,细节可参考以下链接的内容:(http://blog.csdn.net/hjimce/article/details/50810129,https://wenku.baidu.com/view/f31e3f82e43a580216fc700abb68a98271feac56.html)
在K-means方法中,K-means 先随机选择K个初始点作为字典,K个初始点就代表K类。然后通过K-means聚类,聚出K个类(稀疏编码阶段),每个聚类中心(均值)做为新的字典(字典更新)。K-means的编码矩阵X是一个高度稀疏的矩阵,X的每一列就只有一个非零的元素,对应聚类中心。而K-SVD的编码矩阵的每一列可以有多个非零元素。
K-SVD方法的求解步骤如下:
1. 基本定义
Y是一个矩阵,是参与训练的样本yi的集合,样本数量为n,假设样本的维度是m。
A是一个矩阵,是字典,该矩阵是k*m,其中k是字典中原子的数量,m是原子的维度(和样本维度一致)
X是一个矩阵,是稀疏代码xi的集合,xi的维度是m
2. 初始化
从样本集Y中随机挑选k个样本,作为A的初始值;并且初始化X为0。
3. 求解xi
为了简单起见,我们抽出一个样本进行讨论,假定样本为y向量,稀疏代码为x向量。现在y和A算是已知的,求解x,同时满足x尽量的稀疏,也就是非零元素尽量的少。假设A为[a1,a2,a3,a4,a5],其中有5个原子。首先求出离y距离最近的原子,假设是a3。那么我们就可以求出一个初步的x为[0,0,c3,0,0],c3是一个未知系数,代表原子的权重。假定y=c3*a3。可求得c3的值。接着我们用求出的c3求残差向量y'=y-c3*α3,y'是一个预设的阈值向量,当y'小于阈值的话,则停止计算,如果不小于的话,转到下一步。
计算剩余的原子a1,a2,a4,a5中与残差向量y'距离最近的,假设是a1,那么更新x为[c1,0,c3,0,0],假设y=c1*a1+c3*a3,求解出c1,然后更新残差向量y'=y-c1*a1-c3*α3。判断是否小于阈值,如果不满足,再继续求下一个最近的原子的系数。求解原子系数的数量也可以指定为一个常量,例如3,那就代表迭代3次。
4. 更新字典
通过上一个步骤可以求出所有的xi,接着就可以更新字典A了。K-SVD的方法是逐个地更新字典的原子以及编码。