字典学习(KSVD)详解

关于字典学习

对于一个事物,我们如何表征它呢?很明显,这个事物是有特征的,或者说,这个事物它是由许多个不同的特征经过一定的组合而形成的。字典学习的目标是提取实物的最本质特征。用字典来表征该事物的特征。
当提取出了事物的特征,这就相当于一种降维。
对于如何理解字典学习,我想到这样一个例子,比如一堆三维向量,找寻它们的特征,实际上,我们可以用三维直角坐标系(x,y,z三个单位向量)来表征它们,这三个向量通过组合可以表示所有的三维向量,它们就是我们的字典,再搭配上每个三维向量的x,y,z组合方式(稀疏编码),也就可以还原成那一堆三维向量了。

SVD

在理解KSVD之前,首先需要了解的是SVD(奇异值分解)。学习过矩阵理论的同学对SVD肯定是不陌生的。
在了解奇异值分解之前,需要了解一下特征值分解。所谓特征值分解,是为了提取出一个矩阵的特征。特征值,特征向量。这都是我们老生常谈的问题了。这里对于一个方阵 A A A,我们又这样的定义: A x = λ x Ax=\lambda x Ax=λx,其中 λ \lambda λ A A A的特征值, x x x就是我们 A A A的对应 λ \lambda λ的特征向量。当矩阵可以相似对角化时,矩阵 A A A便可以被分解为: A = Q Λ Q − 1 A=Q\Lambda Q^{-1} A=QΛQ1。其中 Q Q Q是矩阵 A A A的特征向量组成的矩阵, Λ \Lambda Λ是一个对角阵,其对角线上的元素是 A A A的特征值。
一个矩阵其实就是一个线性变换,当我们将矩阵成以向量之后,其实就是对这个向量进行了线性变换。对应我们的特征值分解,分解的 Λ \Lambda Λ矩阵是一个对角阵,我们将其中的特征值从大到小排列,这些特征值对应的特征向量就是描述这个矩阵从主要到次要的变化方向。通过特征值分解得到前N个特征向量,那么就对应了这个矩阵最主要的N个变化方向。利用这前N个变化方向,我们就可以近似矩阵,也就是提取这个矩阵的特征。总的来说,特征向量表示特征,特征值表示特征的重要程度,可以把它在应用中当做权重。这种分解方法很好,但是也有特别明显的局限性,那就是它只适合方阵。
所以下面就要引出更适合一般矩阵的分解方式。也就是奇异值分解方法。我们在课上学过,这里我们设矩阵 A A A m ∗ n m*n mn的。奇异值分解形式为: A = U Σ V T A=U\Sigma V^{T} A=UΣVT。其中 U U U是一个 m ∗ m m*m mm的酉矩阵,其里面的向量是相互正交的,我们称它们为做左奇异向量; Σ \Sigma Σ是一个 n ∗ m n*m nm的矩阵,只有对角线上的元素非零,这些值就是我们的奇异值, V T V^{T} VT是一个 n ∗ n n*n nn的矩阵,和一样,它也是酉矩阵,里面的向量也是互相正交的,称为右奇异向量。我们将矩阵 A A A的转置乘上它自己,便会得到一个方阵,用这个方阵来求特征值: A T A v i = λ i v i A^{T}Av_{i}=\lambda_{i}v_{i} ATAvi=λivi。这里的 v i v_{i} vi就是右奇异向量, σ i = λ i \sigma_{i}=\sqrt{\lambda_{i}} σi=λi u i = A v i σ i u_{i}=\frac{Av_{i}}{\sigma_{i}} ui=σiAvi,同理 v i v_{i} vi是我们的左奇异向量。我们这里的 σ \sigma σ就是奇异值。在矩阵中,我们让它以从小到大的顺序排列。在大多数情况下,我们会得到很好的结果,就是少部分的奇异值的和占了全部奇异值的和的大多数,那么我们就可以用前 t t t个奇异值来近似的描述矩阵。
对于一个矩阵,我们可以选取 U U U的前 t t t列, Σ \Sigma Σ的前 t t t个奇异值, V T V_{T} VT的前 t t t行,它们分别相乘累加的结果就可以近似表示我们的 A A A矩阵,这不仅是一种近似,也相当于一种降维。

