⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mvu.m

📁 流形学习中的重要方法MVU的源代码
💻 M
字号:
function [Y,details]=mvu(DD,K,varargin)% [Y,details]=mvu(DD,K,pars)%% 参数介绍% DD    SQUARED distance matrix of the input vectors (e.g. euclidean% distances)数据点的距离平方矩阵%% Optional:%% K     number of neighbors 领域点个数%% pars  Parameters%%       pars.solver    chooses the MVU solver:%       pars.solver=0  CSDP   (default)%       pars.solver=1  SeDuMi%       pars.solver=2  SDPT3  (very fast - not fully tested)%%       pars.slack     switches slack variables on or off启动或关闭松弛变量%       pars.slack=0    (default)%       pars.slack=1   allows distances only to grow 允许距离增长%       pars.slack=2   allows both growing and shrinking of distances既允许距离增长也允许距离收缩     %       pars.slack=3   allows distances only to shrink只允许距离收缩%                      (in combination with pars.factor=0 leads to%                      inequality)%%       pars.factor    Weight of penalty of Slack variables (only if%       pars.slac>0)松弛变量的惩罚权重%                      if pars.factor=0 the equality constraints become%                      inequalities (direction dependend on pars.slack)                      %                      default: pars.factor=0.9999 %%       pars.inequ=0   default%       pars.inequ=1   equivalent to pars.slack=3; pars.factor=0;%                      allos all distances to shrink by setting distance%                      preserving constraints to inequalities%%       pars.verify    Automatically increases K if graph is not%       connected如果图不连通自动增加邻域点个数%                      (Note: If no K is specified pars.verify=1)%       pars.verify=1  (default) on%       pars.verify=0  off%%       pars.angles=1  preserves angles in local neighborhood%       (*DEFAULT*)在局部邻域内保角%       pars.angles=0  does not preserve angles in local neighborhood%       在局部邻域内不保角%%       pars.repell    Mx2 list of two points that should repell each other%                      pars.repell=[] (*default*)%%       pars.rweight   factor between 0 and 1, of how much the repelling %                      should weight compared to the normal objective%                      function   %                      pars.rweight=0.3 (*default*)%%       pars.kernel    (independent of value) adds the original kernel matrix to the output%                      (details.K)%% Output:%% Y         Resulting low dimensional vectors%           (Rows are dimensions i.e. Y(1:d,:) is d-dimensional embedding %% details   Includes all important details%           k           size of neighborhood%           D           all eigenvalues (ascending)%           info        SDP solver output%           pars        parameters%           dual        solution to dual problem%           inder       order of distance constraints (only interesting for%                       analysis of slack variables)%           slack       value of all slack variables% %% (TIP: From version 1.3 on, it is also possible to pass parameters% directly as strings% e.g. [Y,Det]=mvu(D,3,'maxiter',20,'solver',0,'inequ'); % is equivalent to%      pars.maxiter=20%      pars.solver=0%      pars.inequ=1;  % (if the value is not specified, it is set to 1)%      [Y,Det]=mvu(D,3,pars);%% NOTE: mvu requires a functionally copy of SeDuMi or CSDP in the path% (Download CSDP from http://www.nmt.edu/~borchers/csdp.html )% (and SeDuMi from http://fewcal.kub.nl/sturm/software/sedumi.html )%% Example:%  tt=(linspace(0,1,100).^0.65).*3*pi+pi;  %  X=[tt.*cos(tt); tt.*sin(tt)];             % generates spiral input data%  figure;%  h1=scatter(X(1,:),X(2,:),140,tt,'filled');   % plots input data%  title('INPUT DATA');%  set(h1,'MarkerEdgeColor',[0.5 0.5 0.5]);   % draw edges around dots%  drawnow;%  axis equal;%  [Y Det]=mvu(distance(X),3,'maxiter',20,'inequ');            % runs MVU (with inequalities)%  figure;%  h2=scatter(Y(1,:),Y(2,:),140,tt,'filled');   % plots output data%  set(h2,'MarkerEdgeColor',[0.5 0.5 0.5]);   % draw edges around dots%  title('OUTPUT DATA');%  axis equal; %%% You can execute this demo with % mvu('demo');%% (Version 1.3)% (copyright 2004 by Kilian Q. Weinberger:% http://www.seas.upenn.edu/~kilianw )if(nargin==0)  help mvu;  s=input('\n\nShall I run the MVU demo?','s');  if(length(s)>0 & isequal(upper(s(1)),'Y')) mvu('demo');end;  return;end;if(isequal(DD,'demo')) tt=(linspace(0,1,100).^0.65).*3*pi+pi;   X=[tt.*cos(tt); tt.*sin(tt)];             % generates spiral input data figure; h1=scatter(X(1,:),X(2,:),140,tt,'filled');   % plots input data title('INPUT DATA'); set(h1,'MarkerEdgeColor',[0.5 0.5 0.5]);   % draw edges around dots drawnow; axis equal; [Y Det]=mvu(distance(X),3,'maxiter',20,'inequ');            % runs MVU (with inequalities) figure; h2=scatter(Y(1,:),Y(2,:),140,tt,'filled');   % plots output data set(h2,'MarkerEdgeColor',[0.5 0.5 0.5]);   % draw edges around dots title('OUTPUT DATA'); axis equal;    return;end;% extract variablesif(length(varargin)>=1) if(~isstr(varargin{1}))    pars=varargin{1};    for j=1:length(varargin)-1        varargin{j}=varargin{j+1};    end; end; for i=1:nargin-2  if(isstr(varargin{i}))    if(i+1>nargin-2 | isstr(varargin{i+1})) val=1;else val=varargin{i+1};end;    eval(['pars.' varargin{i} '=' sprintf('%i',val) ';']);  end; end;end;[t1 t2]=size(DD);if(t1~=t2)     % little check if distance matrix is really square    error('First argument must be square(!!) distant matrix');end;% Set standard parametersif(~exist('pars') | ~isfield(pars,'factor')) pars.factor=0.9999;end; if(~isfield(pars,'slack')) pars.slack=0;end;if(~isfield(pars,'verify')) pars.verify=1;end;if(~isfield(pars,'solver')) pars.solver=0;end;if(~isfield(pars,'angles')) pars.angles=1;end;if(~isfield(pars,'repell')) pars.repell=[];end;if(~isfield(pars,'rweight')) pars.rweight=0.3;end;if(~isfield(pars,'init')) pars.init=0;end;if(~isfield(pars,'maxiter')) pars.maxiter=50; end;if(~isfield(pars,'maxiter')) pars.maxiter=50; end;if(~isfield(pars,'inequ')) pars.inequ=0; end;% Calculate neighborhoodsif(nargin<2)  K=neighborsUDD(DD,3);  else  if(pars.verify) K=neighborsUDD(DD,K);end;end;if(pars.inequ==1)    pars.slack=3;    pars.factor=0;end;parsN=length(DD);[sorted,index] = sort(DD);neighbors = index(2:(1+K),:);if(isfield(pars,'ne'))   neighbors=pars.ne; % not documented feature to pass as specific                     % neighborhood matrix as parameterend;% Constructing A and b  - the constraints for the SDPnck=nchoosek(K+1,2);depth=N*nck*4;% Initialize matrix AA=zeros(depth,3);A(1:end,1)=vec(repmat(1:N*nck,4,1));b=zeros(N*nck,1);% Initialize Matrix to check for redundant constraintsDONE=sparse([],[],[],N,N,0);VALID=ones(N*nck,1);% just for detailed output, a mapping of input-points > constraintsinder=zeros(depth,2);for i=1:N   ne = neighbors(:,i);   pairs=nchoosek([ne;i],2);      js=pairs(:,1);   ks=pairs(:,2);      %find positions in output gram matrix    v1=sub2ind([N N],ks,ks);   v2=sub2ind([N N],js,ks);   v3=sub2ind([N N],ks,js);   v4=sub2ind([N N],js,js);      pos=(i-1)*4*nck+1;   vv=vec([v1 v2 v3 v4]');   % Eliminate doubles   mask=DONE(v2)==0;   if(pars.angles==0)       mask=mask.*((js==i)+(ks==i));   end;      VALID((i-1)*nck+1:(i-1)*nck+nck)=mask;   DONE([v2;v3])=DONE([v2;v3])+1;   A(pos:pos+4*nck-1,2)=vv;   A(pos  :4:pos+nck*4-4,3)=A(pos  :4:pos+nck*4-4,3)+1;   A(pos+1:4:pos+nck*4-3,3)=A(pos+1:4:pos+nck*4-3,3)-1;   A(pos+2:4:pos+nck*4-2,3)=A(pos+2:4:pos+nck*4-2,3)-1;   A(pos+3:4:pos+nck*4-1,3)=A(pos+3:4:pos+nck*4-1,3)+1;                  b(((i-1)*nck+1):(i*nck))= DD(sub2ind([N N],js,ks))';   inder((i-1)*nck+1:(i*nck),:)=[js ks];end;A=sparse(A(:,1),A(:,2),A(:,3));i=find(VALID>0);A=A(i,:);b=b(i,:);inder=inder(i,:);fprintf('Redundancy:%d%%\n',round(100-full(length(i))/(length(VALID))*100));%% Add constraint to center pointsA=[ones(1,N^2);A];b=[0;b];i=[1;i];if(isfield(pars,'c'))   fprintf('Hidden Feature: Objective Function forced\n');  c=pars.c;%not documented feature to use weighted               % objective function else  c=0-vec(eye(N));end;fprintf('Size of A: %ix%i \n\n\n',size(A));flags.s=N;flags.l=0;%% Add repelling forcesif(length(pars.repell>0))    [rp,temp]=size(pars.repell);    c2=zeros(length(c),1);    js=pars.repell(:,1);    ks=pars.repell(:,2);       v1=sub2ind([N N],ks,ks);    v2=sub2ind([N N],js,ks);    v3=sub2ind([N N],ks,js);    v4=sub2ind([N N],js,js);    for counter=1:rp        c2(v1(counter))=1;        c2(v2(counter))=-1;%        c2(v3(counter))=-1;%        c2(v4(counter))=1;    end;        c=c.*(1-pars.rweight)-c2.*pars.rweight;end;if(pars.slack==3)  % Add Additive Slack Variables  flags.l=length(i)-1;    c=[ones(flags.l,1).*pars.factor;c.*(1-pars.factor)];  A=[[zeros(1,flags.l); speye(flags.l)] A];end;if(pars.slack==2)  % Add Additive Slack Variables (both additive and sub  flags.l=(length(i)-1)*2;    c=[ones(flags.l,1).*pars.factor;c.*(1-pars.factor)];  A=[[zeros(1,length(i)-1); speye(length(i)-1)] [zeros(1,length(i)-1); -speye(length(i)-1)] A];end;if(pars.slack==1)  % Add Additive Slack Variables  flags.l=length(i)-1;    c=[ones(flags.l,1).*pars.factor;c.*(1-pars.factor)];  A=[[zeros(1,flags.l); -speye(flags.l)] A];end;if(pars.slack & 1==0)  % Add Multiplicative Slack Variables  flags.l=length(i)-1;    c=[ones(flags.l,1).*pars.factor;c.*(1-pars.factor)];  A=[[zeros(1,flags.l); -sparse(spdiags(b(2:end),0,length(b)-1,length(b)-1))] A];end;Kneigh=K;switch(pars.solver)    case{0},      OPTIONS.maxiter=pars.maxiter;      [x d z  info]=csdp(A,b,c,flags,OPTIONS);      K=mat(x(flags.l+1:flags.l+flags.s^2));      slack=x(1:flags.l);    case{1},       OPTIONS.maxiter=pars.maxiter;       [k d info]=sedumi(A,b,c,flags,OPTIONS);      K=mat(k(end-flags.s^2+1:end));      slack=k(1:end-flags.s^2);      %keyboard;  case{2},       fprintf('converting into SQLP...');      [blk,A,c,b]=convert_sedumi(A',b,c,flags);      fprintf('DONE\n');       OPTIONS.vers=1;       OPTIONS.gam=0;       OPTIONS.predcorr=1;       OPTIONS.expon=[1 1];       OPTIONS.gaptol=1.0000e-08;       OPTIONS.inftol=1.0000e-08;       OPTIONS.steptol=1.0000e-06;       OPTIONS.maxit=pars.maxiter;       OPTIONS.printyes=1;       OPTIONS.scale_data=0;       OPTIONS.randnstate=0;       OPTIONS.spdensity=0.5000;       OPTIONS.rmdepconstr=0;       OPTIONS.cachesize=256;       OPTIONS.smallblkdim=15;          if(pars.init==1)           fprintf('Initializing ...');          % Initialize with input points        [X0,y0,Z0]=infeaspt(blk,A',c,b);         X0{length(X0)}=getgram(DD)+eye(N).*0.001;        fprintf('DONE\n');        [obj,Kt,d,z]=sqlp(blk,A,c,b,{},X0,y0,Z0);      else        OPTIONS.maxit=pars.maxiter;        [obj,Kt,d,z]=sqlp(blk,A,c,b,OPTIONS);    end;      K=Kt{length(Kt)};      info=0;      if(pars.slack)slack=Kt{1}(:);end;end;%keyboard;[V D]=eig(K);V=V*sqrt(D);D=diag(D);Y=(V(:,end:-1:1))';if(isfield(pars,'kernel'))  details.K=K;end;details.k=Kneigh;details.D=D;details.info=info;details.pars=pars;details.dual=d;details.inder=inder;if(pars.slack)details.slack=slack;end;return; %%% SIMPLE BUT USEFUL UTIL FUNCTIONSfunction neighbors=getneighborsUDD(DD,K);ne=getneighborsDD(DD,K);N=length(DD);for i=1:N    neighbors{i}=[];end;for i=1:N neighbors{i}=merge(sort(neighbors{i}),sort(ne(:,i))); for j=1:K    neighbors{ne(j,i)}=merge(neighbors{ne(j,i)}, i); end;end;function result=merge(x,y);result=unique([x(:);y(:)]);function v=vec(M);v=M(:);function k=neighborsUDD(DD,K);N=length(DD);if(nargin<2)    K=2;end;k=K;while(k<N & (1-connectedUDD(DD,k)))    k=k+1;    fprintf('Trying K=%i \n',k);end;function result=connectedUDD(DD,K);% result = connecteddfs (X,K)%% X input vector% K number of neighbors%% Returns: result = 1 if connected 0 if not connectedif(nargin<2)    fprintf('Number of Neighbors not specified!\nSetting K=4\n');    K=4;    end;N=length(DD);ne=getneighborsUDD(DD,K); maxSize=0;for i=1:N    if(length(ne{i})>maxSize) maxSize=length(ne{i});end;end;neighbors=ones(maxSize,N);for i=1:N    neighbors(1:length(ne{i}),i)=ne{i};    end;oldchecked=[];checked=[1];while((size(checked)<N) & (length(oldchecked)~=length(checked)))   next=neighbors(:,checked); next=transpose(sort(next(:))); next2=[next(2:end) 0]; k=find(next-next2~=0); next=next(k); oldchecked=checked;  checked=neighbors(:,next(:)); checked=transpose(sort(checked(:))); checked2=[checked(2:end) 0]; k=find(checked-checked2~=0); checked=checked(k);end;result=(length(checked)==N);function X = mat(x,n) if nargin < 2   n = floor(sqrt(length(x)));   if (n*n) ~= length(x)     error('Argument X has to be a square matrix')   end end X = reshape(x,n,n);   function neighbors=getneighborsDD(DD,K);N=length(DD);[sorted,index] = sort(DD);neighbors = index(2:(1+K),:);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -