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

📄 icaml.m

📁 ICA is used to classify text in extension to the latent semantic indexing framework. ICA show to ali
💻 M
字号:
function [S,A,ll]=icaML(X)
% icaML     : ICA by ML (Infomax) with square mixing matrix and no noise.
%
% function [S,A,ll]=icaML(X)            Independent component analysis (ICA) using
%                                       maximum likelihood, square mixing matrix and 
%                                       no noise [1] (Infomax). Source prior is assumed 
%                                       to be p(s)=1/pi*exp(-ln(cosh(s))). For optimization
%                                       the BFGS algorithm is used [2]. See code for 
%                                       references.
%                                       
%                                       X  : Mixed signals
%                                       
%                                       A  : Esitmated mixing matrix
%                                       S  : Estimated source signals with variance
%                                            scaled to one.
%                                       ll : Log likelihood for estimated sources
%                                       
% - by Thomas Kolenda 2002 - IMM, Technical University of Denmark
% - version 1.2

% Bibtex references:
% [1]  
%   @article{Bell95,
%       author =       "A. Bell and T.J. Sejnowski",
%       title =        "An Information-Maximization Approach to Blind Separation and Blind Deconvolution",
%       journal =      "Neural Computation",
%       year =         "1995",
%       volume =       "7",
%       pages =        "1129-1159",
%   }
%
% [2]
%   @techreport{Frandsen99:unopt,
%       author =        "H.B. Nielsen",
%       title =         "UCMINF - an Algorithm for Unconstrained, Nonlinear Optimization ",
%       institution =   "IMM, Technical University of Denmark",
%       number =        "IMM-TEC-0019",
%       year =          "2001",
%   }



% algorithm parameter settings
MaxNrIte=1000;

% initialize variables
[M,N]=size(X);
W=eye(M);

ucminf_opt= [1  1e-4  1e-8  MaxNrIte];

% optimize
par.X=X; par.M=M; par.N=N;
W = ucminf( 'ica_MLf' , par , W(:) , ucminf_opt );
W = reshape(W,M,M); 

% estimates
A=inv(W);
S=W*X;

