TwIST算法MALTLAB主程序詳解
關于TwIST算法的具體原理可以參考:
鏈接: https://ieeexplore.ieee.org/abstract/document/4358846
鏈接: https://blog.csdn.net/jbb0523/article/details/52193209
該算法的MATLAB源代碼:
鏈接: http://www.lx.it.pt/~bioucas/TwIST/TwIST.htm
1. 函數定義與輸入輸出變量
主函數的定義如下所示,TwIST包含7個輸出變量和若干個輸入變量,其中包含3個必需輸入變量和若干個可選輸入變量(varargin)。具體每個變量的含義可以參考MATLAB TwIST.m文件中的解釋。下文僅對一些關鍵參數進行解釋。
function [x,x_debias,objective,times,debias_start,mses,max_svd] = ...TwIST(y,A,tau,varargin)
該算法主要解決如下正則化問題:
arg min_x = 0.5*|| y - A x ||_2^2 + tau phi( x )
也就是論文中式(1)所示,注意在MATLAB代碼中存在一些符號表示的改變。如K?A,λ?tau等。
其具體的迭代公式如原論文中式(17)-(19)所示
從式(17)-(19)中看,我們需要 x 0 , α , β , y , K , Ψ λ x_{0},\alpha,\beta,y,K,\Psi_{\lambda} x0?,α,β,y,K,Ψλ?等一系列參數,上述迭代公式方可正確運行。針對算法,輸出變量中x即為目標的估計值,x_debias為目標估計值的去偏結果,獲得這一結果往往需要在主循環迭代結束后,通過適當的去偏迭代,消除正則化器造成的一些偏差。
輸入變量 | 含義 |
---|---|
y | 測量結果,可以為1為向量或者二維數組 |
A | 對應原論文中的K |
tau | 正則化參數,對應原論文中的λ |
Psi | 去噪函數句柄,對應原論文中的去噪函數ψ |
Phi | 正則化器的函數句柄,對應原論文中的Φ |
lambda | TwIST算法的lam1參數,對應原論文中的 λ 1 \lambda_{1} λ1?參數,論文中的 λ N \lambda_{N} λN?在程序中被設置為常數1 |
alpha | TwIST的alpha參數 (詳見論文式 (22)) |
beta | TwIST的beta參數 (詳見論文式 (23)) |
2.算法主要步驟
TwIST.m的代碼很長,但主要包含的內容并不多。下文主要對在代碼中關鍵部分進行解釋。按照從前往后的順序,主要包含了以下幾個內容:
(1)變量注釋。
這一部分對函數的每一個變量都進行了注釋,包括必須變量和可選變量。建議按照以上迭代公式了解關鍵參數的含義。
(2)變量設定。
這一部分主要在變量注釋和初始化兩部分之間。
主要定義了
- 各個變量的默認值。
- 使用一個switch-case分支語句讀取varargin所代表的可選輸入參數,實現可選變量的自定義功能。
- 對主要變量,如alpha和beta進行設定。對于這個部分,多說一點。如原論文中所示
實際上存在如下關系:
0 < ξ 1 ≤ λ 1 < λ N ≤ ξ m , ξ  ̄ m ≡ m a x ( 1 , ξ m ) 0< \xi_{1} ≤ \lambda_{1} < \lambda_{N} ≤ \xi_{m} , \overline{\xi}_{m}≡max(1,\xi_{m}) 0<ξ1?≤λ1?<λN?≤ξm?,ξ?m?≡max(1,ξm?)
而在程序中,作者直接用 λ 1 \lambda_{1} λ1?表示了 ξ 1 \xi_{1} ξ1?,同時設定 ξ m \xi_{m} ξm?為 λ N = 1 \lambda_{N}=1 λN?=1。雖然可能有點誤差,不過我覺得無可厚非。
關于函數句柄,需要注意的是x在這里并不是只迭代的解x,而是一個指代未知變量的參數,如下面的AT(y)中的y。
if ~isa(A, 'function_handle')AT = @(x) A'*x;A = @(x) A*x;
endAty = AT(y);
(3)初始化。
初始化主要實現了 x 0 x_{0} x0?的設置方法,驗證了phi(x)和psi(x)函數是否有效,以及其他一些變量的初始設置。
(4)TwIST主循環迭代。
這一部分是整個代碼中最主要的部分。
TwIST算法的迭代包含兩個主要部分:TwIST迭代和IST迭代。IST_iters和TwIST_iters的值用于確定當前應該執行哪一種迭代。根據條件判斷,當TwIST_iters達到特定閾值或滿足特定條件時,會切換到執行IST迭代,而不是繼續TwIST迭代;反之亦然。
這一部分主要包含2個while循環,兩個while循環會一直運行,直到滿足對應條件。
在第二個while循環中有一個 if-else結構,用于判斷進行何種操作。在TwIST循環中,IST_iters和TwIST_iters并不會一直增加,而只是一個判斷flag,結合對應的if else,完成判斷。迭代次數的增加實際上由iter控制。
建議在主循環設置斷點,并將IST_iters和TwIST_iters后邊的分號去掉,使用demo進行調試。觀察IST_iters和TwIST_iters的值變化。這樣,IST_iters和TwIST_iters取什么值執行什么語句就一清二楚了。
去噪函數的作用
此外,在主循環中,還有一行比較重要。它解決了這樣一個問題:原論文中的迭代公式中并沒有psi去噪函數這樣一個變量,那它在程序中到底起到了什么作用呢?
x = psi_function(xm1 + grad/max_svd,tau/max_svd);
代碼中其他位置的psi_function只是傳參或者驗證,而該位置的psi_function是起到了實質作用的。psi_function主要用于執行閾值或收縮操作,通常涉及對給定向量或信號進行閾值處理。它可能采用軟閾值(soft thresholding)或硬閾值(hard thresholding)等技術,用于將信號的幅度調整為零或接近零,從而產生更稀疏的表示。
稀疏性操作
if sparsemask = (x ~= 0);xm1 = xm1.* mask;xm2 = xm2.* mask;end
以上代碼是處理稀疏性的操作。當 sparse 變量為真時(即 sparse 變量為非零值),代碼會執行以下操作:
- 首先,創建一個邏輯掩碼 mask,該掩碼用于標識變量 x 中非零元素的位置。也就是說,mask 的元素為 1 表示對應 x 中的元素不為零,為 0 表示對應 x 中的元素為零。
- 然后,通過將 xm1 和 xm2 分別與 mask 相乘,將 xm1 和 xm2 中對應于 x 中零元素位置的部分置為零。
- 這樣可以確保在算法的迭代過程中,對 x 的更新僅在非零位置進行,以保持其稀疏性。
(5)去偏。
在主循環之后,還有一個去偏階段(debias phase)。這是一個可選操作,作者給出的解釋是 :
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.
可見,這一部分主要是為了消除l1懲罰的偏差。