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

来源:互联网 发布:思迅会计软件 编辑:程序博客网 时间:2024/06/07 02:23

题目: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代码,方便理解:

[plain] view plain copy
print?
  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行,即:

[plain] view plain copy
print?
  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)

[plain] view plain copy
print?
  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 variablesfor_ever = 1;% maj_max_sv: majorizer for the maximum singular value of operator Amax_svd = 1;% Set the defaults for outputs that may not be computeddebias_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));endif  beta == 0     beta  = alpha*2/(lam1+lamN);endif (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 casesif ~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 lotAty = AT(y);% if phi was given, check to see if it is a handle and that it % accepts two argumentsif 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']);   endelse %if nothing was given, use soft thresholding   psi_function = @(x,tau) soft(x,tau);end% if psi exists, phi must also existif (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']);    endelse  % 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 xif prod(size(tau)) > 1   try,      dummy = x.*tau;   catch,      error(['Parameter tau has wrong dimensions; it should be scalar or size(x)']),   endend% if the true x was given, check its sizeif 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 vectorif 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   endend% define the indicator vector or matrix of nonzeros in xnz_x = (x ~= 0.0);num_nz_x = sum(nz_x(:));% Compute and store initial value of the objective functionresid =  y-A(x);prev_f = 0.5*(resid(:)'*resid(:)) + tau*phi_function(x);% start the clockt0 = cputime;times(1) = cputime - t0;objective(1) = prev_f;if compute_mse   mses(1) = sum(sum((x-true).^2));endcont_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 iterationsIST_iters = 0;TwIST_iters = 0;% initializexm2=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    endend%--------------------------------------------------------------% end of the main loop%--------------------------------------------------------------% Printout resultsif 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');    endendif 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: 

[plain] view plain copy
print?
  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_Basicfprintf('\nTwIST_Basic begin...');  ticx_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_Basicfprintf('\nIST_Basic begin...');  ticx_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)TwISTfprintf('\nTwIST begin...\n');  ticx_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));%恢复残差  %Debiasfigure;        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));%恢复残差  %Debias1figure;        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/

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

原创粉丝点击