Mercurial > hg > pycsalgos
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. |