稀疏表示與字典學習

參考:
1.稀疏表示:https://www.cnblogs.com/yifdu25/p/8128028.html
2.K-SVD : https://blog.csdn.net/chlele0105/article/details/16886795
3.OMP : https://www.cnblogs.com/yifdu25/p/8385204.html
4.https://www.cnblogs.com/yifdu25/p/8128028.html
5.MP的實例 https://korediantousman.staff.telkomuniversity.ac.id/files/2017/08/main.pdf
6.K-SVD https://www.cnblogs.com/salan668/p/3555871.html
7.OMP與MP算法: https://blog.csdn.net/scucj/article/details/7467955

1. 稀疏表示

稀疏表示(sparse representation)假設自然信號可以被一個字典的原子(基)稀疏的線性組合近似表示。即y≈Dα,這裏yRny∈R^{n}表示信號,αRKα∈R^{K}表示稀疏係數,DRn×KD∈R^{n×K}表示是過完備字典。向量α只具有很少的非0值,這便是稀疏的含義。之所以需要字典,是因爲一般的自然信號x本身並不是稀疏的,往往需要在某種稀疏基上纔可以進行稀疏表示。所以稀疏表示的關鍵是在某種基(字典)下的係數稀疏,而這些字典與圖像本身密切相關,可以將字典看做是組成圖像的基本信息。也就是說在稀疏表示中我們把字典當成一種變換域,在該變換中信號的表示是稀疏的。該問題用公式表述爲:
在這裏插入圖片描述
其中YRn×MY∈R^{n×M}表示樣本矩陣,每一列代表一個patch,M個樣本,D={d1,d2,...dK}Rn×KD=\{d_{1},d_{2},...d_{K}\}∈R^{n×K}表示字典,每一列代表一個原子,K個原子,XRK×MX∈R^{K×M}表示係數矩陣,每一列xix_{i}對應一個樣本在該字典上的係數,ε表示重構誤差。對於表示一個信號使用字典稀疏表示的情況如下。
在這裏插入圖片描述
在這裏,稀疏性表現在xix_{i}的係數大部分都是0,而只有很少的非0值。
由於求解0範數是非凸的問題,而在一定條件下,0範數問題可以轉化爲1範數求解,所以(1)式也可以轉化爲:
在這裏插入圖片描述

1.1 字典的生成方式

通常有2種生成字典的方式,一種基於分析模型(pre-constructed),比如利用傅立葉基,小波基(WT),離散餘弦變換(DCT)基,Gabor基,Contourlet基,等等。依靠這種方法生成的字典結構良好,數值計算快速。但是這種字典具有侷限性,只能表示某種類型的信號,過度依賴於圖像的幾何特徵,並且只有少數圖像塊可以用稀疏的原子組合來表示。另一種基於學習模型,將圖像分成一個個小patch,通過訓練樣本得到字典。由這種方法得到的字典具有很好的適應性,能夠捕捉圖像的幾何特徵。相較於第一種往往表現更好。

1.2 字典的種類

而從字典的形式上看,通俗的說就是從字典的長和寬的對比,字典又可以分成3種:過完備字典(n<K),即原子個數要遠遠大於信號的維度,這種情況在稀疏表示中最常見,完備字典(n=K)例如傅里葉變換和DCT變換都是這種情況和欠完備字典(n>K)[4]。通常我們使用的都是過完備字典。那麼爲什麼通常都要求過完備字典呢?參考別人的說法,如果n<K,這個方程要麼有無窮多個解(當增廣矩陣[D,y]的秩=矩陣[D]的秩時),要麼無解(當增廣矩陣[D,y]的秩>矩陣[D]的秩時)。可能在方程有無窮多解的時候更容易找到更適合的稀疏係數。這大概就是過完備性字典的優點。

1.3 稀疏表示的相關算法

從上面的講解來看稀疏表示其實就是在求解式(1),但由於其中只有Y是已知的,而D和X都是未知的,這裏就涉及到2個問題,1)如何對信號進行稀疏表示,即如何求稀疏係數xix_{i}?2)如何根據樣本生成字典,即如何求解D?概括地說,我們可以使用任何追蹤算法來求解稀疏係數xix_{i},例如MP,OMP(正交匹配追蹤算法),BasisPursuit (BP),FocalUnderdetermined System Solver (FOCUSS)。而更新字典最常用的就是K-SVD算法。

2. 如何稀疏表示

2.1 MP算法

