今天摸鱼时候把OMP算法给整理一下,以及我自己的理解,如有不正确的地方,欢迎大家指正。
为什么要OMP
我们看到,当我们对这样非齐次方程组求解时(特别注意,要求m远小于n),矩阵D一定不是可逆的(讨论的是狭义的逆矩阵,为什么不用广义逆矩阵下面再讨论),甚至不是方阵。
我们需要对a提一些其他的条件,比如说“稀疏”
那么我们就可以理解为y可以被矩阵D中某些(由于稀疏的原因)列向量表示。也就是说:
接下来的问题就变成了:如何找到对y贡献较大的"那些向量并求出系数向量a?
算法过程
我们假定当前矩阵D有三个列向量,d1,d2,d3。待表示向量y。
1、初始化
索引集M为空集,初始残差r=y,D_new为空集
分别计算d1,d2,d3和残差r(初始时候r=y)的内积。
选择λ最大的索引和di(i=1,2,3)加入我们本次选择λ1最大,那么将1更新到索引集合中(索引集合的目的就是防止后面迭代更新中一直选择同一个di)。把d1更新到D_new里面,也就是说,此时的D_new=[d1]。
接下来,通过最小二乘法的方式计算a_1=argmin||D_new *a-y||,求得a_1。
还记得我刚才说广义逆矩阵那个地方吗?假定说D是2x3的矩阵,那么此时的矩阵D_new无法求狭义逆矩阵吧。因此用到了矩阵的伪逆,也就是广义逆矩阵。
求得了a_1后,接下来计算残差r=y-D_new * a_1
那么第一次的更新就更新完了。进入下一个更新之前,还记得索引集吗?此时就派上用场了,如果我们不把d1剔除,那么下一次的循环可能还是选到d1,因此才有了这一步。
接下来的循环同上,直到完成稀疏度。
到此为止,算法完毕。
我自己写的代码,欢迎大家批评指正
function x=OMP_mine(D,y,sparsity)
[D_row,D_col]=size(D);
r=y;
D_new=[];
index_list=[];
for i=1:sparsity
[lambda,index]=max(abs(D'*y)); %%计算哪个贡献最大,并保留索引
index_list=[index_list index];%% 更新索引集
D_new=[D_new D(:,index)]; %%更新D_new
hat_a=inv(D_new'*D_new)*D_new'*y;%%伪逆求最小二乘法
r=y-D_new*hat_a; %%求残差
D(:,index)=zeros(D_row,1); %%这里是为了把选过的给剔除掉(我是将那一列置为0)
end
x=zeros(D_col,1);
x(index_list)=hat_a;
end
参考文献
Usman, Koredianto, (2017), Introduction to Orthogonal Matching Pursuit, Telkom University
Online : http://korediantousman.staff.telkomuniversity.ac.id, access : your access time.