% sort components according to energy
Avar=diag(A'*A)/M;
Svar=diag(S*S')/N;
vS=var(S');
sig=Avar.*Svar;
[a,indx]=sort(sig);
S=S(indx(M:-1:1),:);
A=A(:,indx(M:-1:1));

% variance one for sources
A=A.*repmat(std(S'),size(A,1),1);
S=S./repmat(std(S')',1,size(S,2));

% log likelihood
if nargout>2
  ll = - ica_MLf(inv(A),par);
end



function [f,dW]=ica_MLf(W,par)
% returns the negative log likelihood and its gradient w.r.t. W

X=par.X; M=par.M; N=par.N;
W=reshape(W,M,M);

S=W*X;

% negative log likelihood function
f=-( N*log(abs(det(W))) - sum(sum(log( cosh(S) ))) - N*M*log(pi) );

  
if nargout>1
  % gradient w.r.t. W
  dW=-(N*inv(W') - tanh(S)*X');
  dW=dW(:);
end




function  [X, info, perf, D] = ucminf(fun,par, x0, opts, D0)
%UCMINF  BFGS method for unconstrained nonlinear optimization:
% Find  xm = argmin{f(x)} , where  x  is an n-vector and the scalar
% function  F  with gradient  g  (with elements  g(i) = DF/Dx_i )
% must be given by a MATLAB function with with declaration
%           function  [F, g] = fun(x, par)
% par  holds parameters of the function.  It may be dummy.  
% 
% Call:  [X, info {, perf {, D}}] = ucminf(fun,par, x0, opts {,D0})
%
% Input parameters
% fun  :  String with the name of the function.
% par  :  Parameters of the function.  May be empty.
% x0   :  Starting guess for  x .
% opts :  Vector with 4 elements:
%         opts(1) :  Expected length of initial step
%         opts(2:4)  used in stopping criteria:
%             ||g||_inf <= opts(2)                     or 
%             ||dx||_2 <= opts(3)*(opts(3) + ||x||_2)  or
%             no. of function evaluations exceeds  opts(4) . 
%         Any illegal element in  opts  is replaced by its
%         default value,  [1  1e-4*||g(x0)||_inf  1e-8  100]
% D0   :  (optional)  If present, then approximate inverse Hessian
%         at  x0 .  Otherwise, D0 := I 
% Output parameters
% X    :  If  perf  is present, then array, holding the iterates
%         columnwise.  Otherwise, computed solution vector.
% info :  Performance information, vector with 6 elements:
%         info(1:3) = final values of [f(x)  ||g||_inf  ||dx||_2] 
%         info(4:5) = no. of iteration steps and evaluations of (F,g)
%         info(6) = 1 :  Stopped by small gradient
%                   2 :  Stopped by small x-step
%                   3 :  Stopped by  opts(4) .
%                   4 :  Stopped by zero step.
% perf :  (optional). If present, then array, holding 
%          perf(1:2,:) = values of  f(x) and ||g||_inf
%          perf(3:5,:) = Line search info:  values of  
%                        alpha, phi'(alpha), no. fct. evals. 
%          perf(6,:)   = trust region radius.
% D    :  (optional). If present, then array holding the 
%         approximate inverse Hessian at  X(:,end) .

%  Hans Bruun Nielsen,  IMM, DTU.  00.12.18 / 02.01.22

  % Check call 
  [x n F g] = check(fun,par,x0,opts);
  if  nargin > 4,  D = checkD(n,D0);  fst = 0;
  else,            D = eye(n);  fst = 1;    end
  %  Finish initialization
  k = 1;   kmax = opts(4);   neval = 1;   ng = norm(g,inf);
  Delta = opts(1);
  Trace = nargout > 2;
  if  Trace
        X = x(:)*ones(1,kmax+1);
        perf = [F; ng; zeros(3,1); Delta]*ones(1,kmax+1);
      end
  found = ng <= opts(2);      
  h = zeros(size(x));  nh = 0;
  ngs = ng * ones(1,3);
   
  while  ~found
    %  Previous values
    xp = x;   gp = g;   Fp = F;   nx = norm(x);
    ngs = [ngs(2:3) ng];
    h = D*(-g(:));   nh = norm(h);   red = 0; 
    if  nh <= opts(3)*(opts(3) + nx),  found = 2;  
    else
      if  fst | nh > Delta  % Scale to ||h|| = Delta
        h = (Delta / nh) * h;   nh = Delta;   
        fst = 0;  red = 1;
      end
      k = k+1;
      %  Line search
      [al  F  g  dval  slrat] = softline(fun,par,x,F,g, h);
      if  al < 1  % Reduce Delta
        Delta = .35 * Delta;
      elseif   red & (slrat > .7)  % Increase Delta
        Delta = 3*Delta;      
      end 
      %  Update  x, neval and ||g||
      x = x + al*h;   neval = neval + dval;  ng = norm(g,inf);
      if  Trace
             X(:,k) = x(:); 
             perf(:,k) = [F; ng; al; dot(h,g); dval; Delta]; end
      h = x - xp;   nh = norm(h);
      if  nh == 0,
        found = 4; 
      else
        y = g - gp;   yh = dot(y,h);
        if  yh > sqrt(eps) * nh * norm(y)
          %  Update  D
          v = D*y(:);   yv = dot(y,v);
          a = (1 + yv/yh)/yh;   w = (a/2)*h(:) - v/yh;
          D = D + w*h' + h*w';
        end  % update D
        %  Check stopping criteria
        thrx = opts(3)*(opts(3) + norm(x));
        if      ng <= opts(2),              found = 1;
        elseif  nh <= thrx,                 found = 2;
        elseif  neval >= kmax,              found = 3; 
%        elseif  neval > 20 & ng > 1.1*max(ngs), found = 5;
        else,   Delta = max(Delta, 2*thrx);  end
      end  
    end  % Nonzero h
  end  % iteration

  %  Set return values
  if  Trace
    X = X(:,1:k);   perf = perf(:,1:k);
  else,  X = x;  end
  info = [F  ng  nh  k-1  neval  found];

% ==========  auxiliary functions  =================================

function  [x,n, F,g, opts] = check(fun,par,x0,opts0)
% Check function call
  x = x0(:);   sx = size(x);   n = max(sx);   
  if  (min(sx) > 1)
      error('x0  should be a vector'), end
  [F g] = feval(fun,x,par);
  sf = size(F);   sg = size(g);
  if  any(sf-1) | ~isreal(F)
      error('F  should be a real valued scalar'), end
  if  (min(sg) ~= 1) | (max(sg) ~= n)
      error('g  should be a vector of the same length as  x'), end
  so = size(opts0);
  if  (min(so) ~= 1) | (max(so) < 4) | any(~isreal(opts0(1:4)))
      error('opts  should be a real valued vector of length 4'), end
  opts = opts0(1:4);   opts = opts(:).';
  i = find(opts <= 0);
  if  length(i)    % Set default values
    d = [1  1e-4*norm(g, inf)  1e-8  100];
    opts(i) = d(i);
  end   
% ----------  end of  check  ---------------------------------------

function  D = checkD(n,D0)
% Check given inverse Hessian
  D = D0;   sD = size(D);
  if  any(sD - n)
      error(sprintf('D  should be a square matrix of size %g',n)), end
  % Check symmetry
  dD = D - D';   ndD = norm(dD(:),inf);
  if  ndD > 10*eps*norm(D(:),inf)
      error('The given D0 is not symmetric'), end
  if  ndD,  D = (D + D')/2; end  % Symmetrize      
  [R p] = chol(D);
  if  p
      error('The given D0 is not positive definite'), end
    
function  [alpha,fn,gn,neval,slrat] = ...
              softline(fun,fpar, x,f,g, h)
% Soft line search:  Find  alpha = argmin_a{f(x+a*h)}
  % Default return values 
  alpha = 0;   fn = f;   gn = g;   neval = 0;  slrat = 1;
  n = length(x);  
  
  % Initial values
  dfi0 = dot(h,gn);  if  dfi0 >= 0,  return, end
  fi0 = f;    slope0 = .05*dfi0;   slopethr = .995*dfi0;
  dfia = dfi0;   stop = 0;   ok = 0;   neval = 0;   b = 1;
  
  while   ~stop
    [fib g] = feval(fun,x+b*h,fpar);  neval = neval + 1;
    dfib = dot(g,h); 
    if  b == 1, slrat = dfib/dfi0; end
    if  fib <= fi0 + slope0*b    % New lower bound
      if  dfib > abs(slopethr),  stop = 1;
      else
        alpha = b;   fn = fib;   gn = g;   dfia = dfib;  
        ok = 1;   slrat = dfib/dfi0;
        if  (neval < 5) & (b < 2) & (dfib < slopethr)
          % Augment right hand end
          b = 2*b;
        else,  stop = 1; end
      end
    else,  stop = 1; end   
  end
  
  stop = ok;  xfd = [alpha fn dfia; b fib dfib; b fib dfib];
  while   ~stop
    c = interpolate(xfd,n);
    [fic g] = feval(fun, x+c*h, fpar);   neval = neval+1;
    xfd(3,:) = [c  fic  dot(g,h)];
    if fic < fi0 + slope0*c    % New lower bound
      xfd(1,:) = xfd(3,:);   ok = 1;
      alpha = c;   fn = fic;   gn = g;  slrat = xfd(3,3)/dfi0;
    else,  xfd(2,:) = xfd(3,:);  ok = 0; end
    % Check stopping criteria
    ok = ok & abs(xfd(3,3)) <= abs(slopethr);
    stop = ok | neval >= 5 | diff(xfd(1:2,1)) <= 0;
  end  % while   
%------------  end of  softline  ------------------------------
  
function  alpha = interpolate(xfd,n);
% Minimizer of parabola given by
% xfd(1:2,1:3) = [a fi(a) fi'(a); b fi(b) dummy]

  a = xfd(1,1);   b = xfd(2,1);   d = b - a;   dfia = xfd(1,3);
  C = diff(xfd(1:2,2)) - d*dfia;
  if C >= 5*n*eps*b    % Minimizer exists
    A = a - .5*dfia*(d^2/C);
    d = 0.1*d;   alpha = min(max(a+d, A), b-d);
  else
    alpha = (a+b)/2;
  end
%------------  end of  interpolate  --------------------------


⌨️ 快捷键说明

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