字典学习

字典学习主要是将原始样本 Y Y Y给分解中字典矩阵 D D D和稀疏码矩阵 X X X,这里的稀疏码 X X X自然是十分稀疏,数据量比较少。字典 D D D里便存储了原始样本 Y Y Y中的特征,而稀疏码则是用表示原始样本使用特征来组合成自己的方式。
理想情况是 Y m ∗ n = D m ∗ s ∗ X s ∗ n Y_{m*n}=D_{m*s}*X_{s*n} Ymn=DmsXsn,当 s s s远小于 m m m n n n时, D D D X X X的维度会远低于原来的 Y Y Y。当我们把矩阵 X s ∗ n X_{s*n} Xsn的看做列向量形式 ( x 1 , x 2 . . . x n ) (x_{1},x_{2}...x_{n}) (x1,x2...xn),然后 Y = D ∗ ( x 1 , x 2 . . . x n ) = D ∗ x 1 + D ∗ x 2 + . . . + D ∗ x n Y=D*(x_{1},x_{2}...x_{n})=D*x_{1}+D*x_{2}+...+D*x_{n} Y=D(x1,x2...xn)=Dx1+Dx2+...+Dxn,这里 D ∗ x i D*x_{i} Dxi就是Y中的第 i i i列向量,我们可以用一个示意图来理解。
字典学习(KSVD)详解_第1张图片
(图片来源Network Sparse Representation: Decomposition, Dimensionality-Reduction and Reconstruction)

求解过程

为了得到 D D D X X X,这里需要进行求解。这里提出一个优化问题:
m i n D , X ∥ Y − D X ∥ F 2 , s . t . ∀ i , ∥ x i ∥ 0 ≤ ε min_{D,X}\left\|Y-DX\right\|^{2} _{F} ,s.t. \forall i, \left\|x_{i}\right\|_{0} \leq \varepsilon minD,XYDXF2,s.t.i,xi0ε
该优化问题就是在约束条件 x i x_{i} xi的零范数尽量小的情况下,原矩阵与分解的字典矩阵和稀疏码矩阵乘积的差值的矩阵二范数最小,此时的的字典矩阵 D D D和稀疏码矩阵 X X X是多少。

说白了就是,稀疏码矩阵比较稀疏的情况下,追求 Y Y Y D X DX DX差值最小(可以以通过 D X DX DX来还原出 Y Y Y),求 D D D X X X。(这里可以把目标函数和约束函数调换位置求解,本质上没有什么区别,只是这一种更容易理解)
然后就是如何求解这个优化问题了,这里的求解思路是对字典矩阵的每一列和稀疏码矩阵的每一行来进行更新,多次迭代,从而最终实现 D D D X X X的求解。

这里假设是在迭代过程中的某一步,字典矩阵和稀疏矩阵都是有的,只是还不是最终结果。那么此时假设要更新的是字典的第i列和稀疏矩阵的第i行。优化目标公式是上面提到过的 m i n D , X ∥ Y − D X ∥ F min_{D,X}\left\|Y-DX\right\| _{F} minD,XYDXF,这里需要对该公式进行变形,首先将 D X DX DX写成列向量乘以行向量形式(为什么这样写呢,因为我们这里要更新的就是字典的第i列和稀疏矩阵的第i行)。从而,优化目标公式变成了 m i n D , X ∥ Y − ∑ j = 1 s d j x j ∥ F min_{D,X}\left\|Y-\sum ^{s}_{j=1}d_{j}x_{j}\right\| _{F} minD,XYj=1sdjxjF,然后将要更新的 d i , x i d_{i},x_{i} di,xi抽取出来,公式变成了 m i n D , X ∥ Y − ∑ j = 1 , j ≠ i s d j x j − d i x i ∥ F min_{D,X}\left\|Y-\sum ^{s}_{j=1,j\neq i}d_{j}x_{j}-d_{i}x_{i}\right\| _{F} minD,XYj=1,j=isdjxjdixiF,此时将前面两项合并,则就得到了这样一个式子 m i n D , X ∥ E i − d i x i ∥ F min_{D,X}\left\|E_{i}-d_{i}x_{i}\right\| _{F} minD,XEidixiF,此时优化问题就变成了这个。来分析一下这个式子,首先 E i E_{i} Ei是一个矩阵, d i , x i d_{i},x_{i} di,xi也是一个矩阵,它们是同维度的;然后 E i E_{i} Ei是和 d i , x i d_{i},x_{i} di,xi毫不相关的,因为它并没有计算有关 i i i的值。
这里我们可以这样理解: D X DX DX是字典矩阵乘以稀疏码矩阵,就是我们恢复的结果,那么 Y − D X Y-DX YDX就是原始矩阵与我们恢复矩阵的误差。而这个误差项再减去 d i , x i d_{i},x_{i} di,xi就是不考虑字典矩阵第 i i i行和稀疏码矩阵第 i i i行的误差。当执行更新字典矩阵第 i i i行和稀疏码矩阵第 i i i行时,更新的标准是,用新的 d i , x i d_{i},x_{i} di,xi去弥补其他行列造成的误差。(有点贪心的感觉)

