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

📄 comfac.m

📁 本人自己写的一个关于阵列信号处理的算法程序。
💻 M
📖 第 1 页 / 共 2 页
字号:
function [A,B,C,FIT,IT]=comfac(X,Fac,Options,DoComp,CompIt,Init);

%COMFAC Algorithm for fitting the complex-valued PARAFAC model
% 
% See e.g. Rasmus Bro, N. D. Sidiropoulos, and G. B. Giannakis. A Fast 
%          Least Squares Algorithm for Separating Trilinear Mixtures. 
%          Proc. ICA99 ?Int. Workshop on Independent Component Analysis 
%          and Blind Signal Separation. Jan. 11?5, Aussois, France:289-294, 1999.
%
%	        N. D. Sidiropoulos, G. B. Giannakis, and Rasmus Bro. Blind PARAFAC 
%          Receivers for DS-CDMA Systems. IEEE Transactions on Signal Processing March, 2000.
%
% The algorithm works by first compressing the data using a Tucker3 models. Subsequently the 
% PARAFAC model is fitted to the compressed array, either initialized with DTLD (~ESPRIT) or 
% with PARAFAC-ALS. The solution is de-compressed to the original space, and a few safe-guard
% PARAFAC-ALS steps are performed. Further optimization of this algorithm is possible, e.g.
% if the data are very large, if the profiles are very correlated or if the noise is huge. This
% has not been pursued here, in order to have a generally applicable algorithm
% 
% INPUT
% X       : I x J x K data three-way array 
% Fac     : Number of factors in PARAFAC model
%
% OPTIONAL INPUTS
% Options : A 1x2 vector
% (1)     : Mode to compress to dimension two in
%           DTLD if smallest mode-dimension is more
%           than two. Default is the smallest dimension
% (2)     : Number of extra components in Tucker3
%           compression model. Default if no given 
%           is one
% 
% ADVANCED OPTIONS
% DoComp  : 0      => No compression
%           1      => Compression
% CompIt  : CompIt => Max number of iterations in Compression
% Init    : 0      => GRAM/DTLD
%           1      => Ten x PARAFAC with 10 iterations started from RandOrth
%
% 
% I/O
% [A,B,C,FIT,IT]=comfac(X,Fac,Options,DoComp,CompIt,Init);
% 
% Or short : [A,B,C]=comfac(X,Fac);
crit = 1e-13; % Criterion used for fitting with Alternating LS algorithm

if length(size(X))~=3
   error(' The data must be held in a three-way array')
end
   
DimX = size(X);
X = reshape(X,DimX(1),prod(DimX(2:3)));

dbg=1;

DeafultExtraCompInTucker=2;
if exist('DoComp')~=1|isempty(DoComp)
   DoComp = 1;%%运行
end
if exist('CompIt')~=1|isempty(CompIt)
   CompIt = 3;%%运行
end
if exist('Init')~=1|isempty(Init)
   Init   = 1;
end
if length(find(DimX>Fac))<2 % GRAM/ESPRIT cannot be used
   ReplaceTLDwithRand = 1;
else
   ReplaceTLDwithRand = 0;
end   

if dbg
%   home
   %disp(' ')
   %disp([' Fitting ',num2str(Fac),'-comp. PARAFAC model using COMFAC ...'])
   %disp([' Array size: ',num2str(DimX(1)),' x ',num2str(DimX(2)),' x ',num2str(DimX(3))])
end

if nargin<3|isempty(Options)
  Options=[0 DeafultExtraCompInTucker];
end
if Options(1)==0
  [out,CompToTwo] = min(DimX);
else
  CompToTwo = Options(1);
end
if length(Options)<2
  Options(2)=DeafultExtraCompInTucker; % Number of additional components in compression as compared to model
end
W = Options(2)+Fac;%%% W=5+2=7
W = [W W W];
for i=1:3
  if W(i)>DimX(i)
    W(i)=DimX(i);
  end
end  %  W 4 7 7

% Display things
if DoComp & dbg
  %disp([' Array compressed to size ',num2str(W(1)),' x ',num2str(W(2)),' x ',num2str(W(3))])
end

% Compression

if DoComp  %DoComp=1
   [Ut,Vt,Zt,Gt,fit]=tucker3(X,DimX,W,CompIt);
else
   Gt = X;
   W = DimX;  
   Ut=speye(DimX(1));
   Vt=speye(DimX(2));
   Zt=speye(DimX(3));
end

% Initialize PARAFAC using DTLD
if Init == 0
   if ~ReplaceTLDwithRand
      disp(' Initializing using direct trilinear decomposition')
      [Adtld,Bdtld,Cdtld]=cdtld(Gt,W,Fac,CompToTwo);
   else
      disp(' Initializing using random values because tld cannot be used due to the sizes')
      [Adtld,Bdtld,Cdtld,fit]=cparafac(Gt,W,Fac,crit,0,0,0,10);
   end
   