這裏借用[3]的博客的內容來講解MP算法。假設有這樣一個問題:要使用OB,OC,OD來表示OA。這裏OB,OC,OD就相當於字典,OA相當於要稀疏表示的信號。那麼應該如何求解才能達到使用最少的向量近似表示OA呢?答案是每次將OA投影到各個向量上,選擇OA投影最大的那個向量表示原信號會在當前情況下保存信號最多的信息。
在這裏插入圖片描述1)如圖1,將OA向OB,OC,OD分別進行投影,發現OA在OB上的投影最大,這樣OA就被分成投影向量OM和殘差向量MA。假設OMOB=a\frac{OM} {OB} =a,那麼OA=a OB+MA;2)然後繼續對殘差MA進行分解,和第一步一樣將MA向各個向量上投影,如圖2,發現MA在OC向量上的投影最大,則選擇OC來表示MA,並且假設ONOC=b\frac{ON} {OC} =b,此時MA=bOC+NAMA =b*OC+N A^{&#x27;},3)假設此時會有2種情況, [1]發現殘差仍然大於閾值ε,那麼就按照第一步繼續分解,直到殘差小於閾值。[2]發現殘差已經小於閾值了,那麼此時OA=aOB+bOC+NAOA = a*OB +b*OC +NA^{&#x27;}
以上就是追蹤算法MP的思想。稀疏表示記爲OA ≈ a
OB +b*OC 。a,b就相當於係數向量裏面的元素。可以看出如果殘差值可以忽略,則信號OA就是這些原子的線性組合。
那如何使用代碼來實現投影最大呢?也就是如何用代碼尋找最接近原子?又該如何計算殘差呢?

  1. 選擇最接近殘差的原子:MP裏用向量內積定義原子與殘差的距離。也就是殘差與某原子內積最大,即表示殘差在該原子上的投影最大。用R表示殘差,did_{i}表示原子,則每次都在尋找Max[Dist(R,dj)]Max[Dist(R,d_{j})],假設此時最大的原子下標爲did_{i}
  2. 殘差更新:R=R&lt;R,di&gt;diR = R-&lt;R,d_{i}&gt;d_{i};繼續選擇下一個原子,直至收斂。
    使用二維空間上的向量表示該過程。
    在這裏插入圖片描述
    紅色向量r代表當前殘差,綠色向量則表示r投影到d3d_{3}之後的殘差更新。從上圖中也可以看出當前殘差r是直角三角形的斜邊,而新的殘差綠色向量則是一條直角邊。即rk+1&lt;rk|r_{k+1}|&lt;|r_{k}|,所以該算法是收斂的。
    值得注意的有2點,1) MP算法使用的各個原子是歸一化的,即di2=1||d_{i}||^{2}=1。因爲選取max&lt;R,di&gt;max&lt;R,d_{i}&gt;時,如果did_{i}長度不統一,不能得出最好的投影。2) MP算法不是最優的,得到的解是次優解。舉個例子,如果字典中只有兩個向量d1,d2,那麼MP算法會在這兩個向量間交叉迭代投影,也就是f=a1d1+a2d2+a3d1+a4d2+……;可以看到之前投影過的原子方向 d1d_{1},之後還有可能投影。換句話說,MP的方向選擇不是最優的,是次優的。
    理論上說,假設MP算法第k次迭代的結果爲y=i=1kaidi+Rkf=fk+Rkfy = ∑_{i=1}^{k}a_{i}d_{i}+R_{k}f=f_{k}+R_{k}f。由於MP算法僅能保證RkfdkR_{k}f⊥d_{k},所以fkf_{k}一般情況下是次優的。這是什麼意思呢?fkf_{k}是字典中k個原子對y的線性表示,這個組合的值作爲近似值,只有在第k個殘差和fkf_{k}裏所有原子都正交,纔是最優的。如果第k個殘差與fkf_{k}正交,意味着第k個殘差與fkf_{k}的任意一項都線性無關,那麼其在後面的分解中,不可能出現fkf_{k}中已經出現的原子,這纔是最優的。而一般情況下,MP不能滿足這個條件,它一般只能滿足第k個殘差和dkd_{k}正交。也正是因爲MP的這個特點,所以MP算法需要更多次迭代才能收斂。

MP算法流程

算法流程總結如下,需要說明的是這裏使用x表示信號,α表示係數向量。與上面的符號表示略有差異,主要是因爲直接摘抄別人的東西。
在這裏插入圖片描述

2.2 OMP算法

OMP算法即正交的MP算法。MP算法的次最優性來源其殘差只與當前投影方向垂直,這樣在接下來的投影中,因爲殘差與已選到的原子不是線性無關,所以殘差很有可能會再次投影到原來的方向。於是,在投影時,如果使得殘差Rk+1R_{k+1}x1xk+1x_{1}到x_{k+1}(已選到的原子)的所有向量垂直,則可以克服這個問題。這正是OMP算法改進的地方,OMP算法在分解的每一步對所選擇的全部原子進行正交化處理,這使得在精度要求相同的情況下,OMP算法的收斂速度更快。更多信息請參考https://blog.csdn.net/scucj/article/details/7467955

3. 如何生成字典–K-SVD

