IST改进算法之Two-Step Iterative Shrinkage/Thresholding(TwIST)

题目:IST改进算法之Two-Step Iterative Shrinkage/Thresholding(TwIST)

        本篇介绍IST的一种改进算法TwIST,该改进算法由以下文献提出:

Bioucas-DiasJ M, Figueiredo M AT.A new TwIST: two-step iterative shrinkage/thresholding algorithms for imagerestoration[J]. IEEE Transactions on Image processing, 2007, 16(12): 2992-3004.

        据文献介绍,相比于IST,TwIST旨在使算法收敛的更快。

        TwIST解决的问题是目标函数为式(1)的优化问题:

注意:最后一行无穷右边的中括号并没有错,这表示开区间,而0左边的中括号表示闭区间。

1、TwIST算法内容

        相比于IST,TwIST主要是迭代公式的变化:

其中Ψλ定义为:

Ψλ的表达式与式(1)中的正则项Φ(x)有关,当Φ(x)=||x||1时:

即软阈值函数。更一般的,Φ(x)为式(10)时:

例如文中提到的当p=2时:

因此

2、TwIST算法的提出思路

        TwIST实际上是IST与TwSIM的结合:

注意式(13)是推广的IST迭代公式,原始版的IST迭代公式是令式(13)中的β=1。而TwSIM实际上是式(14)一种实现形式(当矩阵At较大时)

其中式(14)如下(即IterativeRe-Weighted Shrinkage (IRS)):

        如何将IST和TwSIM结合得到TwIST的呢?这个过程有点悬:

注意这个结合过程,文中说:若令式(16)中α=1并将C-1替换为ψλ则可以得到式(13)。由此相似性可以得到一个two-step版本的IST:(这个idea来的好突然)

        既然TwIST结合了IST和TwSIM,因此TwIST算法希望能达到如下特性:

        为什么叫two-step  IST呢?

比较一下IST迭代公式式(13)和TwIST迭代公式式(18)可以发现,IST迭代公式等号右边只有xt,而TwIST迭代公式等号右边有xtxt-1

3、TwIST算法的参数设置

        TwIST算法主页:http://www.lx.it.pt/~bioucas/TwIST/TwIST.htm

        在TwIST主页可以下载到最新版本TwIST的Matlab实现代码。

        首先,这里重点介绍一下TwIST迭代公式(18)中α和β两个关键参数如何设置?文中式(22)和式(23)给出了α和β的计算方法,相关公式如下图:

        在TwIST官方代码中,与参数α和β有关的代码如图所示(Notepad++打开截图):

        

        

        

        

        参数α和β可由外部输入(参见第265~268行),若未输入,则默认按第319~326行计算(其中在第235~236行已将α和β置零,若第265~268行未赋值,则执行第319~326行),参数α计算公式与文中的式(22)看来不一样,但其实是相同的,推导如下:

        先将式(20)代入式(22)化简一下:

程序中的lam1即为ξ1(可选输入参数,参见程序第263~264行,默认为10-4,参见程序第242行),lamN即为ξm(恒为1,参见程序第242行),而κ1m,因此程序中的rho0

将rho0代入

因此文中式(22)和程序中的设置是一样的。文中又提到TwIST对参数α和β并不是很敏感,也就是“very robust”:

4、TwIST算法的MATLAB代码

        官方版本的TwIST算法Matlab代码超过700行,其实最核心的就是在一定条件下循环迭代式(18)而已,这里给出一个本人写的简化版本的TwIST代码,方便理解:

  1. function [ x ] = TwIST_Basic( y,Phi,lambda,beta,alpha,epsilon,loopmax,lam1,lamN )  
  2. %   Detailed explanation goes here    
  3. %Version: 1.0 written by jbb0523 @2016-08-12  
  4.     if nargin < 9  
  5.         lamN = 1;  
  6.     end  
  7.     if nargin < 8  
  8.         lam1 = 1e-4;  
  9.     end  
  10.     if nargin < 7      
  11.         loopmax = 10000;      
  12.     end      
  13.     if nargin < 6        
  14.         epsilon = 1e-2;        
  15.     end  
  16.     if nargin < 5  
  17.         rho0 = (1-lam1/lamN)/(1+lam1/lamN);  
  18.         alpha = 2/(1+sqrt(1-rho0^2));  
  19.     end  
  20.     if nargin < 4  
  21.         beta  = alpha*2/(lam1+lamN);  
  22.     end  
  23.     if nargin < 3        
  24.         lambda = 0.1*max(abs(Phi’*y));       
  25.     end    
  26.     [y_rows,y_columns] = size(y);        
  27.     if y_rows<y_columns        
  28.         y = y’;%y should be a column vector        
  29.     end   
  30.     soft = @(x,T) sign(x).*max(abs(x) - T,0);  
  31.     n = size(Phi,2);      
  32.     loop = 0;   
  33.     fprintf(‘\n’);  
  34.     x_pre2 = zeros(n,1);%Initialize x0=0   
  35.     %Initialize x1=soft(x0+Phi’*(y-Phi*x0),lambda)  
  36.     x_pre1 = soft(x_pre2+Phi’*(y-Phi*x_pre2),lambda);  
  37.     f_pre1 = 0.5*(y-Phi*x_pre1)’*(y-Phi*x_pre1)+lambda*sum(abs(x_pre1));  
  38.     while 1  
  39.         %(1)compute x_(t+1)  
  40.         x_temp = soft(x_pre1+Phi’*(y-Phi*x_pre1),lambda);  
  41.         %following 3 lines are important for reconstruction successfully  
  42.         mask = (x_temp ~= 0);  
  43.         x_pre2 = x_pre2.* mask;  
  44.         x_pre1 = x_pre1.* mask;  
  45.         x=(1-alpha)*x_pre2+(alpha-beta)*x_pre1+beta*x_temp;  
  46.         %(2)update x_(t-1)  
  47.         x_pre2 = x_pre1;  
  48.         f_pre2 = f_pre1;  
  49.         %(3)update x_t  
  50.         x_pre1 = x;  
  51.         f_pre1 = 0.5*(y-Phi*x_pre1)’*(y-Phi*x_pre1)+lambda*sum(abs(x_pre1));  
  52.         loop = loop + 1;   
  53.         %fprintf(‘Iter %d:f_pre1 = %f\n’,loop,f_pre1);  
  54.         if abs(f_pre1-f_pre2)/f_pre2<epsilon  
  55.             fprintf(‘abs(f_pre1-f_pre2)/f_pre2<%f\n’,epsilon);  
  56.             fprintf(‘TwIST loop is %d\n’,loop);  
  57.             break;  
  58.         end  
  59.         if loop >= loopmax  
  60.             fprintf(‘loop > %d\n’,loopmax);  
  61.             break;  
  62.         end  
  63.         if norm(x_pre1-x_pre2)<epsilon  
  64.             fprintf(‘norm(x-x_pre)<%f\n’,epsilon);  
  65.             fprintf(‘TwIST loop is %d\n’,loop);  
  66.             break;  
  67.         end  
  68.     end  
  69.   end  
