深刻理解KSVD字典训练方法

在两个博客的基础上深入理解KSVD算法字典训练过程,包括程序运行的步骤:

http://blog.csdn.net/qq1028850792/article/details/12905977

http://blog.sina.com.cn/s/blog_9206acb20101crbw.html

一。K-均值算法:(每个信号由一个Ck表达)

    输入参数:

    目标函数: ek为自然向量,除第k个分量为1,其余为0

    输出:(1)求坐标矩阵X(本质上是稀疏编码,每一列非零元只有一个),X=[x1,x2,x3,...,xN];(2)矩阵C(迭代更新码本),

   理解:本质是通过N个信号,分成K类,每一类的中心点就是码字,是一个迭代过程

  举例:如下,K=2.

   

二。K-SVD算法-广义K-均值算法(放宽了坐标矩阵X(每一列非零元有多个,记为K0个),每个信号yi由多个Ck线性组合而成)

      

    输入参数:

    目标函数: 字典D相当于码本C

    输出:(1)求坐标矩阵X,X=[x1,x2,x3,...,xN];(2)字典D(迭代更新码本),

    注意:迭代求出目标值的时候,不能立即采用SVD分解来做(否则这样可能使解发散),

    举例:K-SVD最大的不同在字典更新这一步,K-SVD每次更新一个原子(即字典的一列)和其对应的稀疏系数,直到所有的原子更新完毕,重复迭代几次即可得到优化的字典和稀疏系数。如下。

             
           

如上图(左上),现在我们要更新第k个原子,即d_k..那我们需要知道在上一步迭代之后哪些信号使用了该原子,即稀疏系数不为0的部分是哪些?从左上图中很容易看出,x'的第k列T(x_k),也就是x的第k行中不为0的那部分所对应的T(y_k)即是我们要找的信号,结果见左下图蓝色部分。我们用d_k和稀疏系数x(k)'来重构这部分使用了d(k)的信号,它和T(y_k)的差值即E,右上图中绿色部分,接下来我们要使用右下图这个约束来更新x_k和d_k这两个值…如此反复,直到过完备字典D的所有原子更新完毕为止…求解这个x_k和d_k,直接对E进行SVD分解即可。


matlab代码

 
 function [A,x]= KSVD(y,codebook_size,errGoal)  
 
%============================== 
%input parameter 
% y - input signal 
% codebook_size - count of atoms 
%output parameter 
% A - dictionary 
% x - coefficent 

%============================== 
if(size(y,2)<codebook_size) 
   disp('codebook_size is too large or training samples is too small'); 
   return; 
end 
% initialization 
[rows,cols]=size(y);
 r=randperm(cols); 
A=y(:,r(1:codebook_size)); 
A=A./repmat(sqrt(sum(A.^2,1)),rows,1); 
ksvd_iter=10; 
for k=1:ksvd_iter 
 % sparse coding 
        x=OMP(A,y,5.0/6*rows); 
  % update dictionary 
    for m=1:codebook_size 
       mindex=find(x(m,:)); 
       if ~isempty(mindex) 
            mx=x(:,mindex); mx(m,:)=0; my=A*mx; resy=y(:,mindex); 

            mE=resy-my; [u,s,v]=svds(mE,1); A(:,m)=u; x(m,mindex)=s*v';
       end 
   end 
end


你可能感兴趣的:(深刻理解KSVD字典训练方法)