VANILLA_NeNMF.m 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. % Non-negative Matrix Factorization via Nesterov's Optimal Gradient Method.
  2. % NeNMF: Matlab Code for Efficient NMF Solver
  3. % Reference
  4. % N. Guan, D. Tao, Z. Luo, and B. Yuan, "NeNMF: An Optimal Gradient Method
  5. % for Non-negative Matrix Factorization", IEEE Transactions on Signal
  6. % Processing, Vol. 60, No. 6, PP. 2882-2898, Jun. 2012. (DOI:
  7. % 10.1109/TSP.2012.2190406)
  8. % Modified by:F. Yahaya
  9. % Date: 06/09/2018
  10. % Contact: farouk.yahaya@univ-littoral.fr
  11. % <Inputs>
  12. % X : Input data matrix (m x n)
  13. % r : Target low-rank
  14. %
  15. % MAX_ITER : Maximum number of iterations. Default is 1,000.
  16. % MIN_ITER : Minimum number of iterations. Default is 10.
  17. % TOL : Stopping tolerance. Default is 1e-5. If you want to obtain a more accurate solution, decrease TOL and increase MAX_ITER at the same time.
  18. % <Outputs>
  19. % W : Obtained basis matrix (m x r).
  20. % H : Obtained coefficients matrix (r x n).
  21. % T : CPU TIME.
  22. % RRE: Relative reconstruction error in each iteration
  23. % Tmax : CPU time in seconds.
  24. % Note: another file 'stop_rule.m' should be included under the same
  25. % directory as this code.
  26. function [W,H,RRE,T]=VANILLA_NeNMF(X,W, H,Tmax)
  27. MinIter=10;
  28. tol=1e-5;
  29. T=zeros(1,301);
  30. RRE=zeros(1,301);
  31. ITER_MAX=500; % maximum inner iteration number (Default)
  32. ITER_MIN=10; % minimum inner iteration number (Default)
  33. HVt=H*X'; HHt=H*H';
  34. WtV=W'*X; WtW=W'*W;
  35. GradW=W*HHt-HVt';
  36. GradH=WtW*H-WtV;
  37. init_delta=stop_rule([W',H],[GradW',GradH]);
  38. tolH=max(tol,1e-3)*init_delta;
  39. tolW=tolH;% Stopping tolerance
  40. W=W';
  41. k=1;
  42. tic
  43. RRE(k) = nmf_norm_fro( X, W', H);
  44. T(k) = 0;
  45. % main loop
  46. while(toc<= Tmax+0.05)
  47. % Optimize H with W fixed
  48. [H,iterH]=NNLS(H,WtW,WtV,ITER_MIN,ITER_MAX,tolH);
  49. if iterH<=ITER_MIN
  50. tolH=tolH/10;
  51. end
  52. HHt=H*H'; HVt=H*X';
  53. % Optimize W with H fixed
  54. [W,iterW,GradW]=NNLS(W,HHt,HVt,ITER_MIN,ITER_MAX,tolW);
  55. if iterW<=ITER_MIN
  56. tolW=tolW/10;
  57. end
  58. WtW=W*W'; WtV=W*X;
  59. GradH=WtW*H-WtV;
  60. % HIS.niter=niter+iterH+iterW;
  61. delta=stop_rule([W,H],[GradW,GradH]);
  62. % Output running detials
  63. % % Stopping condition
  64. if (delta<=tol*init_delta && k>=MinIter)
  65. break;
  66. end
  67. if toc-(k-1)*0.05>=0.05
  68. k = k+1;
  69. RRE(k) = nmf_norm_fro( X, W', H);
  70. T(k) = toc;
  71. end
  72. end %end of loop
  73. W=W';
  74. return;
  75. function [H,iter,Grad]=NNLS(Z,WtW,WtV,iterMin,iterMax,tol)
  76. if ~issparse(WtW)
  77. L=norm(WtW); % Lipschitz constant
  78. else
  79. L=norm(full(WtW));
  80. end
  81. H=Z; % Initialization
  82. Grad=WtW*Z-WtV; % Gradient
  83. alpha1=1;
  84. for iter=1:iterMax
  85. H0=H;
  86. H=max(Z-Grad/L,0); % Calculate sequence 'Y'
  87. alpha2=0.5*(1+sqrt(1+4*alpha1^2));
  88. Z=H+((alpha1-1)/alpha2)*(H-H0);
  89. alpha1=alpha2;
  90. Grad=WtW*Z-WtV;
  91. % Stopping criteria
  92. if iter>=iterMin
  93. % Lin's stopping condition
  94. pgn=stop_rule(Z,Grad);
  95. if pgn<=tol
  96. break;
  97. end
  98. end
  99. end
  100. Grad=WtW*H-WtV;
  101. return;
  102. function f = nmf_norm_fro(X, W, H)
  103. % Author : F. Yahaya
  104. % Date: 13/04/2018
  105. % Contact: farouk.yahaya@univ-littoral.fr
  106. % Goal: compute a normalized error reconstruction of the mixing matrix V
  107. % "Normalized" means that we divide the squared Frobenius norm of the error
  108. % by the squared Frobenius norm of the matrix V
  109. % Note: To express the error in dB, you have to compute 10*log10(f)
  110. %
  111. f = norm(X - W * H,'fro')^2/norm(X,'fro')^2;
  112. return;