comparison matlab/OMP/greed_omp_qr.m @ 2:735a0e24575c

Organized folders: added tests, apps, matlab, docs folders. Added __init__.py files
author nikcleju
date Fri, 21 Oct 2011 13:53:49 +0000
parents
children
comparison
equal deleted inserted replaced
1:2a2abf5092f8 2:735a0e24575c
1 function [s, err_mse, iter_time]=greed_omp_qr(x,A,m,varargin)
2 % greed_omp_qr: Orthogonal Matching Pursuit algorithm based on QR
3 % factorisation
4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % Usage
6 % [s, err_mse, iter_time]=greed_omp_qr(x,P,m,'option_name','option_value')
7 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
9 % Input
10 % Mandatory:
11 % x Observation vector to be decomposed
12 % P Either:
13 % 1) An nxm matrix (n must be dimension of x)
14 % 2) A function handle (type "help function_format"
15 % for more information)
16 % Also requires specification of P_trans option.
17 % 3) An object handle (type "help object_format" for
18 % more information)
19 % m length of s
20 %
21 % Possible additional options:
22 % (specify as many as you want using 'option_name','option_value' pairs)
23 % See below for explanation of options:
24 %__________________________________________________________________________
25 % option_name | available option_values | default
26 %--------------------------------------------------------------------------
27 % stopCrit | M, corr, mse, mse_change | M
28 % stopTol | number (see below) | n/4
29 % P_trans | function_handle (see below) |
30 % maxIter | positive integer (see below) | n
31 % verbose | true, false | false
32 % start_val | vector of length m | zeros
33 %
34 % Available stopping criteria :
35 % M - Extracts exactly M = stopTol elements.
36 % corr - Stops when maximum correlation between
37 % residual and atoms is below stopTol value.
38 % mse - Stops when mean squared error of residual
39 % is below stopTol value.
40 % mse_change - Stops when the change in the mean squared
41 % error falls below stopTol value.
42 %
43 % stopTol: Value for stopping criterion.
44 %
45 % P_trans: If P is a function handle, then P_trans has to be specified and
46 % must be a function handle.
47 %
48 % maxIter: Maximum number of allowed iterations.
49 %
50 % verbose: Logical value to allow algorithm progress to be displayed.
51 %
52 % start_val: Allows algorithms to start from partial solution.
53 %
54 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 % Outputs
56 % s Solution vector
57 % err_mse Vector containing mse of approximation error for each
58 % iteration
59 % iter_time Vector containing computation times for each iteration
60 %
61 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62 % Description
63 % greed_omp_qr performs a greedy signal decomposition.
64 % In each iteration a new element is selected depending on the inner
65 % product between the current residual and columns in P.
66 % The non-zero elements of s are approximated by orthogonally projecting
67 % x onto the selected elements in each iteration.
68 % The algorithm uses QR decomposition.
69 %
70 % See Also
71 % greed_omp_chol, greed_omp_cg, greed_omp_cgp, greed_omp_pinv,
72 % greed_omp_linsolve, greed_gp, greed_nomp
73 %
74 % Copyright (c) 2007 Thomas Blumensath
75 %
76 % The University of Edinburgh
77 % Email: thomas.blumensath@ed.ac.uk
78 % Comments and bug reports welcome
79 %
80 % This file is part of sparsity Version 0.1
81 % Created: April 2007
82 %
83 % Part of this toolbox was developed with the support of EPSRC Grant
84 % D000246/1
85 %
86 % Please read COPYRIGHT.m for terms and conditions.
87
88 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
89 % Default values and initialisation
90 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91
92
93 [n1 n2]=size(x);
94 if n2 == 1
95 n=n1;
96 elseif n1 == 1
97 x=x';
98 n=n2;
99 else
100 display('x must be a vector.');
101 return
102 end
103
104 sigsize = x'*x/n;
105 initial_given=0;
106 err_mse = [];
107 iter_time = [];
108 STOPCRIT = 'M';
109 STOPTOL = ceil(n/4);
110 MAXITER = n;
111 verbose = false;
112 s_initial = zeros(m,1);
113
114
115 if verbose
116 display('Initialising...')
117 end
118
119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 % Output variables
121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122
123 switch nargout
124 case 3
125 comp_err=true;
126 comp_time=true;
127 case 2
128 comp_err=true;
129 comp_time=false;
130 case 1
131 comp_err=false;
132 comp_time=false;
133 case 0
134 error('Please assign output variable.')
135 otherwise
136 error('Too many output arguments specified')
137 end
138
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140 % Look through options
141 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142
143 % Put option into nice format
144 Options={};
145 OS=nargin-3;
146 c=1;
147 for i=1:OS
148 if isa(varargin{i},'cell')
149 CellSize=length(varargin{i});
150 ThisCell=varargin{i};
151 for j=1:CellSize
152 Options{c}=ThisCell{j};
153 c=c+1;
154 end
155 else
156 Options{c}=varargin{i};
157 c=c+1;
158 end
159 end
160 OS=length(Options);
161 if rem(OS,2)
162 error('Something is wrong with argument name and argument value pairs.')
163 end
164
165 for i=1:2:OS
166 switch Options{i}
167 case {'stopCrit'}
168 if (strmatch(Options{i+1},{'M'; 'corr'; 'mse'; 'mse_change'},'exact'));
169 STOPCRIT = Options{i+1};
170 else error('stopCrit must be char string [M, corr, mse, mse_change]. Exiting.'); end
171 case {'stopTol'}
172 if isa(Options{i+1},'numeric') ; STOPTOL = Options{i+1};
173 else error('stopTol must be number. Exiting.'); end
174 case {'P_trans'}
175 if isa(Options{i+1},'function_handle'); Pt = Options{i+1};
176 else error('P_trans must be function _handle. Exiting.'); end
177 case {'maxIter'}
178 if isa(Options{i+1},'numeric'); MAXITER = Options{i+1};
179 else error('maxIter must be a number. Exiting.'); end
180 case {'verbose'}
181 if isa(Options{i+1},'logical'); verbose = Options{i+1};
182 else error('verbose must be a logical. Exiting.'); end
183 case {'start_val'}
184 if isa(Options{i+1},'numeric') & length(Options{i+1}) == m ;
185 s_initial = Options{i+1};
186 initial_given=1;
187 else error('start_val must be a vector of length m. Exiting.'); end
188 otherwise
189 error('Unrecognised option. Exiting.')
190 end
191 end
192
193
194
195 if strcmp(STOPCRIT,'M')
196 maxM=STOPTOL;
197 else
198 maxM=MAXITER;
199 end
200
201 if nargout >=2
202 err_mse = zeros(maxM,1);
203 end
204 if nargout ==3
205 iter_time = zeros(maxM,1);
206 end
207
208
209
210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211 % Make P and Pt functions
212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213
214 if isa(A,'float') P =@(z) A*z; Pt =@(z) A'*z;
215 elseif isobject(A) P =@(z) A*z; Pt =@(z) A'*z;
216 elseif isa(A,'function_handle')
217 try
218 if isa(Pt,'function_handle'); P=A;
219 else error('If P is a function handle, Pt also needs to be a function handle. Exiting.'); end
220 catch error('If P is a function handle, Pt needs to be specified. Exiting.'); end
221 else error('P is of unsupported type. Use matrix, function_handle or object. Exiting.'); end
222
223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
224 % Random Check to see if dictionary is normalised
225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226
227 % Commented by Nic, 13 Sept 2011
228 % Don't want any slow text output
229 % mask=zeros(m,1);
230 % mask(ceil(rand*m))=1;
231 % nP=norm(P(mask));
232 % if abs(1-nP)>1e-3;
233 % display('Dictionary appears not to have unit norm columns.')
234 % end
235
236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237 % Check if we have enough memory and initialise
238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239
240
241 try Q=zeros(n,maxM);
242 catch error('Variable size is too large. Please try greed_omp_chol algorithm or reduce MAXITER.')
243 end
244 try R=zeros(maxM);
245 catch error('Variable size is too large. Please try greed_omp_chol algorithm or reduce MAXITER.')
246 end
247
248
249
250
251 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
252 % Do we start from zero or not?
253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254
255 if initial_given ==1;
256 IN = find(s_initial);
257 if ~isempty(IN)
258 Residual = x-P(s_initial);
259 lengthIN=length(IN);
260 z=[];
261 for k=1:length(IN)
262 % Extract new element
263 mask=zeros(m,1);
264 mask(IN(k))=1;
265 new_element=P(mask);
266
267 % Orthogonalise new element
268 qP=Q(:,1:k-1)'*new_element;
269 q=new_element-Q(:,1:k-1)*(qP);
270
271 nq=norm(q);
272 q=q/nq;
273 % Update QR factorisation
274 R(1:k-1,k)=qP;
275 R(k,k)=nq;
276 Q(:,k)=q;
277
278 z(k)=q'*x;
279 end
280 s = s_initial;
281 Residual=x-Q(:,k)*z;
282 oldERR = Residual'*Residual/n;
283 else
284 IN = [];
285 Residual = x;
286 s = s_initial;
287 sigsize = x'*x/n;
288 oldERR = sigsize;
289 k=0;
290 z=[];
291 end
292
293 else
294 IN = [];
295 Residual = x;
296 s = s_initial;
297 sigsize = x'*x/n;
298 oldERR = sigsize;
299 k=0;
300 z=[];
301 end
302
303
304
305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306 % Main algorithm
307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
308 if verbose
309 display('Main iterations...')
310 end
311 tic
312 t=0;
313 DR=Pt(Residual);
314 done = 0;
315 iter=1;
316
317 %Nic: find norms of dictionary atoms, for RandOMP
318 % for i = 1:m
319 % norms(i) = norm(P([zeros(i-1,1) ; 1 ; zeros(m-i,1)]));
320 % end
321
322 while ~done
323
324 % Select new element
325 DR(IN)=0;
326 % Nic: replace selection with random variable
327 % i.e. Randomized OMP!!
328 % DON'T FORGET ABOUT THIS!!
329 [v I]=max(abs(DR));
330 %I = randp(exp(abs(DR).^2 ./ (norms.^2)'), [1 1]);
331 IN=[IN I];
332
333
334 k=k+1;
335 % Extract new element
336 mask=zeros(m,1);
337 mask(IN(k))=1;
338 new_element=P(mask);
339
340 % Orthogonalise new element
341 qP=Q(:,1:k-1)'*new_element;
342 q=new_element-Q(:,1:k-1)*(qP);
343
344 nq=norm(q);
345 q=q/nq;
346 % Update QR factorisation
347 R(1:k-1,k)=qP;
348 R(k,k)=nq;
349 Q(:,k)=q;
350
351 z(k)=q'*x;
352
353 % New residual
354 Residual=Residual-q*(z(k));
355 DR=Pt(Residual);
356
357 ERR=Residual'*Residual/n;
358 if comp_err
359 err_mse(iter)=ERR;
360 end
361
362 if comp_time
363 iter_time(iter)=toc;
364 end
365
366 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
367 % Are we done yet?
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369
370 if strcmp(STOPCRIT,'M')
371 if iter >= STOPTOL
372 done =1;
373 elseif verbose && toc-t>10
374 display(sprintf('Iteration %i. --- %i iterations to go',iter ,STOPTOL-iter))
375 t=toc;
376 end
377 elseif strcmp(STOPCRIT,'mse')
378 if comp_err
379 if err_mse(iter)<STOPTOL;
380 done = 1;
381 elseif verbose && toc-t>10
382 display(sprintf('Iteration %i. --- %i mse',iter ,err_mse(iter)))
383 t=toc;
384 end
385 else
386 if ERR<STOPTOL;
387 done = 1;
388 elseif verbose && toc-t>10
389 display(sprintf('Iteration %i. --- %i mse',iter ,ERR))
390 t=toc;
391 end
392 end
393 elseif strcmp(STOPCRIT,'mse_change') && iter >=2
394 if comp_err && iter >=2
395 if ((err_mse(iter-1)-err_mse(iter))/sigsize <STOPTOL);
396 done = 1;
397 elseif verbose && toc-t>10
398 display(sprintf('Iteration %i. --- %i mse change',iter ,(err_mse(iter-1)-err_mse(iter))/sigsize ))
399 t=toc;
400 end
401 else
402 if ((oldERR - ERR)/sigsize < STOPTOL);
403 done = 1;
404 elseif verbose && toc-t>10
405 display(sprintf('Iteration %i. --- %i mse change',iter ,(oldERR - ERR)/sigsize))
406 t=toc;
407 end
408 end
409 elseif strcmp(STOPCRIT,'corr')
410 if max(abs(DR)) < STOPTOL;
411 done = 1;
412 elseif verbose && toc-t>10
413 display(sprintf('Iteration %i. --- %i corr',iter ,max(abs(DR))))
414 t=toc;
415 end
416 end
417
418 % Also stop if residual gets too small or maxIter reached
419 if comp_err
420 if err_mse(iter)<1e-16
421 display('Stopping. Exact signal representation found!')
422 done=1;
423 end
424 else
425
426
427 if iter>1
428 if ERR<1e-16
429 display('Stopping. Exact signal representation found!')
430 done=1;
431 end
432 end
433 end
434
435 if iter >= MAXITER
436 display('Stopping. Maximum number of iterations reached!')
437 done = 1;
438 end
439
440 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
441 % If not done, take another round
442 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
443
444 if ~done
445 iter=iter+1;
446 oldERR=ERR;
447 end
448 end
449
450 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
451 % Now we can solve for s by back-substitution
452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453
454 s(IN)=R(1:k,1:k)\z(1:k)';
455
456 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
457 % Only return as many elements as iterations
458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459
460 if nargout >=2
461 err_mse = err_mse(1:iter);
462 end
463 if nargout ==3
464 iter_time = iter_time(1:iter);
465 end
466 if verbose
467 display('Done')
468 end
469
470 % Change history
471 %
472 % 8 of Februray: Algo does no longer stop if dictionary is not normaliesd.