K-SVD算法
-
算法简介
- K-SVD可以看做K-means的一种泛化形式(由K-means扩展而来),K-means算法中每个信号量只能用一个原子来近似表示,而K-SVD中每个信号是用多个原子的线性组合来表示的。
- K-SVD通过构建字典来对数据进行稀疏表示,经常用于图像压缩、编码、分类等应用。
主要问题
Y=DX
其中
Y∈R(n∗N),
D∈R(n∗K),
X∈R(k∗N),
N是样例数,
n是特征在字典中每一个Word的维度,
K是在训练字典中系数(原子的数量)的长度.
Y为要表示的信号,
D为超完备矩阵(列数大于行数),
X为稀疏矩阵,
X与
Y按列对应, 表示
D中元素按照
Xi为系数线性组合为
Y, 我们的目的就是找到
让X尽量稀疏的D.
minD.X||Y−DX||2Fs.t∀i,||xi||0≤T0
minD.X||xi||0s.t||Y−DX||2F≤ε
(其中第一个函数的意思是指求矩阵
Y−DX的F范数即矩阵中所有元素的绝对值平方再开方)(第二个式子是求
xi的0范数即计算向量之中非零元素的个数.
范数)上述式子的本质上是相通的, 只是表述形式上不一样. 由于寻找最优解(X最稀疏)是NP难的问题, 因此用追逐算法(Pursuit Algorithm)得到的次优解代替. (MP, OMP, BP, FOCUSS)
算法求解
给定训练数据后一次找到全局最优解的字典为NP难的问题, 只能逐步逼近最优解. 构造D算法分为两步: 稀疏表示和字典更新
稀疏表示
首先设定一个初始化的字典, 用该字典对给定数据进行稀疏表示(即用尽量少的系数尽可能近似的表示数据)得到系数矩阵X. 此时, 应该把DX看成D中每列与X中每行乘积的和, 也就是把DX分片, 即:
DX=∑i=1Kdixi
di表示
D的列,
xi表示
X的行, 然后逐片优化.
字典更新
初始字典往往不是最优的, 满足稀疏性的系数矩阵表示的数据和原数据会有较大误差, 我们需要在满足稀疏度的条件下逐行逐列更新优化, 减少整体误差, 逼近可用字典. 剥离字典中第k(1−k)项dk的贡献, 计算当前表示误差的矩阵:
E=Y−∑i≠kdixi
误差值为
En=||E||2F
上式可以看做把第
k个基分量剥离后, 表达中产生空洞, 如何找到一个新基, 以更好地填补这个洞, 就是SVD方法的功能所在, 当误差值稳定的时候字典基本收敛.
求解流程
K-SVD是一个迭代的过程. 首先, 假设字典D是固定的, 用MP, OMP, BP等算法, 可以得到字典D上, Y的稀疏表示的系数是矩阵X, 然后让X固定, 根据X更新字典D, 如此循环直到收敛为止.
字典D的更新是逐列进行的. 首先假设系数矩阵X和字典D都是固定的, 将要更新的是字典的第k列dk, 系数矩阵X中dk对应第k行为xkT, 则
||Y−DX||2F=||Y−∑j=1kdjxjT||2F=||(Y−∑j≠kkdjxjT)−djxkT||2F=||Ek−dkxkT||2F
得到当前误差矩阵
Ek后, 我们只要调整
dk和
xk, 使其乘积与
Ek的误差尽可能小.
对于上面的问题, 如果直接用
Ek的SVD分解结果来更新
dk和
xk则会导致
xk不稀疏, 出现”发散”. 换句话说,
xkT中非零位置乘积后的那些项
. 形成
EkR, 将
EkR做SVD分解, 更新
dk.
具体如下:
算法流程

参考:
1. http://blog.****.net/chlele0105/article/details/16886795
2. K-SVD: An algorithm fordesigning overcomplete dictionaries for sparse representation (IEEE Trans. OnSignal Processing 2006)
3. http://home.ustc.edu.cn/~zywvvd/files/K-SVD.pdf
4. http://blog.****.net/cc198877/article/details/9167989