function [ x ] = TwIST_Basic( y,Phi,lambda,beta,alpha,epsilon,loopmax,lam1,lamN )
%   Detailed explanation goes here  
%Version: 1.0 written by jbb0523 @2016-08-12
    if nargin < 9
        lamN = 1;
    end
    if nargin < 8
        lam1 = 1e-4;
    end
    if nargin < 7    
        loopmax = 10000;    
    end    
    if nargin < 6      
        epsilon = 1e-2;      
    end
    if nargin < 5
        rho0 = (1-lam1/lamN)/(1+lam1/lamN);
        alpha = 2/(1+sqrt(1-rho0^2));
    end
    if nargin < 4
        beta  = alpha*2/(lam1+lamN);
    end
    if nargin < 3      
        lambda = 0.1*max(abs(Phi'*y));     
    end  
    [y_rows,y_columns] = size(y);      
    if y_rows<y_columns      
        y = y';%y should be a column vector      
    end 
    soft = @(x,T) sign(x).*max(abs(x) - T,0);
    n = size(Phi,2);    
    loop = 0; 
    fprintf('\n');
    x_pre2 = zeros(n,1);%Initialize x0=0 
    %Initialize x1=soft(x0+Phi'*(y-Phi*x0),lambda)
    x_pre1 = soft(x_pre2+Phi'*(y-Phi*x_pre2),lambda);
    f_pre1 = 0.5*(y-Phi*x_pre1)'*(y-Phi*x_pre1)+lambda*sum(abs(x_pre1));
    while 1
        %(1)compute x_(t+1)
        x_temp = soft(x_pre1+Phi'*(y-Phi*x_pre1),lambda);
        %following 3 lines are important for reconstruction successfully
        mask = (x_temp ~= 0);
        x_pre2 = x_pre2.* mask;
        x_pre1 = x_pre1.* mask;
        x=(1-alpha)*x_pre2+(alpha-beta)*x_pre1+beta*x_temp;
        %(2)update x_(t-1)
        x_pre2 = x_pre1;
        f_pre2 = f_pre1;
        %(3)update x_t
        x_pre1 = x;
        f_pre1 = 0.5*(y-Phi*x_pre1)'*(y-Phi*x_pre1)+lambda*sum(abs(x_pre1));
        loop = loop + 1; 
        %fprintf('Iter %d:f_pre1 = %f\n',loop,f_pre1);
        if abs(f_pre1-f_pre2)/f_pre2<epsilon
            fprintf('abs(f_pre1-f_pre2)/f_pre2<%f\n',epsilon);
            fprintf('TwIST loop is %d\n',loop);
            break;
        end
        if loop >= loopmax
            fprintf('loop > %d\n',loopmax);
            break;
        end
        if norm(x_pre1-x_pre2)<epsilon
            fprintf('norm(x-x_pre)<%f\n',epsilon);
            fprintf('TwIST loop is %d\n',loop);
            break;
        end
    end
  end


值得注意的是,本基本版TwIST_Basic仅解决当文中式(1)正则项Φ(x)=||x||1时的情况,而官方版本的TwIST通过参数配置可以解决当Φ(x)为其它表达式时的情况。

        这里最核心的是第40~45行,即:

  1. x_temp = soft(x_pre1+Phi’*(y-Phi*x_pre1),lambda);  
  2. %following 3 lines are important for reconstruction successfully  
  3. mask = (x_temp ~= 0);  
  4. x_pre2 = x_pre2.* mask;  
  5. x_pre1 = x_pre1.* mask;  
  6. x=(1-alpha)*x_pre2+(alpha-beta)*x_pre1+beta*x_temp;  
        x_temp = soft(x_pre1+Phi'*(y-Phi*x_pre1),lambda);
        %following 3 lines are important for reconstruction successfully
        mask = (x_temp ~= 0);
        x_pre2 = x_pre2.* mask;
        x_pre1 = x_pre1.* mask;
        x=(1-alpha)*x_pre2+(alpha-beta)*x_pre1+beta*x_temp;

即执行TwIST迭代公式(18)的过程。值得注意的是起初本人并没有加入第42~44行,当然,也基本无法成功重构,但官方版本的TwIST却可以重构成功,于是本人仔细对比了与TwIST的差别,最终发现关键点在官方版本的以下几行:

        

于是在我的基本版本里新加入了即第42~44行,重构效果明显改善。

        为了保证本篇的完整性,这里也同时也给出官方版本的TwIST算法Matlab代码:

        (TwIST算法主页:http://www.lx.it.pt/~bioucas/TwIST/TwIST.htm

  1. function [x,x_debias,objective,times,debias_start,mses,max_svd] = …  
  2.          TwIST(y,A,tau,varargin)  
  3. %  
  4. % Usage:  
  5. % [x,x_debias,objective,times,debias_start,mses] = TwIST(y,A,tau,varargin)  
  6. %  
  7. % This function solves the regularization problem   
  8. %  
  9. %     arg min_x = 0.5*|| y - A x ||_2^2 + tau phi( x ),   
  10. %  
  11. % where A is a generic matrix and phi(.) is a regularizarion   
  12. % function  such that the solution of the denoising problem   
  13. %  
  14. %     Psi_tau(y) = arg min_x = 0.5*|| y - x ||_2^2 + tau \phi( x ),   
  15. %  
  16. % is known.   
  17. %   
  18. % For further details about the TwIST algorithm, see the paper:  
  19. %  
  20. % J. Bioucas-Dias and M. Figueiredo, “A New TwIST: Two-Step  
  21. % Iterative Shrinkage/Thresholding Algorithms for Image   
  22. % Restoration”,  IEEE Transactions on Image processing, 2007.  
  23. %   
  24. % and  
  25. %   
  26. % J. Bioucas-Dias and M. Figueiredo, “A Monotonic Two-Step   
  27. % Algorithm for Compressive Sensing and Other Ill-Posed   
  28. % Inverse Problems”, submitted, 2007.  
  29. %  
  30. % Authors: Jose Bioucas-Dias and Mario Figueiredo, October, 2007.  
  31. %   
  32. % Please check for the latest version of the code and papers at  
  33. % www.lx.it.pt/~bioucas/TwIST  
  34. %  
  35. % ———————————————————————–  
  36. % Copyright (2007): Jose Bioucas-Dias and Mario Figueiredo  
  37. %   
  38. % TwIST is distributed under the terms of   
  39. % the GNU General Public License 2.0.  
  40. %   
  41. % Permission to use, copy, modify, and distribute this software for  
  42. % any purpose without fee is hereby granted, provided that this entire  
  43. % notice is included in all copies of any software which is or includes  
  44. % a copy or modification of this software and in all copies of the  
  45. % supporting documentation for such software.  
  46. % This software is being provided “as is”, without any express or  
  47. % implied warranty.  In particular, the authors do not make any  
  48. % representation or warranty of any kind concerning the merchantability  
  49. % of this software or its fitness for any particular purpose.”  
  50. % ———————————————————————-  
  51. %   
  52. %  ===== Required inputs =============  
  53. %  
  54. %  y: 1D vector or 2D array (image) of observations  
  55. %       
  56. %  A: if y and x are both 1D vectors, A can be a   
  57. %     k*n (where k is the size of y and n the size of x)  
  58. %     matrix or a handle to a function that computes  
  59. %     products of the form A*v, for some vector v.  
  60. %     In any other case (if y and/or x are 2D arrays),   
  61. %     A has to be passed as a handle to a function which computes   
  62. %     products of the form A*x; another handle to a function   
  63. %     AT which computes products of the form A’*x is also required   
  64. %     in this case. The size of x is determined as the size  
  65. %     of the result of applying AT.  
  66. %  
  67. %  tau: regularization parameter, usually a non-negative real   
  68. %       parameter of the objective  function (see above).   
  69. %    
  70. %  
  71. %  ===== Optional inputs =============  
  72. %    
  73. %  ‘Psi’ = denoising function handle; handle to denoising function  
  74. %          Default = soft threshold.  
  75. %  
  76. %  ‘Phi’ = function handle to regularizer needed to compute the objective  
  77. %          function.  
  78. %          Default = ||x||_1  
  79. %  
  80. %  ‘lambda’ = lam1 parameters of the  TwIST algorithm:  
  81. %             Optimal choice: lam1 = min eigenvalue of A’*A.  
  82. %             If min eigenvalue of A’*A == 0, or unknwon,    
  83. %             set lam1 to a value much smaller than 1.  
  84. %  
  85. %             Rule of Thumb:   
  86. %                 lam1=1e-4 for severyly ill-conditioned problems  
  87. %                 lam1=1e-2 for mildly  ill-conditioned problems  
  88. %                 lam1=1    for A unitary direct operators  
  89. %  
  90. %             Default: lam1 = 0.04.  
  91. %  
  92. %             Important Note: If (max eigenvalue of A’*A) > 1,  
  93. %             the algorithm may diverge. This is  be avoided   
  94. %             by taking one of the follwoing  measures:  
  95. %   
  96. %                1) Set ‘Monontone’ = 1 (default)  
  97. %                    
  98. %                2) Solve the equivalenve minimization problem  
  99. %  
  100. %             min_x = 0.5*|| (y/c) - (A/c) x ||_2^2 + (tau/c^2) \phi( x ),   
  101. %  
  102. %             where c > 0 ensures that  max eigenvalue of (A’A/c^2) <= 1.  
  103. %  
  104. %   ‘alpha’ = parameter alpha of TwIST (see ex. (22) of the paper)           
  105. %             Default alpha = alpha(lamN=1, lam1)  
  106. %     
  107. %   ‘beta’  =  parameter beta of twist (see ex. (23) of the paper)  
  108. %              Default beta = beta(lamN=1, lam1)              
  109. %   
  110. %  ‘AT’    = function handle for the function that implements  
  111. %            the multiplication by the conjugate of A, when A  
  112. %            is a function handle.   
  113. %            If A is an array, AT is ignored.  
  114. %  
  115. %  ‘StopCriterion’ = type of stopping criterion to use  
  116. %                    0 = algorithm stops when the relative   
  117. %                        change in the number of non-zero   
  118. %                        components of the estimate falls   
  119. %                        below ‘ToleranceA’  
  120. %                    1 = stop when the relative   
  121. %                        change in the objective function   
  122. %                        falls below ‘ToleranceA’  
  123. %                    2 = stop when the relative norm of the difference between   
  124. %                        two consecutive estimates falls below toleranceA  
  125. %                    3 = stop when the objective function   
  126. %                        becomes equal or less than toleranceA.  
  127. %                    Default = 1.  
  128. %  
  129. %  ‘ToleranceA’ = stopping threshold; Default = 0.01  
  130. %   
  131. %  ‘Debias’     = debiasing option: 1 = yes, 0 = no.  
  132. %                 Default = 0.  
  133. %                   
  134. %                 Note: Debiasing is an operation aimed at the   
  135. %                 computing the solution of the LS problem   
  136. %  
  137. %                         arg min_x = 0.5*|| y - A’ x’ ||_2^2   
  138. %  
  139. %                 where A’ is the  submatrix of A obatained by  
  140. %                 deleting the columns of A corresponding of components  
  141. %                 of x set to zero by the TwIST algorithm  
  142. %                   
  143. %  
  144. %  ‘ToleranceD’ = stopping threshold for the debiasing phase:  
  145. %                 Default = 0.0001.  
  146. %                 If no debiasing takes place, this parameter,  
  147. %                 if present, is ignored.  
  148. %  
  149. %  ‘MaxiterA’ = maximum number of iterations allowed in the  
  150. %               main phase of the algorithm.  
  151. %               Default = 1000  
  152. %  
  153. %  ‘MiniterA’ = minimum number of iterations performed in the  
  154. %               main phase of the algorithm.  
  155. %               Default = 5  
  156. %  
  157. %  ‘MaxiterD’ = maximum number of iterations allowed in the  
  158. %               debising phase of the algorithm.  
  159. %               Default = 200  
  160. %  
  161. %  ‘MiniterD’ = minimum number of iterations to perform in the  
  162. %               debiasing phase of the algorithm.  
  163. %               Default = 5  
  164. %  
  165. %  ‘Initialization’ must be one of {0,1,2,array}  
  166. %               0 -> Initialization at zero.   
  167. %               1 -> Random initialization.  
  168. %               2 -> initialization with A’*y.  
  169. %               array -> initialization provided by the user.  
  170. %               Default = 0;  
  171. %  
  172. %  ‘Monotone’ = enforce monotonic decrease in f.   
  173. %               any nonzero -> enforce monotonicity  
  174. %               0 -> don’t enforce monotonicity.  
  175. %               Default = 1;  
  176. %  
  177. %  ‘Sparse’   = {0,1} accelarates the convergence rate when the regularizer   
  178. %               Phi(x) is sparse inducing, such as ||x||_1.  
  179. %               Default = 1  
  180. %                 
  181. %               
  182. %  ‘True_x’ = if the true underlying x is passed in   
  183. %                this argument, MSE evolution is computed  
  184. %  
  185. %  
  186. %  ‘Verbose’  = work silently (0) or verbosely (1)  
  187. %  
  188. % ===================================================    
  189. % ============ Outputs ==============================  
  190. %   x = solution of the main algorithm  
  191. %  
  192. %   x_debias = solution after the debiasing phase;  
  193. %                  if no debiasing phase took place, this  
  194. %                  variable is empty, x_debias = [].  
  195. %  
  196. %   objective = sequence of values of the objective function  
  197. %  
  198. %   times = CPU time after each iteration  
  199. %  
  200. %   debias_start = iteration number at which the debiasing   
  201. %                  phase started. If no debiasing took place,  
  202. %                  this variable is returned as zero.  
  203. %  
  204. %   mses = sequence of MSE values, with respect to True_x,  
  205. %          if it was given; if it was not given, mses is empty,  
  206. %          mses = [].  
  207. %  
  208. %   max_svd = inverse of the scaling factor, determined by TwIST,  
  209. %             applied to the direct operator (A/max_svd) such that  
  210. %             every IST step is increasing.  
  211. % ========================================================  
  212.   
  213. %————————————————————–  
  214. % test for number of required parametres  
  215. %————————————————————–  
  216. if (nargin-length(varargin)) ~= 3  
  217.      error(‘Wrong number of required parameters’);  
  218. end  
  219. %————————————————————–  
  220. % Set the defaults for the optional parameters  
  221. %————————————————————–  
  222. stopCriterion = 1;  
  223. tolA = 0.01;  
  224. debias = 0;  
  225. maxiter = 1000;  
  226. maxiter_debias = 200;  
  227. miniter = 5;  
  228. miniter_debias = 5;  
  229. init = 0;  
  230. enforceMonotone = 1;  
  231. compute_mse = 0;  
  232. plot_ISNR = 0;  
  233. AT = 0;  
  234. verbose = 1;  
  235. alpha = 0;  
  236. beta  = 0;  
  237. sparse = 1;  
  238. tolD = 0.001;  
  239. phi_l1 = 0;  
  240. psi_ok = 0;  
  241. % default eigenvalues   
  242. lam1=1e-4;   lamN=1;  
  243. %   
  244.   
  245. % constants ans internal variables  
  246. for_ever = 1;  
  247. % maj_max_sv: majorizer for the maximum singular value of operator A  
  248. max_svd = 1;  
  249.   
  250. % Set the defaults for outputs that may not be computed  
  251. debias_start = 0;  
  252. x_debias = [];  
  253. mses = [];  
  254.   
  255. %————————————————————–  
  256. % Read the optional parameters  
  257. %————————————————————–  
  258. if (rem(length(varargin),2)==1)  
  259.   error(‘Optional parameters should always go by pairs’);  
  260. else  
  261.   for i=1:2:(length(varargin)-1)  
  262.     switch upper(varargin{i})  
  263.      case ‘LAMBDA’  
  264.        lam1 = varargin{i+1};  
  265.      case ‘ALPHA’  
  266.        alpha = varargin{i+1};  
  267.      case ‘BETA’  
  268.        beta = varargin{i+1};  
  269.      case ‘PSI’  
  270.        psi_function = varargin{i+1};  
  271.      case ‘PHI’  
  272.        phi_function = varargin{i+1};     
  273.      case ‘STOPCRITERION’  
  274.        stopCriterion = varargin{i+1};  
  275.      case ‘TOLERANCEA’         
  276.        tolA = varargin{i+1};  
  277.      case ‘TOLERANCED’  
  278.        tolD = varargin{i+1};  
  279.      case ‘DEBIAS’  
  280.        debias = varargin{i+1};  
  281.      case ‘MAXITERA’  
  282.        maxiter = varargin{i+1};  
  283.      case ‘MAXIRERD’  
  284.        maxiter_debias = varargin{i+1};  
  285.      case ‘MINITERA’  
  286.        miniter = varargin{i+1};  
  287.      case ‘MINITERD’  
  288.        miniter_debias = varargin{i+1};  
  289.      case ‘INITIALIZATION’  
  290.        if prod(size(varargin{i+1})) > 1   % we have an initial x  
  291.      init = 33333;    % some flag to be used below  
  292.      x = varargin{i+1};  
  293.        else   
  294.      init = varargin{i+1};  
  295.        end  
  296.      case ‘MONOTONE’  
  297.        enforceMonotone = varargin{i+1};  
  298.      case ‘SPARSE’  
  299.        sparse = varargin{i+1};  
  300.      case ‘TRUE_X’  
  301.        compute_mse = 1;  
  302.        true = varargin{i+1};  
  303.        if prod(double((size(true) == size(y))))  
  304.            plot_ISNR = 1;  
  305.        end  
  306.      case ‘AT’  
  307.        AT = varargin{i+1};  
  308.      case ‘VERBOSE’  
  309.        verbose = varargin{i+1};  
  310.      otherwise  
  311.       % Hmmm, something wrong with the parameter string  
  312.       error([‘Unrecognized option: ”’ varargin{i} ””]);  
  313.     end;  
  314.   end;  
  315. end  
  316. %%%%%%%%%%%%%%  
  317.   
  318.   
  319. % twist parameters   
  320. rho0 = (1-lam1/lamN)/(1+lam1/lamN);  
  321. if alpha == 0   
  322.     alpha = 2/(1+sqrt(1-rho0^2));  
  323. end  
  324. if  beta == 0   
  325.     beta  = alpha*2/(lam1+lamN);  
  326. end  
  327.   
  328.   
  329. if (sum(stopCriterion == [0 1 2 3])==0)  
  330.    error([‘Unknwon stopping criterion’]);  
  331. end  
  332.   
  333. % if A is a function handle, we have to check presence of AT,  
  334. if isa(A, ‘function_handle’) & ~isa(AT,’function_handle’)  
  335.    error([‘The function handle for transpose of A is missing’]);  
  336. end   
  337.   
  338.   
  339. % if A is a matrix, we find out dimensions of y and x,  
  340. % and create function handles for multiplication by A and A’,  
  341. % so that the code below doesn’t have to distinguish between  
  342. % the handle/not-handle cases  
  343. if ~isa(A, ‘function_handle’)  
  344.    AT = @(x) A’*x;  
  345.    A = @(x) A*x;  
  346. end  
  347. % from this point down, A and AT are always function handles.  
  348.   
  349. % Precompute A’*y since it’ll be used a lot  
  350. Aty = AT(y);  
  351.   
  352. % if phi was given, check to see if it is a handle and that it   
  353. % accepts two arguments  
  354. if exist(‘psi_function’,’var’)  
  355.    if isa(psi_function,’function_handle’)  
  356.       try  % check if phi can be used, using Aty, which we know has   
  357.            % same size as x  
  358.             dummy = psi_function(Aty,tau);   
  359.             psi_ok = 1;  
  360.       catch  
  361.          error([‘Something is wrong with function handle for psi’])  
  362.       end  
  363.    else  
  364.       error([‘Psi does not seem to be a valid function handle’]);  
  365.    end  
  366. else %if nothing was given, use soft thresholding  
  367.    psi_function = @(x,tau) soft(x,tau);  
  368. end  
  369.   
  370. % if psi exists, phi must also exist  
  371. if (psi_ok == 1)  
  372.    if exist(‘phi_function’,’var’)  
  373.       if isa(phi_function,’function_handle’)  
  374.          try  % check if phi can be used, using Aty, which we know has   
  375.               % same size as x  
  376.               dummy = phi_function(Aty);   
  377.          catch  
  378.            error([‘Something is wrong with function handle for phi’])  
  379.          end  
  380.       else  
  381.         error([‘Phi does not seem to be a valid function handle’]);  
  382.       end  
  383.    else  
  384.       error([‘If you give Psi you must also give Phi’]);   
  385.    end  
  386. else  % if no psi and phi were given, simply use the l1 norm.  
  387.    phi_function = @(x) sum(abs(x(:)));   
  388.    phi_l1 = 1;  
  389. end  
  390.       
  391.   
  392. %————————————————————–  
  393. % Initialization  
  394. %————————————————————–  
  395. switch init  
  396.     case 0   % initialize at zero, using AT to find the size of x  
  397.        x = AT(zeros(size(y)));  
  398.     case 1   % initialize randomly, using AT to find the size of x  
  399.        x = randn(size(AT(zeros(size(y)))));  
  400.     case 2   % initialize x0 = A’*y  
  401.        x = Aty;   
  402.     case 33333  
  403.        % initial x was given as a function argument; just check size  
  404.        if size(A(x)) ~= size(y)  
  405.           error([‘Size of initial x is not compatible with A’]);   
  406.        end  
  407.     otherwise  
  408.        error([‘Unknown ”Initialization” option’]);  
  409. end  
  410.   
  411. % now check if tau is an array; if it is, it has to   
  412. % have the same size as x  
  413. if prod(size(tau)) > 1  
  414.    try,  
  415.       dummy = x.*tau;  
  416.    catch,  
  417.       error([‘Parameter tau has wrong dimensions; it should be scalar or size(x)’]),  
  418.    end  
  419. end  
  420.         
  421. % if the true x was given, check its size  
  422. if compute_mse & (size(true) ~= size(x))    
  423.    error([‘Initial x has incompatible size’]);   
  424. end  
  425.   
  426.   
  427. % if tau is large enough, in the case of phi = l1, thus psi = soft,  
  428. % the optimal solution is the zero vector  
  429. if phi_l1  
  430.    max_tau = max(abs(Aty(:)));  
  431.    if (tau >= max_tau)&(psi_ok==0)  
  432.       x = zeros(size(Aty));  
  433.       objective(1) = 0.5*(y(:)’*y(:));  
  434.       times(1) = 0;  
  435.       if compute_mse  
  436.         mses(1) = sum(true(:).^2);  
  437.       end  
  438.       return  
  439.    end  
  440. end  
  441.   
  442.   
  443. % define the indicator vector or matrix of nonzeros in x  
  444. nz_x = (x ~= 0.0);  
  445. num_nz_x = sum(nz_x(:));  
  446.   
  447. % Compute and store initial value of the objective function  
  448. resid =  y-A(x);  
  449. prev_f = 0.5*(resid(:)’*resid(:)) + tau*phi_function(x);  
  450.   
  451.   
  452. % start the clock  
  453. t0 = cputime;  
  454.   
  455. times(1) = cputime - t0;  
  456. objective(1) = prev_f;  
  457.   
  458. if compute_mse  
  459.    mses(1) = sum(sum((x-true).^2));  
  460. end  
  461.   
  462. cont_outer = 1;  
  463. iter = 1;  
  464.   
  465. if verbose  
  466.     fprintf(1,’\nInitial objective = %10.6e,  nonzeros=%7d\n’,…  
  467.         prev_f,num_nz_x);  
  468. end  
  469.   
  470. % variables controling first and second order iterations  
  471. IST_iters = 0;  
  472. TwIST_iters = 0;  
  473.   
  474. % initialize  
  475. xm2=x;  
  476. xm1=x;  
  477.   
  478. %————————————————————–  
  479. % TwIST iterations  
  480. %————————————————————–  
  481. while cont_outer  
  482.     % gradient  
  483.     grad = AT(resid);  
  484.     while for_ever  
  485.         % IST estimate  
  486.         x = psi_function(xm1 + grad/max_svd,tau/max_svd);  
  487.         if (IST_iters >= 2) | ( TwIST_iters ~= 0)  
  488.             % set to zero the past when the present is zero  
  489.             % suitable for sparse inducing priors  
  490.             if sparse  
  491.                 mask = (x ~= 0);  
  492.                 xm1 = xm1.* mask;  
  493.                 xm2 = xm2.* mask;  
  494.             end  
  495.             % two-step iteration  
  496.             xm2 = (alpha-beta)*xm1 + (1-alpha)*xm2 + beta*x;  
  497.             % compute residual  
  498.             resid = y-A(xm2);  
  499.             f = 0.5*(resid(:)’*resid(:)) + tau*phi_function(xm2);  
  500.             if (f > prev_f) & (enforceMonotone)  
  501.                 TwIST_iters = 0;  % do a IST iteration if monotonocity fails  
  502.             else  
  503.                 TwIST_iters = TwIST_iters+1; % TwIST iterations  
  504.                 IST_iters = 0;  
  505.                 x = xm2;  
  506.                 if mod(TwIST_iters,10000) == 0  
  507.                     max_svd = 0.9*max_svd;  
  508.                 end  
  509.                 break;  % break loop while  
  510.             end  
  511.         else  
  512.             resid = y-A(x);  
  513.             f = 0.5*(resid(:)’*resid(:)) + tau*phi_function(x);  
  514.             if f > prev_f  
  515.                 % if monotonicity  fails here  is  because  
  516.                 % max eig (A’A) > 1. Thus, we increase our guess  
  517.                 % of max_svs  
  518.                 max_svd = 2*max_svd;  
  519.                 if verbose  
  520.                     fprintf(‘Incrementing S=%2.2e\n’,max_svd)  
  521.                 end  
  522.                 IST_iters = 0;  
  523.                 TwIST_iters = 0;  
  524.             else  
  525.                 TwIST_iters = TwIST_iters + 1;  
  526.                 break;  % break loop while  
  527.             end  
  528.         end  
  529.     end  
  530.   
  531.     xm2 = xm1;  
  532.     xm1 = x;  
  533.   
  534.   
  535.   
  536.     %update the number of nonzero components and its variation  
  537.     nz_x_prev = nz_x;  
  538.     nz_x = (x~=0.0);  
  539.     num_nz_x = sum(nz_x(:));  
  540.     num_changes_active = (sum(nz_x(:)~=nz_x_prev(:)));  
  541.   
  542.     % take no less than miniter and no more than maxiter iterations  
  543.     switch stopCriterion  
  544.         case 0,  
  545.             % compute the stopping criterion based on the change  
  546.             % of the number of non-zero components of the estimate  
  547.             criterion =  num_changes_active;  
  548.         case 1,  
  549.             % compute the stopping criterion based on the relative  
  550.             % variation of the objective function.  
  551.             criterion = abs(f-prev_f)/prev_f;  
  552.         case 2,  
  553.             % compute the stopping criterion based on the relative  
  554.             % variation of the estimate.  
  555.             criterion = (norm(x(:)-xm1(:))/norm(x(:)));  
  556.         case 3,  
  557.             % continue if not yet reached target value tolA  
  558.             criterion = f;  
  559.         otherwise,  
  560.             error([‘Unknwon stopping criterion’]);  
  561.     end  
  562.     cont_outer = ((iter <= maxiter) & (criterion > tolA));  
  563.     if iter <= miniter  
  564.         cont_outer = 1;  
  565.     end  
  566.   
  567.   
  568.   
  569.     iter = iter + 1;  
  570.     prev_f = f;  
  571.     objective(iter) = f;  
  572.     times(iter) = cputime-t0;  
  573.   
  574.     if compute_mse  
  575.         err = true - x;  
  576.         mses(iter) = (err(:)’*err(:));  
  577.     end  
  578.   
  579.     % print out the various stopping criteria  
  580.     if verbose  
  581.         if plot_ISNR  
  582.             fprintf(1,’Iteration=%4d, ISNR=%4.5e  objective=%9.5e, nz=%7d, criterion=%7.3e\n’,…  
  583.                 iter, 10*log10(sum((y(:)-true(:)).^2)/sum((x(:)-true(:)).^2) ), …  
  584.                 f, num_nz_x, criterion/tolA);  
  585.         else  
  586.             fprintf(1,’Iteration=%4d, objective=%9.5e, nz=%7d,  criterion=%7.3e\n’,…  
  587.                 iter, f, num_nz_x, criterion/tolA);  
  588.         end  
  589.     end  
  590.   
  591. end  
  592. %————————————————————–  
  593. % end of the main loop  
  594. %————————————————————–  
  595.   
  596. % Printout results  
  597. if verbose  
  598.     fprintf(1,’\nFinished the main algorithm!\nResults:\n’)  
  599.     fprintf(1,’||A x - y ||_2 = %10.3e\n’,resid(:)’*resid(:))  
  600.     fprintf(1,’||x||_1 = %10.3e\n’,sum(abs(x(:))))  
  601.     fprintf(1,’Objective function = %10.3e\n’,f);  
  602.     fprintf(1,’Number of non-zero components = %d\n’,num_nz_x);  
  603.     fprintf(1,’CPU time so far = %10.3e\n’, times(iter));  
  604.     fprintf(1,’\n’);  
  605. end  
  606.   
  607.   
  608. %————————————————————–  
  609. % If the ‘Debias’ option is set to 1, we try to  
  610. % remove the bias from the l1 penalty, by applying CG to the  
  611. % least-squares problem obtained by omitting the l1 term  
  612. % and fixing the zero coefficients at zero.  
  613. %————————————————————–  
  614. if debias  
  615.     if verbose  
  616.         fprintf(1,’\n’)  
  617.         fprintf(1,’Starting the debiasing phase…\n\n’)  
  618.     end  
  619.   
  620.     x_debias = x;  
  621.     zeroind = (x_debias~=0);  
  622.     cont_debias_cg = 1;  
  623.     debias_start = iter;  
  624.   
  625.     % calculate initial residual  
  626.     resid = A(x_debias);  
  627.     resid = resid-y;  
  628.     resid_prev = eps*ones(size(resid));  
  629.   
  630.     rvec = AT(resid);  
  631.   
  632.     % mask out the zeros  
  633.     rvec = rvec .* zeroind;  
  634.     rTr_cg = rvec(:)’*rvec(:);  
  635.   
  636.     % set convergence threshold for the residual || RW x_debias - y ||_2  
  637.     tol_debias = tolD * (rvec(:)’*rvec(:));  
  638.   
  639.     % initialize pvec  
  640.     pvec = -rvec;  
  641.   
  642.     % main loop  
  643.     while cont_debias_cg  
  644.   
  645.         % calculate A*p = Wt * Rt * R * W * pvec  
  646.         RWpvec = A(pvec);  
  647.         Apvec = AT(RWpvec);  
  648.   
  649.         % mask out the zero terms  
  650.         Apvec = Apvec .* zeroind;  
  651.   
  652.         % calculate alpha for CG  
  653.         alpha_cg = rTr_cg / (pvec(:)’* Apvec(:));  
  654.   
  655.         % take the step  
  656.         x_debias = x_debias + alpha_cg * pvec;  
  657.         resid = resid + alpha_cg * RWpvec;  
  658.         rvec  = rvec  + alpha_cg * Apvec;  
  659.   
  660.         rTr_cg_plus = rvec(:)’*rvec(:);  
  661.         beta_cg = rTr_cg_plus / rTr_cg;  
  662.         pvec = -rvec + beta_cg * pvec;  
  663.   
  664.         rTr_cg = rTr_cg_plus;  
  665.   
  666.         iter = iter+1;  
  667.   
  668.         objective(iter) = 0.5*(resid(:)’*resid(:)) + …  
  669.             tau*phi_function(x_debias(:));  
  670.         times(iter) = cputime - t0;  
  671.   
  672.         if compute_mse  
  673.             err = true - x_debias;  
  674.             mses(iter) = (err(:)’*err(:));  
  675.         end  
  676.   
  677.         % in the debiasing CG phase, always use convergence criterion  
  678.         % based on the residual (this is standard for CG)  
  679.         if verbose  
  680.             fprintf(1,’ Iter = %5d, debias resid = %13.8e, convergence = %8.3e\n’, …  
  681.                 iter, resid(:)’*resid(:), rTr_cg / tol_debias);  
  682.         end  
  683.         cont_debias_cg = …  
  684.             (iter-debias_start <= miniter_debias )| …  
  685.             ((rTr_cg > tol_debias) & …  
  686.             (iter-debias_start <= maxiter_debias));  
  687.   
  688.     end  
  689.     if verbose  
  690.         fprintf(1,’\nFinished the debiasing phase!\nResults:\n’)  
  691.         fprintf(1,’||A x - y ||_2 = %10.3e\n’,resid(:)’*resid(:))  
  692.         fprintf(1,’||x||_1 = %10.3e\n’,sum(abs(x(:))))  
  693.         fprintf(1,’Objective function = %10.3e\n’,f);  
  694.         nz = (x_debias~=0.0);  
  695.         fprintf(1,’Number of non-zero components = %d\n’,sum(nz(:)));  
  696.         fprintf(1,’CPU time so far = %10.3e\n’, times(iter));  
  697.         fprintf(1,’\n’);  
  698.     end  
  699. end  
  700.   
  701. if compute_mse  
  702.     mses = mses/length(true(:));  
  703. end  
  704.   
  705.   
  706. %————————————————————–  
  707. % soft for both real and  complex numbers  
  708. %————————————————————–  
  709. function y = soft(x,T)  
  710. %y = sign(x).*max(abs(x)-tau,0);  
  711. y = max(abs(x) - T, 0);  
  712. y = y./(y+T) .* x;  
function [x,x_debias,objective,times,debias_start,mses,max_svd] = ...
         TwIST(y,A,tau,varargin)
%
% Usage:
% [x,x_debias,objective,times,debias_start,mses] = TwIST(y,A,tau,varargin)
%
% This function solves the regularization problem 
%
%     arg min_x = 0.5*|| y - A x ||_2^2 + tau phi( x ), 
%
% where A is a generic matrix and phi(.) is a regularizarion 
% function  such that the solution of the denoising problem 
%
%     Psi_tau(y) = arg min_x = 0.5*|| y - x ||_2^2 + tau \phi( x ), 
%
% is known. 
% 
% For further details about the TwIST algorithm, see the paper:
%
% J. Bioucas-Dias and M. Figueiredo, "A New TwIST: Two-Step
% Iterative Shrinkage/Thresholding Algorithms for Image 
% Restoration",  IEEE Transactions on Image processing, 2007.
% 
% and
% 
% J. Bioucas-Dias and M. Figueiredo, "A Monotonic Two-Step 
% Algorithm for Compressive Sensing and Other Ill-Posed 
% Inverse Problems", submitted, 2007.
%
% Authors: Jose Bioucas-Dias and Mario Figueiredo, October, 2007.
% 
% Please check for the latest version of the code and papers at
% www.lx.it.pt/~bioucas/TwIST
%
% -----------------------------------------------------------------------
% Copyright (2007): Jose Bioucas-Dias and Mario Figueiredo
% 
% TwIST is distributed under the terms of 
% the GNU General Public License 2.0.
% 
% Permission to use, copy, modify, and distribute this software for
% any purpose without fee is hereby granted, provided that this entire
% notice is included in all copies of any software which is or includes
% a copy or modification of this software and in all copies of the
% supporting documentation for such software.
% This software is being provided "as is", without any express or
% implied warranty.  In particular, the authors do not make any
% representation or warranty of any kind concerning the merchantability
% of this software or its fitness for any particular purpose."
% ----------------------------------------------------------------------
% 
%  ===== Required inputs =============
%
%  y: 1D vector or 2D array (image) of observations
%     
%  A: if y and x are both 1D vectors, A can be a 
%     k*n (where k is the size of y and n the size of x)
%     matrix or a handle to a function that computes
%     products of the form A*v, for some vector v.
%     In any other case (if y and/or x are 2D arrays), 
%     A has to be passed as a handle to a function which computes 
%     products of the form A*x; another handle to a function 
%     AT which computes products of the form A'*x is also required 
%     in this case. The size of x is determined as the size
%     of the result of applying AT.
%
%  tau: regularization parameter, usually a non-negative real 
%       parameter of the objective  function (see above). 
%  
%
%  ===== Optional inputs =============
%  
%  'Psi' = denoising function handle; handle to denoising function
%          Default = soft threshold.
%
%  'Phi' = function handle to regularizer needed to compute the objective
%          function.
%          Default = ||x||_1
%
%  'lambda' = lam1 parameters of the  TwIST algorithm:
%             Optimal choice: lam1 = min eigenvalue of A'*A.
%             If min eigenvalue of A'*A == 0, or unknwon,  
%             set lam1 to a value much smaller than 1.
%
%             Rule of Thumb: 
%                 lam1=1e-4 for severyly ill-conditioned problems
%                 lam1=1e-2 for mildly  ill-conditioned problems
%                 lam1=1    for A unitary direct operators
%
%             Default: lam1 = 0.04.
%
%             Important Note: If (max eigenvalue of A'*A) > 1,
%             the algorithm may diverge. This is  be avoided 
%             by taking one of the follwoing  measures:
% 
%                1) Set 'Monontone' = 1 (default)
%                  
%                2) Solve the equivalenve minimization problem
%
%             min_x = 0.5*|| (y/c) - (A/c) x ||_2^2 + (tau/c^2) \phi( x ), 
%
%             where c > 0 ensures that  max eigenvalue of (A'A/c^2) <= 1.
%
%   'alpha' = parameter alpha of TwIST (see ex. (22) of the paper)         
%             Default alpha = alpha(lamN=1, lam1)
%   
%   'beta'  =  parameter beta of twist (see ex. (23) of the paper)
%              Default beta = beta(lamN=1, lam1)            
% 
%  'AT'    = function handle for the function that implements
%            the multiplication by the conjugate of A, when A
%            is a function handle. 
%            If A is an array, AT is ignored.
%
%  'StopCriterion' = type of stopping criterion to use
%                    0 = algorithm stops when the relative 
%                        change in the number of non-zero 
%                        components of the estimate falls 
%                        below 'ToleranceA'
%                    1 = stop when the relative 
%                        change in the objective function 
%                        falls below 'ToleranceA'
%                    2 = stop when the relative norm of the difference between 
%                        two consecutive estimates falls below toleranceA
%                    3 = stop when the objective function 
%                        becomes equal or less than toleranceA.
%                    Default = 1.
%
%  'ToleranceA' = stopping threshold; Default = 0.01
% 
%  'Debias'     = debiasing option: 1 = yes, 0 = no.
%                 Default = 0.
%                 
%                 Note: Debiasing is an operation aimed at the 
%                 computing the solution of the LS problem 
%
%                         arg min_x = 0.5*|| y - A' x' ||_2^2 
%
%                 where A' is the  submatrix of A obatained by
%                 deleting the columns of A corresponding of components
%                 of x set to zero by the TwIST algorithm
%                 
%
%  'ToleranceD' = stopping threshold for the debiasing phase:
%                 Default = 0.0001.
%                 If no debiasing takes place, this parameter,
%                 if present, is ignored.
%
%  'MaxiterA' = maximum number of iterations allowed in the
%               main phase of the algorithm.
%               Default = 1000
%
%  'MiniterA' = minimum number of iterations performed in the
%               main phase of the algorithm.
%               Default = 5
%
%  'MaxiterD' = maximum number of iterations allowed in the
%               debising phase of the algorithm.
%               Default = 200
%
%  'MiniterD' = minimum number of iterations to perform in the
%               debiasing phase of the algorithm.
%               Default = 5
%
%  'Initialization' must be one of {0,1,2,array}
%               0 -> Initialization at zero. 
%               1 -> Random initialization.
%               2 -> initialization with A'*y.
%               array -> initialization provided by the user.
%               Default = 0;
%
%  'Monotone' = enforce monotonic decrease in f. 
%               any nonzero -> enforce monotonicity
%               0 -> don't enforce monotonicity.
%               Default = 1;
%
%  'Sparse'   = {0,1} accelarates the convergence rate when the regularizer 
%               Phi(x) is sparse inducing, such as ||x||_1.
%               Default = 1
%               
%             
%  'True_x' = if the true underlying x is passed in 
%                this argument, MSE evolution is computed
%
%
%  'Verbose'  = work silently (0) or verbosely (1)
%
% ===================================================  
% ============ Outputs ==============================
%   x = solution of the main algorithm
%
%   x_debias = solution after the debiasing phase;
%                  if no debiasing phase took place, this
%                  variable is empty, x_debias = [].
%
%   objective = sequence of values of the objective function
%
%   times = CPU time after each iteration
%
%   debias_start = iteration number at which the debiasing 
%                  phase started. If no debiasing took place,
%                  this variable is returned as zero.
%
%   mses = sequence of MSE values, with respect to True_x,
%          if it was given; if it was not given, mses is empty,
%          mses = [].
%
%   max_svd = inverse of the scaling factor, determined by TwIST,
%             applied to the direct operator (A/max_svd) such that
%             every IST step is increasing.
% ========================================================

%--------------------------------------------------------------
% test for number of required parametres
%--------------------------------------------------------------
if (nargin-length(varargin)) ~= 3
     error('Wrong number of required parameters');
end
%--------------------------------------------------------------
% Set the defaults for the optional parameters
%--------------------------------------------------------------
stopCriterion = 1;
tolA = 0.01;
debias = 0;
maxiter = 1000;
maxiter_debias = 200;
miniter = 5;
miniter_debias = 5;
init = 0;
enforceMonotone = 1;
compute_mse = 0;
plot_ISNR = 0;
AT = 0;
verbose = 1;
alpha = 0;
beta  = 0;
sparse = 1;
tolD = 0.001;
phi_l1 = 0;
psi_ok = 0;
% default eigenvalues 
lam1=1e-4;   lamN=1;
% 

% constants ans internal variables
for_ever = 1;
% maj_max_sv: majorizer for the maximum singular value of operator A
max_svd = 1;

% Set the defaults for outputs that may not be computed
debias_start = 0;
x_debias = [];
mses = [];

%--------------------------------------------------------------
% Read the optional parameters
%--------------------------------------------------------------
if (rem(length(varargin),2)==1)
  error('Optional parameters should always go by pairs');
else
  for i=1:2:(length(varargin)-1)
    switch upper(varargin{i})
     case 'LAMBDA'
       lam1 = varargin{i+1};
     case 'ALPHA'
       alpha = varargin{i+1};
     case 'BETA'
       beta = varargin{i+1};
     case 'PSI'
       psi_function = varargin{i+1};
     case 'PHI'
       phi_function = varargin{i+1};   
     case 'STOPCRITERION'
       stopCriterion = varargin{i+1};
     case 'TOLERANCEA'       
       tolA = varargin{i+1};
     case 'TOLERANCED'
       tolD = varargin{i+1};
     case 'DEBIAS'
       debias = varargin{i+1};
     case 'MAXITERA'
       maxiter = varargin{i+1};
     case 'MAXIRERD'
       maxiter_debias = varargin{i+1};
     case 'MINITERA'
       miniter = varargin{i+1};
     case 'MINITERD'
       miniter_debias = varargin{i+1};
     case 'INITIALIZATION'
       if prod(size(varargin{i+1})) > 1   % we have an initial x
     init = 33333;    % some flag to be used below
     x = varargin{i+1};
       else 
     init = varargin{i+1};
       end
     case 'MONOTONE'
       enforceMonotone = varargin{i+1};
     case 'SPARSE'
       sparse = varargin{i+1};
     case 'TRUE_X'
       compute_mse = 1;
       true = varargin{i+1};
       if prod(double((size(true) == size(y))))
           plot_ISNR = 1;
       end
     case 'AT'
       AT = varargin{i+1};
     case 'VERBOSE'
       verbose = varargin{i+1};
     otherwise
      % Hmmm, something wrong with the parameter string
      error(['Unrecognized option: ''' varargin{i} '''']);
    end;
  end;
end
%%%%%%%%%%%%%%


% twist parameters 
rho0 = (1-lam1/lamN)/(1+lam1/lamN);
if alpha == 0 
    alpha = 2/(1+sqrt(1-rho0^2));
end
if  beta == 0 
    beta  = alpha*2/(lam1+lamN);
end


if (sum(stopCriterion == [0 1 2 3])==0)
   error(['Unknwon stopping criterion']);
end

% if A is a function handle, we have to check presence of AT,
if isa(A, 'function_handle') & ~isa(AT,'function_handle')
   error(['The function handle for transpose of A is missing']);
end 


% if A is a matrix, we find out dimensions of y and x,
% and create function handles for multiplication by A and A',
% so that the code below doesn't have to distinguish between
% the handle/not-handle cases
if ~isa(A, 'function_handle')
   AT = @(x) A'*x;
   A = @(x) A*x;
end
% from this point down, A and AT are always function handles.

% Precompute A'*y since it'll be used a lot
Aty = AT(y);

% if phi was given, check to see if it is a handle and that it 
% accepts two arguments
if exist('psi_function','var')
   if isa(psi_function,'function_handle')
      try  % check if phi can be used, using Aty, which we know has 
           % same size as x
            dummy = psi_function(Aty,tau); 
            psi_ok = 1;
      catch
         error(['Something is wrong with function handle for psi'])
      end
   else
      error(['Psi does not seem to be a valid function handle']);
   end
else %if nothing was given, use soft thresholding
   psi_function = @(x,tau) soft(x,tau);
end

% if psi exists, phi must also exist
if (psi_ok == 1)
   if exist('phi_function','var')
      if isa(phi_function,'function_handle')
         try  % check if phi can be used, using Aty, which we know has 
              % same size as x
              dummy = phi_function(Aty); 
         catch
           error(['Something is wrong with function handle for phi'])
         end
      else
        error(['Phi does not seem to be a valid function handle']);
      end
   else
      error(['If you give Psi you must also give Phi']); 
   end
else  % if no psi and phi were given, simply use the l1 norm.
   phi_function = @(x) sum(abs(x(:))); 
   phi_l1 = 1;
end


%--------------------------------------------------------------
% Initialization
%--------------------------------------------------------------
switch init
    case 0   % initialize at zero, using AT to find the size of x
       x = AT(zeros(size(y)));
    case 1   % initialize randomly, using AT to find the size of x
       x = randn(size(AT(zeros(size(y)))));
    case 2   % initialize x0 = A'*y
       x = Aty; 
    case 33333
       % initial x was given as a function argument; just check size
       if size(A(x)) ~= size(y)
          error(['Size of initial x is not compatible with A']); 
       end
    otherwise
       error(['Unknown ''Initialization'' option']);
end

% now check if tau is an array; if it is, it has to 
% have the same size as x
if prod(size(tau)) > 1
   try,
      dummy = x.*tau;
   catch,
      error(['Parameter tau has wrong dimensions; it should be scalar or size(x)']),
   end
end

% if the true x was given, check its size
if compute_mse & (size(true) ~= size(x))  
   error(['Initial x has incompatible size']); 
end


% if tau is large enough, in the case of phi = l1, thus psi = soft,
% the optimal solution is the zero vector
if phi_l1
   max_tau = max(abs(Aty(:)));
   if (tau >= max_tau)&(psi_ok==0)
      x = zeros(size(Aty));
      objective(1) = 0.5*(y(:)'*y(:));
      times(1) = 0;
      if compute_mse
        mses(1) = sum(true(:).^2);
      end
      return
   end
end


% define the indicator vector or matrix of nonzeros in x
nz_x = (x ~= 0.0);
num_nz_x = sum(nz_x(:));

% Compute and store initial value of the objective function
resid =  y-A(x);
prev_f = 0.5*(resid(:)'*resid(:)) + tau*phi_function(x);


% start the clock
t0 = cputime;

times(1) = cputime - t0;
objective(1) = prev_f;

if compute_mse
   mses(1) = sum(sum((x-true).^2));
end

cont_outer = 1;
iter = 1;

if verbose
    fprintf(1,'\nInitial objective = %10.6e,  nonzeros=%7d\n',...
        prev_f,num_nz_x);
end

% variables controling first and second order iterations
IST_iters = 0;
TwIST_iters = 0;

% initialize
xm2=x;
xm1=x;

%--------------------------------------------------------------
% TwIST iterations
%--------------------------------------------------------------
while cont_outer
    % gradient
    grad = AT(resid);
    while for_ever
        % IST estimate
        x = psi_function(xm1 + grad/max_svd,tau/max_svd);
        if (IST_iters >= 2) | ( TwIST_iters ~= 0)
            % set to zero the past when the present is zero
            % suitable for sparse inducing priors
            if sparse
                mask = (x ~= 0);
                xm1 = xm1.* mask;
                xm2 = xm2.* mask;
            end
            % two-step iteration
            xm2 = (alpha-beta)*xm1 + (1-alpha)*xm2 + beta*x;
            % compute residual
            resid = y-A(xm2);
            f = 0.5*(resid(:)'*resid(:)) + tau*phi_function(xm2);
            if (f > prev_f) & (enforceMonotone)
                TwIST_iters = 0;  % do a IST iteration if monotonocity fails
            else
                TwIST_iters = TwIST_iters+1; % TwIST iterations
                IST_iters = 0;
                x = xm2;
                if mod(TwIST_iters,10000) == 0
                    max_svd = 0.9*max_svd;
                end
                break;  % break loop while
            end
        else
            resid = y-A(x);
            f = 0.5*(resid(:)'*resid(:)) + tau*phi_function(x);
            if f > prev_f
                % if monotonicity  fails here  is  because
                % max eig (A'A) > 1. Thus, we increase our guess
                % of max_svs
                max_svd = 2*max_svd;
                if verbose
                    fprintf('Incrementing S=%2.2e\n',max_svd)
                end
                IST_iters = 0;
                TwIST_iters = 0;
            else
                TwIST_iters = TwIST_iters + 1;
                break;  % break loop while
            end
        end
    end

    xm2 = xm1;
    xm1 = x;



    %update the number of nonzero components and its variation
    nz_x_prev = nz_x;
    nz_x = (x~=0.0);
    num_nz_x = sum(nz_x(:));
    num_changes_active = (sum(nz_x(:)~=nz_x_prev(:)));

    % take no less than miniter and no more than maxiter iterations
    switch stopCriterion
        case 0,
            % compute the stopping criterion based on the change
            % of the number of non-zero components of the estimate
            criterion =  num_changes_active;
        case 1,
            % compute the stopping criterion based on the relative
            % variation of the objective function.
            criterion = abs(f-prev_f)/prev_f;
        case 2,
            % compute the stopping criterion based on the relative
            % variation of the estimate.
            criterion = (norm(x(:)-xm1(:))/norm(x(:)));
        case 3,
            % continue if not yet reached target value tolA
            criterion = f;
        otherwise,
            error(['Unknwon stopping criterion']);
    end
    cont_outer = ((iter <= maxiter) & (criterion > tolA));
    if iter <= miniter
        cont_outer = 1;
    end



    iter = iter + 1;
    prev_f = f;
    objective(iter) = f;
    times(iter) = cputime-t0;

    if compute_mse
        err = true - x;
        mses(iter) = (err(:)'*err(:));
    end

    % print out the various stopping criteria
    if verbose
        if plot_ISNR
            fprintf(1,'Iteration=%4d, ISNR=%4.5e  objective=%9.5e, nz=%7d, criterion=%7.3e\n',...
                iter, 10*log10(sum((y(:)-true(:)).^2)/sum((x(:)-true(:)).^2) ), ...
                f, num_nz_x, criterion/tolA);
        else
            fprintf(1,'Iteration=%4d, objective=%9.5e, nz=%7d,  criterion=%7.3e\n',...
                iter, f, num_nz_x, criterion/tolA);
        end
    end

end
%--------------------------------------------------------------
% end of the main loop
%--------------------------------------------------------------

% Printout results
if verbose
    fprintf(1,'\nFinished the main algorithm!\nResults:\n')
    fprintf(1,'||A x - y ||_2 = %10.3e\n',resid(:)'*resid(:))
    fprintf(1,'||x||_1 = %10.3e\n',sum(abs(x(:))))
    fprintf(1,'Objective function = %10.3e\n',f);
    fprintf(1,'Number of non-zero components = %d\n',num_nz_x);
    fprintf(1,'CPU time so far = %10.3e\n', times(iter));
    fprintf(1,'\n');
end


%--------------------------------------------------------------
% If the 'Debias' option is set to 1, we try to
% remove the bias from the l1 penalty, by applying CG to the
% least-squares problem obtained by omitting the l1 term
% and fixing the zero coefficients at zero.
%--------------------------------------------------------------
if debias
    if verbose
        fprintf(1,'\n')
        fprintf(1,'Starting the debiasing phase...\n\n')
    end

    x_debias = x;
    zeroind = (x_debias~=0);
    cont_debias_cg = 1;
    debias_start = iter;

    % calculate initial residual
    resid = A(x_debias);
    resid = resid-y;
    resid_prev = eps*ones(size(resid));

    rvec = AT(resid);

    % mask out the zeros
    rvec = rvec .* zeroind;
    rTr_cg = rvec(:)'*rvec(:);

    % set convergence threshold for the residual || RW x_debias - y ||_2
    tol_debias = tolD * (rvec(:)'*rvec(:));

    % initialize pvec
    pvec = -rvec;

    % main loop
    while cont_debias_cg

        % calculate A*p = Wt * Rt * R * W * pvec
        RWpvec = A(pvec);
        Apvec = AT(RWpvec);

        % mask out the zero terms
        Apvec = Apvec .* zeroind;

        % calculate alpha for CG
        alpha_cg = rTr_cg / (pvec(:)'* Apvec(:));

        % take the step
        x_debias = x_debias + alpha_cg * pvec;
        resid = resid + alpha_cg * RWpvec;
        rvec  = rvec  + alpha_cg * Apvec;

        rTr_cg_plus = rvec(:)'*rvec(:);
        beta_cg = rTr_cg_plus / rTr_cg;
        pvec = -rvec + beta_cg * pvec;

        rTr_cg = rTr_cg_plus;

        iter = iter+1;

        objective(iter) = 0.5*(resid(:)'*resid(:)) + ...
            tau*phi_function(x_debias(:));
        times(iter) = cputime - t0;

        if compute_mse
            err = true - x_debias;
            mses(iter) = (err(:)'*err(:));
        end

        % in the debiasing CG phase, always use convergence criterion
        % based on the residual (this is standard for CG)
        if verbose
            fprintf(1,' Iter = %5d, debias resid = %13.8e, convergence = %8.3e\n', ...
                iter, resid(:)'*resid(:), rTr_cg / tol_debias);
        end
        cont_debias_cg = ...
            (iter-debias_start <= miniter_debias )| ...
            ((rTr_cg > tol_debias) & ...
            (iter-debias_start <= maxiter_debias));

    end
    if verbose
        fprintf(1,'\nFinished the debiasing phase!\nResults:\n')
        fprintf(1,'||A x - y ||_2 = %10.3e\n',resid(:)'*resid(:))
        fprintf(1,'||x||_1 = %10.3e\n',sum(abs(x(:))))
        fprintf(1,'Objective function = %10.3e\n',f);
        nz = (x_debias~=0.0);
        fprintf(1,'Number of non-zero components = %d\n',sum(nz(:)));
        fprintf(1,'CPU time so far = %10.3e\n', times(iter));
        fprintf(1,'\n');
    end
end

if compute_mse
    mses = mses/length(true(:));
end


%--------------------------------------------------------------
% soft for both real and  complex numbers
%--------------------------------------------------------------
function y = soft(x,T)
%y = sign(x).*max(abs(x)-tau,0);
y = max(abs(x) - T, 0);
y = y./(y+T) .* x;

5、TwIST算法测试

        这里测试代码基本与IST测试代码相同,略作修改,对比本人所写的TwIST_Basic、IST_Basic(参见压缩感知重构算法之迭代软阈值(IST))以及官方版本的TwIST: 

  1. clear all;close all;clc;          
  2. M = 64;%观测值个数          
  3. N = 256;%信号x的长度          
  4. K = 10;%信号x的稀疏度          
  5. Index_K = randperm(N);          
  6. x = zeros(N,1);          
  7. x(Index_K(1:K)) = 5*randn(K,1);%x为K稀疏的,且位置是随机的   
  8. %x(Index_K(1:K)) = sign(5*randn(K,1));               
  9. Phi = randn(M,N);%测量矩阵为高斯矩阵      
  10. Phi = orth(Phi’)’;              
  11. sigma = 0.005;        
  12. e = sigma*randn(M,1);      
  13. y = Phi * x + e;%得到观测向量y          
  14. % y = Phi * x;%得到观测向量y   
  15. % lamda = sigma*sqrt(2*log(N));  
  16. lamda = 0.1*max(abs(Phi’*y));  
  17. fprintf(‘\nlamda = %f\n’,lamda);        
  18. %% 恢复重构信号x     
  19. %(1)TwIST_Basic  
  20. fprintf(‘\nTwIST_Basic begin…’);    
  21. tic  
  22. x_r1 = TwIST_Basic(y,Phi,lamda);   
  23. toc    
  24. %Debias  
  25. [xsorted inds] = sort(abs(x_r1), ‘descend’);   
  26. AI = Phi(:,inds(xsorted(:)>1e-3));  
  27. xI = pinv(AI’*AI)*AI’*y;  
  28. x_bias1 = zeros(length(x),1);  
  29. x_bias1(inds(xsorted(:)>1e-3)) = xI;  
  30. %(2)IST_Basic  
  31. fprintf(‘\nIST_Basic begin…’);    
  32. tic  
  33. x_r2 = IST_Basic(y,Phi,lamda);   
  34. toc    
  35. %Debias  
  36. [xsorted inds] = sort(abs(x_r2), ‘descend’);   
  37. AI = Phi(:,inds(xsorted(:)>1e-3));  
  38. xI = pinv(AI’*AI)*AI’*y;  
  39. x_bias2 = zeros(length(x),1);  
  40. x_bias2(inds(xsorted(:)>1e-3)) = xI;  
  41. %(3)TwIST  
  42. fprintf(‘\nTwIST begin…\n’);    
  43. tic  
  44. x_r3 =  TwIST(y,Phi,lamda,’Monotone’,0,’Verbose’,0);   
  45. toc    
  46. %Debias  
  47. [xsorted inds] = sort(abs(x_r3), ‘descend’);   
  48. AI = Phi(:,inds(xsorted(:)>1e-3));  
  49. xI = pinv(AI’*AI)*AI’*y;  
  50. x_bias3 = zeros(length(x),1);  
  51. x_bias3(inds(xsorted(:)>1e-3)) = xI;  
  52. %% 绘图          
  53. figure;          
  54. plot(x_bias1,’k.-‘);%绘出x的恢复信号          
  55. hold on;          
  56. plot(x,’r’);%绘出原信号x          
  57. hold off;          
  58. legend(‘TwIST\_Basic’,’Original’)          
  59. fprintf(‘\n恢复残差(TwIST_Basic):’);          
  60. fprintf(‘%f\n’,norm(x_bias1-x));%恢复残差    
  61. %Debias  
  62. figure;          
  63. plot(x_bias2,’k.-‘);%绘出x的恢复信号          
  64. hold on;          
  65. plot(x,’r’);%绘出原信号x          
  66. hold off;          
  67. legend(‘IST\_Basic’,’Original’)          
  68. fprintf(‘恢复残差(IST_Basic):’);          
  69. fprintf(‘%f\n’,norm(x_bias2-x));%恢复残差    
  70. %Debias1  
  71. figure;          
  72. plot(x_bias3,’k.-‘);%绘出x的恢复信号          
  73. hold on;          
  74. plot(x,’r’);%绘出原信号x          
  75. hold off;          
  76. legend(‘TwIST’,’Original’)          
  77. fprintf(‘恢复残差(TwIST):’);          
  78. fprintf(‘%f\n’,norm(x_bias3-x));%恢复残差    
clear all;close all;clc;        
M = 64;%观测值个数        
N = 256;%信号x的长度        
K = 10;%信号x的稀疏度        
Index_K = randperm(N);        
x = zeros(N,1);        
x(Index_K(1:K)) = 5*randn(K,1);%x为K稀疏的,且位置是随机的 
%x(Index_K(1:K)) = sign(5*randn(K,1));             
Phi = randn(M,N);%测量矩阵为高斯矩阵    
Phi = orth(Phi')';            
sigma = 0.005;      
e = sigma*randn(M,1);    
y = Phi * x + e;%得到观测向量y        
% y = Phi * x;%得到观测向量y 
% lamda = sigma*sqrt(2*log(N));
lamda = 0.1*max(abs(Phi'*y));
fprintf('\nlamda = %f\n',lamda);      
%% 恢复重构信号x   
%(1)TwIST_Basic
fprintf('\nTwIST_Basic begin...');  
tic
x_r1 = TwIST_Basic(y,Phi,lamda); 
toc  
%Debias
[xsorted inds] = sort(abs(x_r1), 'descend'); 
AI = Phi(:,inds(xsorted(:)>1e-3));
xI = pinv(AI'*AI)*AI'*y;
x_bias1 = zeros(length(x),1);
x_bias1(inds(xsorted(:)>1e-3)) = xI;
%(2)IST_Basic
fprintf('\nIST_Basic begin...');  
tic
x_r2 = IST_Basic(y,Phi,lamda); 
toc  
%Debias
[xsorted inds] = sort(abs(x_r2), 'descend'); 
AI = Phi(:,inds(xsorted(:)>1e-3));
xI = pinv(AI'*AI)*AI'*y;
x_bias2 = zeros(length(x),1);
x_bias2(inds(xsorted(:)>1e-3)) = xI;
%(3)TwIST
fprintf('\nTwIST begin...\n');  
tic
x_r3 =  TwIST(y,Phi,lamda,'Monotone',0,'Verbose',0); 
toc  
%Debias
[xsorted inds] = sort(abs(x_r3), 'descend'); 
AI = Phi(:,inds(xsorted(:)>1e-3));
xI = pinv(AI'*AI)*AI'*y;
x_bias3 = zeros(length(x),1);
x_bias3(inds(xsorted(:)>1e-3)) = xI;
%% 绘图        
figure;        
plot(x_bias1,'k.-');%绘出x的恢复信号        
hold on;        
plot(x,'r');%绘出原信号x        
hold off;        
legend('TwIST\_Basic','Original')        
fprintf('\n恢复残差(TwIST_Basic):');        
fprintf('%f\n',norm(x_bias1-x));%恢复残差  
%Debias
figure;        
plot(x_bias2,'k.-');%绘出x的恢复信号        
hold on;        
plot(x,'r');%绘出原信号x        
hold off;        
legend('IST\_Basic','Original')        
fprintf('恢复残差(IST_Basic):');        
fprintf('%f\n',norm(x_bias2-x));%恢复残差  
%Debias1
figure;        
plot(x_bias3,'k.-');%绘出x的恢复信号        
hold on;        
plot(x,'r');%绘出原信号x        
hold off;        
legend('TwIST','Original')        
fprintf('恢复残差(TwIST):');        
fprintf('%f\n',norm(x_bias3-x));%恢复残差  

        运行结果如下:(信号为随机生成,所以每次结果均不一样)

1)图(均为debias之后,参见压缩感知重构算法之迭代软阈值(IST)




2)Command Windows

lamda = 0.224183


TwIST_Basic begin…
abs(f_pre1-f_pre2)/f_pre2<0.010000
TwIST loop is 21
Elapsed time is 0.011497 seconds.


IST_Basic begin…
abs(f-f_pre)/f_pre<0.010000
IST loop is 14
Elapsed time is 0.006397 seconds.


TwIST begin…
Elapsed time is 0.029590 seconds.


恢复残差(TwIST_Basic):0.047943
恢复残差(IST_Basic):4.928160
恢复残差(TwIST):0.047943

注:重构经常失败,运行结果仅为挑了一次重构效果较好的附上;IST有时也可以较好的重构,凑巧这次重构效果不佳。

6、结束语

        从重构结果来看,尤其是Command Windows的输出结果来看,TwIST相比于IST并没有什么优势,这可能是由于我的测试案例十分简单的原因吧。

        另外,谈一下个人对TwIST_Basic函数中第42~44行(或TwIST函数中第490~494行)的理解:这几行很关键,直接影响着能否重构,虽然加上后也经常重构失败(但去掉这几行代码基本无法重构)。个人认为原因是这样的,TwIST容易发散,加上这几行代码后实际是把x非零值的位置依靠IST去决定(因为决定mask的实际是IST迭代公式计算结果),而x迭代则使用TwIST迭代公式。当然,这仅为个人看法。

        最后再说一句,在文中压根就没提“压缩感知”,但由于TwIST可以求解基追踪降噪(BPDN)问题,所以也就可以拿来作为压缩感知重构算法了……

        给出TwIST两位作者的个人主页:

        Jose M. Bioucas Dias:http://www.lx.it.pt/~bioucas/

        MárioA. T. Figueiredo:http://www.lx.it.pt/~mtf/

        凑巧的是在第一作者主页上居然还发现了一个研究生同学,感叹世界好小,哈哈……

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值