annotate util/classes/dictionaryMatrices/rotatematrix.m @ 193:cc540df790f4 danieleb

Simple example that demonstrated dictionary learning... to be completed
author Daniele Barchiesi <daniele.barchiesi@eecs.qmul.ac.uk>
date Fri, 09 Mar 2012 15:12:01 +0000
parents 8fc38e8df8c6
children
rev   line source
daniele@169 1 function [Dhat cost W] = rotatematrix(D,Phi,method,param)
daniele@184 2 %
daniele@169 3 %
daniele@169 4 %
daniele@169 5 % REFERENCE
daniele@169 6 % M.D. Plumbley, Geometrical Methods for Non-Negative ICA: Manifolds, Lie
daniele@169 7 % Groups and Toral Subalgebra, Neurocomputing
daniele@170 8
daniele@170 9 %% Parse inputs and set defaults
daniele@169 10 if ~nargin, testrotatematrix; return, end
daniele@169 11
daniele@170 12 if ~exist('param','var') || isempty(param), param = struct; end
daniele@170 13 if ~exist('method','var') || isempty(method), method = 'conjgradLie'; end
daniele@170 14 if ~isfield(param,'nIter'), param.nIter = 100; end %number of iterations
daniele@170 15 if ~isfield(param,'eps'), param.eps = 1e-9; end %tolerance level
daniele@170 16 if ~isfield(param,'step'), param.step = 0.01; end
daniele@169 17
daniele@170 18 J = @(W) 0.5*norm(D-W*Phi,'fro'); %cost function
daniele@169 19
daniele@170 20 % Initialise variables
daniele@170 21 cost = zeros(param.nIter,1); %cost at each iteration
daniele@170 22 W = eye(size(Phi,1)); %rotation matrix
daniele@170 23 grad = ones(size(W)); %gradient
daniele@170 24 t = param.step; %step size
daniele@170 25 Gprev = 0; %previous gradient
daniele@170 26 Hprev = 0; %previous Lie search direction
daniele@170 27 iIter = 1; %iteration counter
daniele@169 28
daniele@170 29 %% Main algorithm
daniele@170 30 while iIter<=param.nIter && norm(grad,'fro')>eps
daniele@170 31 cost(iIter) = J(W); %calculate cost
daniele@170 32 grad = (W*Phi-D)*Phi'; %calculate gradient
daniele@169 33 switch method
daniele@169 34 case 'unconstrained' % gradient descent
daniele@169 35 eta = param.step;
daniele@169 36 W = W - eta*grad; % update W by steepest descent
daniele@169 37 case 'tangent' % self correcting tangent
daniele@169 38 eta = param.step;
daniele@170 39 W = W - 0.5*eta*(grad - W*grad'*W);
daniele@170 40 [U , ~, V] = svd(W);
daniele@170 41 W = U*V';
daniele@170 42 case 'steepestlie' %steepest descent in Lie algebra
daniele@169 43 eta = param.step;
daniele@170 44 B = 2*skew(grad*W'); % calculate gradient in Lie algebra
daniele@169 45 W = expm(-eta*B)*W; % update W by steepest descent
daniele@170 46 case 'linesearchlie' % line search in Lie algebra
daniele@170 47 B = 2*skew(grad*W'); % calculate gradient in Lie algebra
daniele@169 48 H = -B; % calculate direction as negative gradient
daniele@170 49 t = searchline(J,H,W,t);% line search in one-parameter Lie subalgebra
daniele@169 50 W = expm(t*H)*W; % update W by line search
daniele@170 51 case 'conjgradlie' % conjugate gradient in Lie algebra
daniele@170 52 G = 2*skew(grad*W'); % calculate gradient in Lie algebra
daniele@169 53 H = -G + polakRibiere(G,Gprev)*Hprev; %calculate conjugate gradient direction
daniele@170 54 t = searchline(J,H,W,t);% line search in one-parameter Lie subalgebra
daniele@169 55 W = expm(t*H)*W; % update W by line search
daniele@170 56 Hprev = H; % save search direction
daniele@170 57 Gprev = G; % save gradient
daniele@169 58 end
daniele@170 59 iIter = iIter+1; % update iteration counter
daniele@169 60 end
daniele@170 61 Dhat = W*Phi; %rotate matrix
daniele@172 62 cost(iIter:end) = cost(iIter-1); %zero-pad cost vector
daniele@169 63 end
daniele@169 64
daniele@170 65 %% Support functions
daniele@169 66 function gamma = polakRibiere(G,Gprev)
daniele@170 67 %Polak-Ribiere rule for conjugate direction calculation
daniele@169 68 gamma = G(:)'*(G(:)-Gprev(:))/(norm(Gprev(:))^2);
daniele@169 69 if isnan(gamma) || isinf(gamma)
daniele@169 70 gamma = 0;
daniele@169 71 end
daniele@169 72 end
daniele@169 73
daniele@169 74 function t = searchline(J,H,W,t)
daniele@170 75 %Line search in one-parameter Lie subalgebra
daniele@169 76 t = fminsearch(@(x) J(expm(x*H)*W),t);
daniele@169 77 end
daniele@169 78
daniele@169 79 function B = skew(A)
daniele@170 80 %Skew-symmetric matrix
daniele@169 81 B = 0.5*(A - A');
daniele@169 82 end
daniele@169 83
daniele@169 84
daniele@170 85 %% Test function
daniele@169 86 function testrotatematrix
daniele@169 87 clear, clc, close all
daniele@170 88 n = 256; %ambient dimension
daniele@170 89 m = 512; %number of atoms
daniele@170 90 param.nIter = 300; %number of iterations
daniele@170 91 param.step = 0.001; %step size
daniele@170 92 param.mu = 0.01; %regularization factor (for tangent method)
daniele@184 93 methods = {'tangent','linesearchlie','conjgradlie'};
daniele@169 94
daniele@170 95 Phi = randn(n,m); %initial dictionary
daniele@170 96 Qtrue = expm(skew(randn(n))); %rotation matrix
daniele@170 97 D = Qtrue*Phi; %target dictionary
daniele@170 98
daniele@170 99 cost = zeros(param.nIter,length(methods));
daniele@184 100 times = zeros(param.nIter,length(methods));
daniele@170 101 for iIter=1:length(methods)
daniele@170 102 tic
daniele@170 103 [~, cost(:,iIter)] = rotatematrix(D,Phi,methods{iIter},param);
daniele@184 104 times(:,iIter) = linspace(0,toc,param.nIter);
daniele@184 105 sprintf('Method %s completed in %f seconds \n',methods{iIter},toc)
daniele@170 106 end
daniele@169 107
daniele@184 108 figure, plot(times,cost)
daniele@184 109 set(gca,'XScale','lin','Yscale','log')
daniele@170 110 legend(methods)
daniele@169 111 grid on
daniele@184 112 xlabel('time (sec)')
daniele@169 113 ylabel('J(W)')
daniele@169 114 end