这里的 E i E_{i} Ei是很好算的,直接 Y − ∑ j = 1 , j ≠ i s d j x j Y-\sum ^{s}_{j=1,j\neq i}d_{j}x_{j} Yj=1,j=isdjxj即可求得。不过这里还没这么简单,用于我们要进行多次迭代,有一个问题出现了,你如何保证稀疏码第 i i i行很稀疏呢(很多0呢),当你更新了字典矩阵第 i i i行和稀疏码矩阵第 i i i行,然后继续往后更新,进入下一次大的迭代,然后再来更新稀疏码矩阵第 i i i行,此时的 E i E_{i} Ei都不一样了,此时,你完全无法控制第 i i i行的稀疏情况,有可能会更稀疏,有可能会不变,有可能会更稠密,这是完全不可控的。
所以在这里,要进行一个操作,就是根据之前的 x i x_{i} xi的情况,将 x i x_{i} xi中非零元素提取出来形成新的行向量 x i ′ {x_{i}'} xi,然后将 x i x_{i} xi非零元素与 E i E_{i} Ei对应的列提取出来形成新的误差矩阵 E i ′ {E_{i}}' Ei,显然, E i ′ {E_{i}}' Ei的维度和 d i x i ′ d_{i}{x_{i}'} dixi的维度还是一致的。这里给出一个示意图:
字典学习(KSVD)详解_第2张图片
(图片来源于https://www.cnblogs.com/endlesscoding/p/10090866.html,其中 E k E_{k} Ek就是本文中的 E i E_{i} Ei,)
然后我们的优化目标公式就变成了 m i n D , X ∥ E i ′ − d i x i ′ ∥ F 2 min_{D,X}\left\|{E_{i}}'-d_{i}{x_{i}}'\right\|^{2} _{F} minD,XEidixiF2,对这个式子进行求解。
这个步骤的意义在于什么呢?在更新稀疏码第 i i i行时,选择继承之前该行稀疏码的稀疏性,本次更新我们只更新这个稀疏码的非零元素。这样就保证了一个什么问题呢,就是之前是零的元素在更新之后一定还是零,之前非零的元素呢,这就不好说,可能继续非零,也可能为零,这要取决于计算结果。
总之,这里提取非零元素与非零列,就保证了稀疏码只会朝着不变或者更稀疏的方向发展,而不会更稠密。然而,这也是有问题的,你只更新非零元素,虽然提取除了 E i ′ {E_{i}}' Ei,但它和 E i E_{i} Ei,是不一样的,无论你最后求得的 d i x i ′ d_{i}{x_{i}}' dixi有多么解决 E i ; ′ {E_{i}};' Ei;,它和 E i E_{i} Ei的误差始终存在,无法解决。这就是保证了稀疏性,而损失了准确性,只能寄希望靠更多的迭代次数去弥补。

之后就是来求解 m i n D , X ∥ E i ′ − d i x i ′ ∥ F 2 min_{D,X}\left\|{E_{i}}'-d_{i}{x_{i}}'\right\|^{2} _{F} minD,XEidixiF2,这是一个最小二乘问题,也就是你只能找 d i , x i ′ d_{i},{x_{i}}' di,xi去逼近 E i ′ {E_{i}}' Ei,而无法直接求出其结果。这里就采用SVD(奇异值分解,前面讲的终于派上用场了)来求解。
求解的步骤就是将 E i ′ {E_{i}}' Ei进行奇异值分解,得到 E i ′ = U Σ V T {E_{i}}'=U\Sigma V^{T} Ei=UΣVT,然后取 U U U的第一列作为新的 d i d_{i} di,而 Σ V T \Sigma V^{T} ΣVT乘积结果的第一行作为新的 x i ′ {x_{i}}' xi(其实就是 Σ \Sigma Σ的主对角线第一个元素乘以 V T V^{T} VT的i第一行(这里 Σ \Sigma Σ中的奇异值按从大到小顺序来排列))。
至于为什么这样取呢?这在矩阵理论中是叫做秩一逼近。对于 E i ′ = U Σ V T {E_{i}}'=U\Sigma V^{T} Ei=UΣVT,我们可以将其表示如下 E i ′ = U Σ V T = σ 1 u 1 v 1 T + . . . + σ k u k v k T {E_{i}}'=U\Sigma V^{T}=\sigma_{1}u_{1}v_{1}^{T}+...+\sigma_{k}u_{k}v_{k}^{T} Ei=UΣVT=σ1u1v1T+...+σkukvkT,即分解成k个小矩阵,它们分别是 U U U的第 i i i行和 Σ \Sigma Σ的第 i i i个奇异值和 V T V^{T} VT的第 i i i个列向量的成绩,它们是同维度的矩阵。
同时因为奇异值分解的性质, u 1 , u 2 . . . u m u_{1},u_{2}...u_{m} u1,u2...um是相互正交的,同样, v 1 , v 2 . . . v n v_{1},v_{2}...v_{n} v1,v2...vn是相互正交的,所以我们在计算 E i {E_{i}} Ei F F F范数的平方时,便会有这样一个结果 ∥ E i ′ ∥ F 2 = σ 1 2 ∥ u 1 v 1 T ∥ + . . . σ k 2 ∥ u k v k T ∥ = σ 1 2 + . . . σ k 2 \left\|{E_{i}}' \right\|^{2}_{F} =\sigma^{2}_{1}\left\|u_{1}v^{T}_{1}\right\|+...\sigma^{2}_{k}\left\|u_{k}v^{T}_{k}\right\|=\sigma^{2}_{1}+...\sigma^{2}_{k} EiF2=σ12u1v1T+...σk2ukvkT=σ12+...σk2,可以得到这样一个结果,因为 Σ \Sigma Σ中的奇异值是从大到小排列,而 σ 1 2 \sigma^{2}_{1} σ12占据了 ∥ E i ′ ∥ F 2 \left\|{E_{i}}' \right\|^{2}_{F} EiF2的大部分能量,所以用第一个小矩阵来近似原矩阵会让误差尽可能小,这样也能达到比较好的逼近效果。同时,这个小矩阵已经为我们分解好了 u k v k T u_{k}v^{T}_{k} ukvkT,所以我们选择这样的方式来进行求解。

至此,以上便是求解的全部过程。

不过还存在一个问题,就是我们假设更新时建立在字典和稀疏码已经存在情况下,那么第一次迭代时字典怎么办呢。我们可以采用对原始矩阵直接进行奇异值分解,取左歧义矩阵的前 k k k列作为字典,而稀疏码甚至可以选择全是1的矩阵,一开始误差较大,反正迭代次数够的话也是可以解决的。

参考资料

本文是我阅读了部分博客之后写的,其中KSVD的核心就在于它的对每行每列进行更新的方式上,求解其实并不是重点,由于数学基础薄弱,所以写的比较啰嗦,但是希望能让自己和看博客的朋友弄懂。
本文主要参考了
https://www.cnblogs.com/endlesscoding/p/10090866.html
我是看这篇博客看懂的,不过还是推了好半天,然后结合自己的理解进行阐述。同时,还参考了
https://blog.csdn.net/jzz3933/article/details/90599816

你可能感兴趣的:(个人日记)