应用场景
K-means算法多用于聚类
K-SVD算法则可用于压缩,编码,聚类等
稀疏表示
用较少的基本信号的线性组合来表达大部分或者全部的原始信号。
每个矩阵的列向量可看成一个信号,一个矩阵则是信号的集合。
其中, 基本信号可成为原子信号。
设矩阵Y为样本集,由N个样本组成,每个样本由n个特征表示,即Y的尺寸为(n * N)。
所谓稀疏表示,就是找到一组向量基(一组原子信号),将此组向量基进行线性组合类表示矩阵(样本集)。
Y
=
D
X
Y = DX
Y=DX

这里的 D D D是 n ∗ K n*K n∗K的矩阵,称为字典, D D D是由 K K K个 n n n维原子组成。且 n < < P n<<P n<<P,此字典称为超完备字典。
X X X由N个k维系数向量组成。N对应样本个数。k对应字典个数。
主要目标
寻找最佳的字典
D
D
D,同时使
X
X
X系数矩阵达到稀疏最大。系数矩阵中,0元素越多,越稀疏,即目标是用更少的原子线性组合来逼近原始矩阵。我这里系数矩阵指的是待优化的稀疏矩阵。
即
m
i
n
∥
X
∥
0
min\parallel X \parallel_0
min∥X∥0
s
.
t
.
Y
=
D
X
s.t.Y = DX
s.t.Y=DX
K-means算法
K-means算法可以看做是K-SVD的简单版,同样可以理解K-SVD是K-means算法的衍生版本。K-means算法中X类似one-hot形式,X中的每个列向量中只有一项不为0,其余均为0,即,每个样本只由一个原子逼近。此处是逼近,并不能等于。
K-means实现方法:
- 在样本集中随机挑选k个样本作为质心,即随机初始化k个原子,此步骤可视为字典的初始化。
- 通过计算样本与质心之间的距离,样本类别化为最近的质心所对应的类别,就是,离谁近,则化为谁的类。此步骤可视为稀疏矩阵的初始化,只不过对应系数矩阵的每一列只有一项不为0,其余均为0,不为0的一项的索引便是我们样本对应的类别。
- 通过划分好的类别来重新计算每类样本的质心。此步便是原子矩阵的优化。
- 根据新计算得来的质心重新分类(原子矩阵,即字典的每个列向量则可看做是一个质心)。此步便是稀疏矩阵的优化。
- 直至两步质心(原子矩阵)相差少于规定的阈值,便停止优化。
K-SVD算法原理
K-means主要通过计算距离来分类,并不是利用
D
X
DX
DX来十分逼近原样本矩阵
Y
Y
Y,从而主要用于聚类,而K-SVD则由一系列原子来线性组合逼近,因此相比K-means更适用于压缩,编码等应用。
同样。K-SVD算法也分两步:字典的优化及系数矩阵的优化。
K-SVD算法步骤
K-SVD算法也分两步:字典的优化及系数矩阵的优化。优化系统矩阵时,字典固定,优化字典时,系数矩阵同时跟着优化。
- 同K-means算法一样,在样本集中随机挑选K个样本形成原子矩阵,并初始化系数矩阵全为0.
- 固定字典,优化系数矩阵(求取样本集对应该字典的稀疏编码)
设样本集中的一个样本向量 y y y,设原子矩阵中的原子个数为4,令 D = [ d 1 , d 2 , d 3 , d 4 ] D = [d1, d2, d3, d4] D=[d1,d2,d3,d4],求对应的系数向量 x x x,使得 D x ≈ y Dx \approx y Dx≈y,使用此方法从而的整个系数矩阵
系数矩阵计算方法:
(1) 计算D中所有原子与y的点积,求取点积结果中的最大值对应的原子d。两个向量的点积越大,则表示两个向量方向更为接近,即两个向量之间的夹角越小。
(2) 设 d 2 ⋅ y d2 \cdot y d2⋅y的值最大,则将 d 2 d2 d2作为第一个原子向量,则 y y y对应的系数向量 x = ( 0 , b , 0 , 0 ) x = (0, b, 0, 0) x=(0,b,0,0), b b b为待求取参数。
(3) 求解系数b: y − b ⋅ d 2 = 0 y - b \cdot d2 = 0 y−b⋅d2=0利用最小二乘法计算系数b。
这里介绍两个概念:
超定方程是指未知数小于方程个数的方程。
此方程参数只有一个 b b b,因此也属于超定方程。
最小二乘法也称最小平方法,将无解方程,转化为求取距离最小的方程,即将 X β = y X\beta = y Xβ=y转化为求 m i n S ( β ) = ∥ X β − y ∥ 2 min S(\beta) = \parallel X\beta - y\parallel^2 minS(β)=∥Xβ−y∥2,详细最小二乘法参考百度百科最小二乘法
(4) 利用以上得到的原子向量及系数向量,计算残差向量:
y
′
=
y
−
b
⋅
d
2
y' = y - b \cdot d2
y′=y−b⋅d2。
如果残差向量小于误差阈值
ε
\varepsilon
ε,则结束系数矩阵的优化计算,若不满足,则进入下一步计算。
(5) 计算字典中除
d
2
d2
d2剩余原子向量与残差向量
y
′
y'
y′的方向最接近的原子向量,即计算剩余原子向量中与残差向量的点积最大的原子向量。本例中如下:
d
1
⋅
y
′
,
d
3
⋅
y
′
,
d
4
⋅
y
′
d1 \cdot y', d3 \cdot y', d4 \cdot y'
d1⋅y′,d3⋅y′,d4⋅y′得到最大值随影的原子向量d,假设
d
3
⋅
y
′
d3 \cdot y'
d3⋅y′最大, 那么则将系数矩阵更新为:
x
=
(
0
,
b
,
c
,
0
)
x = (0, b, c, 0)
x=(0,b,c,0) 其中b、c是未知参数。
(6) 求解系数b、c,同样为超定方程:
y
−
b
⋅
d
2
−
c
⋅
d
3
=
0
y - b \cdot d2 - c \cdot d3 = 0
y−b⋅d2−c⋅d3=0再利用最小二乘法,求得b、c。
(7) 更新残差向量
y
′
=
y
−
b
⋅
d
2
−
c
⋅
d
3
y' = y - b \cdot d2 - c \cdot d3
y′=y−b⋅d2−c⋅d3,如果y’的模长满足阈值范围,那么就结束,否则就继续循环,就这样一直循环下去。
3. 字典优化,同时更新系数矩阵
更新字典,采用逐列更新原子向量的方法来更新。
将原子向量的作用进行分解,即:
D
X
=
∑
i
=
1
K
d
i
x
i
DX = \sum_{i=1}^Kd_ix_i
DX=i=1∑Kdixi
d
i
d_i
di则表示原子矩阵
D
D
D中的第
i
i
i个原子向量,
x
i
x_i
xi则表示
X
X
X的第
i
i
i行。
对于 D X DX DX的两种理解:
D D D由K个基本原子向量构成,将系数矩阵按列拆解称N个系数向量,N对应样本个数。
系数矩阵 X X X,按列拆解,每一列对应样本矩阵中的每一列,即一个系数向量对应一个样本向量。系数向量的各维对应字典的个数。 y = D ⋅ x y = D \cdot x y=D⋅x,其中 y y y为一个样本(样本矩阵中其中一列), x x x为系数矩阵中的其中一列,即字典中原子向量的线性组合逼近一个个样本。
系数矩阵按行拆解,每一行对应原子矩阵中的每一列,即系数矩阵的每一行对应字典中的一个原子。 d i x i , 0 < = i < = k − 1 d_ix_i, 0<=i<=k-1 dixi,0<=i<=k−1则表示一个原子向量 d i d_i di对整个样本矩阵的影响。 Y ≈ D X = ∑ i = 1 K d i x i Y\approx DX = \sum_{i=1}^Kd_ix_i Y≈DX=∑i=1Kdixi
初始化字典是随机抽取样本作为字典,且本身字典的行数小于列数,因此存在一些重复,所以整体误差
E
=
Y
−
D
X
E = Y - DX
E=Y−DX仍需要进一步优化。
K-SVD采取的字典更新算法是,对原子向量进行逐个更新。算法原理:
(1) 剥离字典中第k个原子向量对
D
K
DK
DK的贡献,如果不计入第k个原子向量的贡献,则误差矩阵为:
E
k
=
Y
−
∑
i
≠
k
d
i
x
i
E_k = Y - \sum_{i \neq k}d_ix_i
Ek=Y−i̸=k∑dixi然后优化
d
k
,
x
k
d_k, x_k
dk,xk,使得
E
k
E_k
Ek最小。即使
d
k
x
k
≈
E
k
d_kx_k\approx E_k
dkxk≈Ek。
注意此处
d
k
x
k
d_kx_k
dkxk是一个列向量乘以一个行向量,
x
k
x_k
xk是系数矩阵的行,而非列向量。
(2) 去除
E
k
E_k
Ek中对应
x
k
x_k
xk为0项对应的部分。
- 这种做法优点:
很大部分的减少 E k E_k Ek的大小,简化计算;
使优化后系数X中的为零项仍旧为0,保证稀疏性。
- 具体做法:
设对 d k d_k dk进行优化, d k d_k dk对应系数矩阵的第k行,记为 x k x_k xk,系数矩阵 X X X的列对应的样本矩阵 Y Y Y及误差矩阵 E E E的列。因此,想要去掉 d k d_k dk对应的 x k x_k xk为0项对应误差矩阵 E k E_k Ek中的部分(去掉没有受 d k d_k dk影响的误差列,即 d k d_k dk不参与该列的线性逼近),就去掉 E k E_k Ek对应的 x k x_k xk中等于0的列。即提取 E k E_k Ek对应的列。
初始化一个矩阵 Ω \Omega Ω,设要提取 E k E_k Ek的第1,2,5列,则令 Ω \Omega Ω= [[1 0 0 … 0] [0 1 0 … 0] [0 0 0 0 1 0 … 0]]的转置。 Ω \Omega Ω的(0,0), (1,1), (3,4)为1,其余困为0。
(3) 对 E k E_k Ek进行SVD分解,即 E k = U Δ V T E_k = U\Delta V^T Ek=UΔVT,令 U U U的第一列为 d k d_k dk的优化值, V V V的第一列( V T 的 第 一 行 V^T的第一行 VT的第一行)乘以第一个奇异值即 Δ [ 0 , 0 ] \Delta[0, 0] Δ[0,0]作为 x k x_k xk的优化值。这里 Δ [ 0 , 0 ] \Delta[0, 0] Δ[0,0]为一个常数,而非向量。关于SVD分解可以参考SVD分解
(4) 在所有原子向量都优化过后,判断是否达到停止条件,满足则退出优化,否则继续迭代系数矩阵及字典优化。
详细步骤如下图
问题与猜想
1 为什么不直接用SVD奇异值直接将样本矩阵分解出
D
X
DX
DX?
猜想:样本矩阵巨大,运算量巨大,现有SVD接口以及机器设备难以维持?
但是采用K-SVD,在优化字典时,缩小
E
E
E,从而完成计算。
2 需要使用两步迭代优化的原因?
猜想:第一步初始化字典使用的随机样本,因为字典属于超完备字典,因此,中间存在重复列,或可以相互线性表示的列,因此需要优化字典。优化字典的时候,仅仅同时优化了系数矩阵对应行非0项,因此还需要单独的系数矩阵优化步骤,否则,从系数矩阵初始化之后,系数矩阵被优化的都是固定项。
3 选取
U
U
U的第一项作为
d
k
d_k
dk优化值的原因:
猜想:矩阵经过奇异值分解后,奇异值的重要顺序是从上到下排列的,即靠前的都是比较重要的项,甚至有的矩阵的奇异值第一个远大于剩余的奇异值,则第一项以外奇异值相关的计算对逼近原矩阵的影响较小。
TIPS:
1 矩阵A左乘矩阵,即是对矩阵A的行向量线性组合生成新的矩阵
矩阵A右乘矩阵,即是对矩阵A的列向量线性组合生成新的矩阵
[x x x] * [x x x]T
2 SVD分解后,奇异值的大小反映了奇异矩阵的重要程度,则
U
U
U及
V
V
V的第一列重要,而奇异值则被用作系数。
参考文献
https://blog.csdn.net/chlele0105/article/details/16886795
https://blog.csdn.net/lanyanchenxi/article/details/50471698
https://blog.csdn.net/hjimce/article/details/50810129