elseif Init == 1%%% 运行
  % disp(' Initializing using best of 11 initial small runs')
  
   if ~ReplaceTLDwithRand %ReplaceTLDwithRand=0  运行
      [Adtld,Bdtld,Cdtld]=cdtld(Gt,W,Fac,CompToTwo);% DIRECT TRILINEAR DECOMPOSITION 
      %disp('张小飞');
  else
      [Adtld,Bdtld,Cdtld,fit]=cparafac(Gt,W,Fac,crit,0,0,0,10);
   end
  fitout=sum(sum(abs(  Gt-Adtld*ppp(Bdtld,Cdtld).').^2));
  for rep=1:10
     [adtld,bdtld,cdtldvar,fit]=cparafac(Gt,W,Fac,crit,0,0,0,10);
       %disp('张小飞张小飞');
     if fit<fitout %%%%% 没有运行
       Adtld=adtld;Bdtld=bdtld;Cdtld=cdtldvar;fitout=fit;%%%选择较好性能
   end
  end
end

% Fit PARAFAC model in compressed space
if DoComp
  %disp(' Fitting PARAFAC in compressed space')
  [Acomp,Bcomp,Ccomp,fit2,it2]=cparafac(Gt,W,Fac,crit,Adtld,Bdtld,Cdtld);
  % Decompress to original domain
  %disp(' Transforming interim solution to original space')
  Ainit = Ut*Acomp;
  Binit = Vt*Bcomp;
  Cinit = Zt*Ccomp;
else
  Ainit = Adtld;
  Binit = Bdtld;
  Cinit = Cdtld;
  it2=0;
  fit2=NaN;
end

% Fit PARAFAC model in raw space
%disp(' Fitting PARAFAC in original space')
[A,B,C,FIT,IT]=cparafac(X,DimX,Fac,crit,Ainit,Binit,Cinit);
%disp(' Algorithm converged')


function [A,B,C,fit0,it]=cparafac(X,DimX,Fac,crit,A,B,C,maxit,DoLineSearch);

% Complex PARAFAC-ALS
% Fits the PARAFAC model Xk = A*Dk*B.' + E
% where Dk is a diagonal matrix holding the k'th
% row of C.
%
% Uses on-the-fly projection-compression to speed up 
% the computations. This requires that the first mode 
% is the largest to be effective
% 
% INPUT
% X       : Data
% DimX    : Dimension of X
% Fac     : Number of factors
% OPTIONAL INPUT
% crit    : Convergence criterion (default 1e-6)
% A,B,C   : Initial parameter values
%
% I/O
% [A,B,C,fit,it]=parafac(X,DimX,Fac,crit,A,B,C);
%
% Copyright 1998
% Rasmus Bro
% KVL, Denmark, rb@kvl.dk


% Initialization
if nargin<8
  maxit   = 250;      % Maximal number of iterations
end
showfit = pi;         % Show fit every 'showfit'th iteration (set to pi to avoid)

if nargin<4
  crit=1e-10;
end

if crit==0
  crit=1e-6;
end

I = DimX(1);
J = DimX(2);
K = DimX(3);

InitWithRandom=0;
if nargin<7
   InitWithRandom=1;
end
if nargin>6 & size(A,1)~=I
  InitWithRandom=1;
end

if InitWithRandom

  if I<Fac
    A = rand(I,Fac);
  else
    A = orth(rand(I,Fac));
  end
  if J<Fac
    B = rand(J,Fac);
  else
    B = orth(rand(J,Fac));
  end
  if K<Fac
    C = rand(K,Fac);
  else
    C = orth(rand(K,Fac));
  end
end

SumSqX = sum(sum(abs(X).^2));
fit    = sum(sum(abs(X-A*ppp(B,C).')));%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%fit
fit0   = fit;
fitold = 2*fit;
it     = 0;
Delta  = 5;

while abs((fit-fitold)/fitold)>crit & it<maxit & fit>10*eps
   it=it+1;
   fitold=fit;

   % Do line-search
   if rem(it+2,2)==-1
      [A,B,C,Delta]=linesrch(X,DimX,A,B,C,Ao,Bo,Co,Delta);
   end

   Ao=A;Bo=B;Co=C;
   % Update A
   Xbc=0;

   for k=1:K
     Xbc = Xbc + X(:,(k-1)*J+1:k*J)*conj(B*diag(C(k,:)));
   end
   A = Xbc*inv((B'*B).*(C'*C)).';

   % Project X down on orth(A) - saves time if first mode is large
   [Qa,Ra]=qr(A,0);
   x=Qa'*X;

   % Update B
   Xac=0;
   for k=1:K
     Xac = Xac + x(:,(k-1)*J+1:k*J).'*conj(Ra*diag(C(k,:)));
   end
   B = Xac*inv((Ra'*Ra).*(C'*C)).';
   
   % Update C
   ab=inv((Ra'*Ra).*(B'*B));
   for k=1:K
     C(k,:) = (ab*diag(Ra'* x(:,(k-1)*J+1:k*J)*conj(B))).';
   end

   % Calculating fit. Using orthogonalization instead
   %fit=0;for k=1:K,residual=X(:,(k-1)*J+1:k*J)-A*diag(C(k,:))*B.';fit=fit+sum(sum((abs(residual).^2)));end
   [Qb,Rb]=qr(B,0);
   [Z,Rc]=qr(C,0);
   fit=SumSqX-sum(sum(abs(Ra*ppp(Rb,Rc).').^2));%%%%%%%
   fit0(it)=fit;
   if rem(it,showfit)==0
     fprintf(' %12.10f       %g        %3.4f \n',fit,it,100*(1-fit/fit0));
   end
end

%fprintf(' %12.10f       %g        %3.4f \n',fit,it,100*(1-fit/fit0));


function [A,B,C]=cgram(X1,X2,F);

% cGRAM - Complex Generalized Rank Annihilation Method
% Fits the PARAFAC model directly for the case of a 
% three-way array with only two frontal slabs.
% For noise-free trilinear data the algorithm is exact.
% 
% INPUTS:
% X1    : I x J matrix of data from observation one
% X2    : I x J matrix of data from observation two
% Fac   : Number of factors
% 
% OUTPUTS:
% A     : Components in the row mode (I x F)
% B     : Components in the column mode (J x F)
% C     : Weights for each slab; C(1,:) are the component 
%         weights for first slab such that the approximation
%         of X1 is equivalent to X1 = A*diag(C(1,:))*B.'
%
% Copyright 1998
% Rasmus Bro, KVL, DK
% rb@kvl.dk


  DontShowOutput = 1;

  [U,s,V]=svd(X1+X2);
  U=U(:,1:F);
  V=V(:,1:F);

%  S2=S1*b
%  b*k = k*l =>
%  S1*b*k = S1*k*l =>
%  S2*k = S1*k*l =>
%  inv(S1*k)*S2*k = l = diagonal

  S1=U'*X1*V;
  S2=U'*X2*V;
  [v,d]=eig(S1\S2);

  ddd=d;
  d=diag(d);out=abs(d)>eps;v=v(:,out);d=d(out); %only significant terms
  [dd,out]=sort(abs(d));out=flipud(out);
  d=d(out);d=diag(d);v(:,out);v=v/norm(v);% sort them

  A = U*S1*v;
  B=V/v';
  B=(B.')';
  C=(pinv(ppp(A,B))*[X1(:) X2(:)]).';

  if ~DontShowOutput
    fit = sum(sum(abs([X1 X2] - [A*diag(C(1,:))*B.' A*diag(C(2,:))*B.']).^2));
    disp([' GRAM fitted data with a sum-squared error of ',num2str(fit)])
 end
 
 
 
 function [A,B,C,fit]=cdtld(X,DimX,F,SmallMode);

% DIRECT TRILINEAR DECOMPOSITION
% calculate the parameters of the three-
% way PARAFAC model directly. The model
% is not the least-squares but will be close
% to for precise data with little model-error
%
% This implementation works with an optimal
% compression using least-squares Tucker3 fitting
% to generate two pseudo-observation matrices that
% maximally span the variation of all samples. per
% default the mode of smallest dimension is compressed
% to two samples, while the remaining modes are 
% compressed to dimension F.
% 
% For large arrays it is fastest to have the smallest
% dimension in the first mode
%
% INPUT
% [A,B,C]=dtld(X,DimX,F);
% X is the I x J x K array unfolded to an I x JK matrix
% DimX = [I J K]
% F is the number of factors to fit
% An optional parameter may be given to enforce which
% mode is to be compressed to dimension two
%
% Copyright 1998
% Rasmus Bro, KVL
% rb@kvl.dk


DontShowOutput = 1;

%rearrange X so smallest dimension is in first mode
if nargin<4
  [a,SmallMode] = min(DimX);
  X = nshape(X,DimX,SmallMode);
  DimX = DimX([SmallMode 1:SmallMode-1 SmallMode+1:3]);
  Fac   = [2 F F];
else
  X = nshape(X,DimX,SmallMode);
  DimX = DimX([SmallMode 1:SmallMode-1 SmallMode+1:3]);
  Fac   = [2 F F];
end

if DimX(1) < 2
  error(' The smallest dimension must be > 1')
end
if any(DimX(2:3)-Fac(2:3)<0)
  error(' This algorithm requires that two modes are of dimension not less the number of components')
end

% Compress data into a 2 x F x F array. Only 10 iterations are used since exact SL fit is insignificant; only obtaining good truncated bases is important
[At,Bt,Ct,G]=tucker3(X,DimX,Fac,10);

% Fit GRAM to compressed data
[Bg,Cg,Ag]=cgram(reshape(G(1,:),F,F),reshape(G(2,:),F,F),F);

% De-compress data and find A
BB = Bt*Bg;
CC = Ct*Cg;
AA = X*pinv(ppp(BB,CC)).';

if SmallMode == 1
  A=AA;
  B=BB;
  C=CC;
elseif SmallMode == 2 

⌨️ 快捷键说明

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