Double Sparsity: Learning Sparse Dictionaries for Sparse Signal Approximation

from:http://rabbit3306.diandian.com/post/2012-06-14/40027417022


12-14是Ron Rubinstein, Student Member, IEEE, Michael Zibulevsky, and Michael Elad, Senior Member, IEEE. 2010.2.10

字典分两种,一种是隐性字典,implicit dictionary,这种主要是由它们的算法表现出来的,而不是矩阵结构,比如wavelet,curvelet,contourlet,等等。另一种是通过机器学习来从样本中获取字典,这种字典表现为一种显性矩阵,explicit matrix,而算法是用来适应矩阵的,比如PCA,GPCA,MOD,K-SVD等等,这种字典的好处在于比前一种灵活,表现也好,坏处就是耗费时间和运算资源,另外复杂的约束限制了字典的大小以及需要处理的信号的维度(所以论文提出的这个算法最后用3D图像去噪来表现优越性)。

本文提出的方法跨越了这两种字典的鸿沟。

之前存在的算法,一种是正交基的归一化组合,这种方法通过块协调松弛(Block-coordinate-relaxation BCR)可以稀疏表发,并且算法简单有效(有效是指的是字典收敛得快?),但是缺点是字典结构太严格了,并且表现不好。一种是半多层次结构算法,硬性地将子字典排列成一种稀疏的形式,本文的方法就是吸收了这种稀疏字典的形式。还有一种是Signature字典,这种字典来源于一个紧致的Signature图像,图像的没一个子块构成了字典的一个原子。这种字典的好处是几乎是translation-invariance,减少过重叠,当用相邻信号块的关系的时候编码很快,但是这种字典的参数很少,每个原子一个系数也导致字典更严格,这篇论文提出的方法就是增加了参数,每个原子的系数1到p之间。

字典的两个主要性质:复杂度和适应性,第一个性质是指操作性,需要多复杂的操作步数,比如OMP等等;第二个性质是指适用性,是否在不同图像上普遍表现好。第二个性质的代表就是小波。

怎样兼顾这两者呢?这就需要一个带参数的字典模型提供足够的自由度。从K-SVD方法提取出来的字典中可以看到,字典本身是有结构的,原子本身是规则的,因此或许可以假设字典本身在某个更基础的字典上是稀疏的。

因此之前的D就可以代换成Fai*A,A是一个稀疏矩阵。Y=Fai*A*X;双稀疏字典的算法就是在已知Y的情况下计算出稀疏矩阵A和稀疏表示X。Fai其实和训练字典一样,随便选个初始化的值,会随着迭代变化,最后变成理想字典,若用最后的Fai做字典,那么稀疏表示是A*X,若用Fai*A做字典,那么稀疏表示是X。

算法解释:大体上就是两次K-SVD的嵌套,如果按照论文的步骤,12-14步是一次K-SVD,只更新了稀疏表示a,没有更新字典的原子;5-15步是一次K-SVD,更新了稀疏表示X,字典的原子更新是通过稀疏表示a的更新实现的。初始化各个值之后,把Fai*A看做一体,用K-SVD求X,然后注意力集中在A的一行上,以及X的对应一列上,计算这一行和这一列的贡献,用K-SVD求这个贡献在Fai上的稀疏表示,求出来的稀疏表示替代了A原来那一行,同时更新X的一列。

clear all

%% 初始化,和前面很多一样的地方,因为我懒,借用了,

if not(exist('w'))

w = 10;

end

n = w*w;

p = 2*n; % 字典中原子的个数

m = 20*p; % 训练用块数的多少

sp1 = 4; % 稀疏表示X的稀疏度

sp2=3; % 稀疏矩阵A的稀疏度

if not(exist('f'))

f = rescale( crop(load_image('barb'),256) ); % 截取原图像的中心区域

end

n0 = size(f,1);

q = 3*m;% Overlapping

x = floor( rand(1,1,q)*(n0-w) )+1; % 随机选取块的中心像素位置,x坐标

y = floor( rand(1,1,q)*(n0-w) )+1; % 随机选取块的中心像素位置,y坐标

[dY,dX] = meshgrid(0:w-1,0:w-1);

Xp = repmat(dX,[1 1 q]) + repmat(x, [w w 1]);

Yp = repmat(dY,[1 1 q]) + repmat(y, [w w 1]);

Y = f(Xp+(Yp-1)*n0);

Y = reshape(Y, [n q]);

Y = Y - repmat( mean(Y), [n 1] );

[tmp,I] = sort(sum(Y.^2), 'descend'); % 按照递减排列

Y = Y(:,I(1:m)); % 取前m个作为训练样本

ProjC = @(D)D ./ repmat( sqrt(sum(D.^2)), [w^2, 1] );% 归一化

sel = randperm(m);

sel = sel(1:p);

D0 = ProjC( Y(:,sel) ); % 取p个归一化后的训练样本作为初始字典

D = D0;

It=15; % 循环次数

A0 = eye(200,200); % 初始化A0,这里有点不懂,论文上关于A也没说太清感觉,是我没看太懂吧还是,反正A是可以随便选的,当然前提是要稀疏,我开始选了ones,明显就不行

A=A0; % 初始化A,

for i=1:It % 总的循环次数

Xs=zeros(p,m);

%% OMP求稀疏表示

D1=D*A; % 固定D和A,把D*A看做字典

F = omp_m(m,Y,p,D1,n,sp1,Xs); % 用OMP的子函数算出稀疏表示X

X=F;

%% 计算稀疏矩阵A

for ite = 1:p

eff = A(ite,:)*X;

A(ite,:)=A0(ite,:)*0; % 抽取A的一行,取一行而非一列的原因和K-SVD一样,

Pos = find(eff); % A的一行被值为零,若eff中有不为零的,即为用到了A的这一行

if ~isempty(Pos) % 有时候A的这一行根本就没用着……

G=X(ite,Pos);

moG = G*G'; % 问题就在这里,有时候2范数为0!!

G = G/moG; % 求出的X的一行的归一化,

Yi=Y(:,Pos); % Y=D*A*X,X的一行当中不为0的数,反映在Y中就是Y的列

z=Yi*G'-D*A*X(:,Pos)*G'; % 计算A的一行和X的一行的贡献,本来A的一行的贡献为(Yi-D*A*X(:,Pos)),这个贡献再乘以G,就是再缩减到X的一行的贡献

Di=1;Xo = zeros(p,1);

a = omp_m(Di,z,p,D,sp2,Xo); % 用OMP的子函数计算出稀疏表示a,

auni=D*a;

auni=auni'*auni;

a=a/auni;

A(ite,:)=a; % 更新稀疏表示,这里用这种方法替代了SVD

Y2 = D*A*X(:,Pos);

X2 = Yi'*D*a-Y2'*D*a;

X(ite,Pos) = X2'; % 这里更新了外面一层的稀疏表示

end

end

end


你可能感兴趣的:(算法,image,XP,Matrix,Dictionary,Signal)