在進行稀疏表示的時候,我們往往會先初始化一個字典,但是它並不是最優的。常用K-SVD算法對字典進行更新。但是K-SVD算法並不是獨立的,它需要和上面講述的追蹤算法結合在一起使用才能對字典進行更新。需要注意的是,這裏

3.1 稀疏表示

首先要初始化一個字典D,使用該字典對數據進行稀疏表示,得到係數矩陣X。然後把DX看做是D中每列did_{i}與X中每行xix_{i}(在這裏表示X的一行,前面該符號表示X的一列)的乘積,即將DX的結果分片。如前所述D={d1,d2,...dK}Rn×KD=\{d_{1},d_{2},...d_{K}\}∈R^{n×K}表示字典,每一列diRn×1d_{i}∈R^{n×1}代表一個原子,有K個原子,XRK×MX∈R^{K×M}表示係數矩陣,每一行xiR1×Mx_{i}∈R^{1×M}did_{i}xix_{i}相乘的結果也是一個n×M的矩陣。表示該原子在整個重構矩陣中的貢獻。DX分片的結果如下,
在這裏插入圖片描述

3.2 字典更新

由於初始的字典往往並不是最優的,所以需要對初始字典進行更新。而更新的動力就來源於殘差矩陣。K-SVD採用逐列更新字典的方法,通過K次迭代完成一次字典更新。之所以需要K次主要是因爲字典D有K個原子。而小寫k表示每次更新字典所正在操作的原子。具體來說每次都提取出一個原子dkd_{k}對整個重構矩陣DX的影響,因爲缺少了dkd_{k},上述表達式會產生一個"空洞"。K-SVD算法的目的就是如何選擇一個新的原子填補空洞,使得結果更加逼近Y,減小整體誤差。提取出一個原子dkd_{k}的影響之後,當前誤差矩陣如下。
在這裏插入圖片描述
誤差值爲En=EF2E_{n} =||E||_{F}^{2}
正如3.1所述,在開始更新字典之前就已經得到了字典D和其對應的係數矩陣X。言下之意,在更新字典的時候,D,X都是固定的,但因爲重構的結果不好所以要更新。假設此時將要更新的是係數矩陣的xkx_{k}行和字典的dkd_{k}列,則有,
在這裏插入圖片描述
上式中的EkE_{k}是誤差矩陣,對EkE_{k}做SVD分解,得到Ek=UΛVTE_{k}=UΛV^{T},其中U和V的列矢量均是正交基,Λ是對角矩陣。若Λ的對角元素從大到小排列,則表示EkE_{k}的能量分量主軸在相應幾個正交方向上由大到小分配,如此取U的第一個列向量來表示did_{i},取V的第一個列向量與Λ的第一個元素的乘積表示xix_{i},這樣就完成了字典一個條目的更新。
值得注意的是,如果直接用上面的方法來更新xkx_{k}dkd_{k},則會導致xkx_{k}不稀疏,出現"發散"。換句話說,更新之後的xknewx_{knew}與更新dkd_{k}前的xkx_{k}的非零元素所處位置和value不一樣。
那應該如何更新xkx_{k}dkd_{k}
處理方法是在進行SVD分解之前,我們使用如下公式對EkE_{k}xkTx_{k}^{T}進行變換。即只保留係數中的非零值,再進行SVD分解就不會出現這種現象了。
在這裏插入圖片描述
其中ΩRM×WΩ∈R^{M×W},W是xkTx_{k}^{T}中的非零元素個數,M是樣本個數。其實質就是保留xkTx_{k}^{T}中的非零元素,EkE_{k}中只保留dkd_{k}xkTx_{k}^{T}中非零元素乘積後的那些項的貢獻,形成EkRE_{k}^{R}。換句話說,乘以新的矩陣Ω之後的結果就是EkE_{k},xkTx_{k}^{T}去掉0輸入之後的收縮結果。
那如何生成矩陣Ω?定義集合wk={i1iM,xkT(i)0}w_{k}=\{i|1≤i≤M,x_{k}^{T}(i)≠0\}表示xkT(i)0x_{k}^{T}(i)≠0的點的索引。定義Ω爲M×wkM×|w_{k}|矩陣,它在(wk(i),i)(w_{k}(i),i)處值爲1,其餘都是0。
此時對EkRE_{k}^{R}做SVD分解得到EkR=UΔVTE_{k}^{R}=UΔV^{T},按照上面的思路使用U的第一列更新dkd_{k},使用V的第一列和Δ(1,1)的乘積更新xkTx_{k}^{T},這樣更新字典就正確了。

K-SVD算法流程

總得來說,整個字典學習的流程如下。它分爲2個階段,1)對數據使用OMP算法(也可以使用其他算法)進行稀疏表示,得到對應字典的係數矩陣X。2) 依據得到係數矩陣X,根據K-SVD算法對字典逐列進行更新,同時也對係數矩陣進行更新,經過K次迭代完成一次字典更新。直到算法收斂。下面是K-SVD算法的流程。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章