function [eigvector, eigvalue, bSuccess] = OLGE(W, D, options, data) % OLGE: Orthogonal Linear Graph Embedding % % [eigvector, eigvalue, bSuccess] = OLGE(W, D, options, data) % % Input: % data - data matrix. Each row vector of data is a % sample vector. % W - Affinity graph matrix. % D - Constraint graph matrix. % LGE solves the optimization problem of % a* = argmax (a'data'WXa)/(a'data'DXa) % with the constraint a_i'*a_j=0 (i ~= j) % Default: D = I % % options - Struct value in Matlab. The fields in options % that can be set: % % ReducedDim - The dimensionality of the reduced % subspace. If 0, all the dimensions % will be kept. Default is 30. % % Regu - 1: regularized solution, % a* = argmax (a'data'WXa)/(a'data'DXa+ReguAlpha*I) % 0: solve the sinularity problem by SVD (PCA) % Default: 1 % % ReguAlpha - The regularization parameter. Valid % when Regu==1. Default value is 0.1. % % ReguType - 'Ridge': Tikhonov regularization % 'Custom': User provided % regularization matrix % Default: 'Ridge' % regularizerR - (nFea x nFea) regularization % matrix which should be provided % if ReguType is 'Custom'. nFea is % the feature number of data % matrix % % PCARatio - The percentage of principal % component kept in the PCA % step. The percentage is % calculated based on the % eigenvalue. Default is 1 % (100%, all the non-zero % eigenvalues will be kept. % If PCARatio > 1, the PCA step % will keep exactly PCARatio principle % components (does not exceed the % exact number of non-zero components). % % bDisp - 0 or 1. diagnostic information % display % % Output: % eigvector - Each column is an embedding function, for a new % sample vector (row vector) x, y = x*eigvector % will be the embedding result of x. % eigvalue - The sorted eigvalue of the eigen-problem. % % bSuccess - 0 or 1. Indicates whether the OLPP calcuation % is successful. (OLPP needs matrix inverse, % which will lead to eigen-decompose a % non-symmetrical matrix. The caculation precsion % of malab sometimes will cause imaginary numbers % in eigenvectors. It seems that the caculation % precsion of matlab is a little bit random, you % can try again if not successful. More robust % and efficient algorithms are welcome!) % % % Examples: % % See also LGE, OLPP, LPP. % % %Reference: % % 1. Deng Cai and Xiaofei He, "Orthogonal Locality Preserving Indexing" % The 28th Annual International ACM SIGIR Conference (SIGIR'2005), % Salvador, Brazil, Aug. 2005. % % 2. Deng Cai, Xiaofei He, Jiawei Han and Hong-Jiang Zhang, "Orthogonal % Laplacianfaces for Face Recognition". IEEE Transactions on Image % Processing, vol. 15, no. 11, pp. 3608-3614, November, 2006. % % 3. Deng Cai, Xiaofei He, Jiawei Han, "Spectral Regression for Efficient % Regularized Subspace Learning", IEEE International Conference on % Computer Vision (ICCV), Rio de Janeiro, Brazil, Oct. 2007. % % 4. Deng Cai, "Spectral Regression: A Regression Framework for % Efficient Regularized Subspace Learning", PhD Thesis, Department of % Computer Science, UIUC, 2009. % % version 3.0 --Dec/2011 % version 2.0 --May/2007 % version 1.0 --Sep/2006 % % Written by Deng Cai (dengcai AT gmail.com) if (~exist('options','var')) options = []; end ReducedDim = 30; if isfield(options,'ReducedDim') ReducedDim = options.ReducedDim; end if ~isfield(options,'Regu') || ~options.Regu bPCA = 1; if ~isfield(options,'PCARatio') options.PCARatio = 1; end else bPCA = 0; if ~isfield(options,'ReguType') options.ReguType = 'Ridge'; end if ~isfield(options,'ReguAlpha') options.ReguAlpha = 0.1; end end if ~isfield(options,'bDisp') options.bDisp = 1; end bD = 1; if ~exist('D','var') || isempty(D) bD = 0; end [nSmp,nFea] = size(data); if size(W,1) ~= nSmp error('W and data mismatch!'); end if bD && (size(D,1) ~= nSmp) error('D and data mismatch!'); end %====================================== % SVD %====================================== if bPCA [U, S, V] = mySVD(data); [U, S, V]=CutonRatio(U,S,V,options); data = U*S; eigvector_PCA = V; if bD DPrime = data'*D*data; else DPrime = data'*data; end DPrime = max(DPrime,DPrime'); else if bD DPrime = data'*D*data; else DPrime = data'*data; end switch lower(options.ReguType) case {lower('Ridge')} for i=1:size(DPrime,1) DPrime(i,i) = DPrime(i,i) + options.ReguAlpha; end case {lower('Tensor')} DPrime = DPrime + options.ReguAlpha*options.regularizerR; case {lower('Custom')} DPrime = DPrime + options.ReguAlpha*options.regularizerR; otherwise error('ReguType does not exist!'); end DPrime = max(DPrime,DPrime'); end WPrime = data'*W*data; WPrime = max(WPrime,WPrime'); %====================================== % Generalized Eigen with Orthogonal Constraint %====================================== dimM = size(WPrime,2); if ReducedDim > dimM ReducedDim = dimM; end rDPrime = chol(DPrime); lDPrime = rDPrime'; Q0 = rDPrime\(lDPrime\WPrime); % Q0 = inv(DPrime)*WPrime; eigvector = []; eigvalue = []; tmpD = []; Q = Q0; bSuccess = 1; for i = 1:ReducedDim, try option = struct('disp',0); [eigVec, eigv] = eigs(Q,1,'lr',option); catch disp('eigs Error!'); bSuccess = 0; return; end if ~isreal(eigVec) disp('Virtual part!'); bSuccess = 0; break; end if eigv < 1e-3 break; end eigvector = [eigvector, eigVec]; % Each col of D is a eigenvector eigvalue = [eigvalue;eigv]; tmpD = [tmpD, rDPrime\(lDPrime\eigVec)]; % tmpD = inv(DPrime)*D; DTran = eigvector'; tmptmpD = DTran*tmpD; tmptmpD = max(tmptmpD,tmptmpD'); rtmptmpD = chol(tmptmpD); tmptmpD = rtmptmpD\(rtmptmpD'\DTran); % tmptmpD = inv(D'*inv(DPrime)*D)*D' Q = -tmpD*tmptmpD; for j=1:dimM Q(j,j) = Q(j,j) + 1; end Q = Q*Q0; if (mod(i,10) == 0) && options.bDisp disp([num2str(i),' eigenvector calculated!']); end end if bPCA if bSuccess eigvector = eigvector_PCA*eigvector; elseif size(eigvector,1) == size(eigvector_PCA,2) eigvector = eigvector_PCA*eigvector; end end function [U, S, V]=CutonRatio(U,S,V,options) if ~isfield(options, 'PCARatio') options.PCARatio = 1; end eigvalue_PCA = full(diag(S)); if options.PCARatio > 1 idx = options.PCARatio; if idx < length(eigvalue_PCA) U = U(:,1:idx); V = V(:,1:idx); S = S(1:idx,1:idx); end elseif options.PCARatio < 1 sumEig = sum(eigvalue_PCA); sumEig = sumEig*options.PCARatio; sumNow = 0; for idx = 1:length(eigvalue_PCA) sumNow = sumNow + eigvalue_PCA(idx); if sumNow >= sumEig break; end end U = U(:,1:idx); V = V(:,1:idx); S = S(1:idx,1:idx); end