理解稀疏编码sparse coding


稀疏编码系列:

  • (一)----Spatial Pyramid 小结
  • (二)----图像的稀疏表示——ScSPM和LLC的总结
  • (三)----理解sparse coding
  • (四)----稀疏模型与结构性稀疏模型

---------------------------------------------------------------------------

       

        本文的内容主要来自余凯老师在CVPR2012上给的Tutorial。前面在总结ScSPM和LLC的时候,引用了很多Tutorial上的图片。其实这个Tutorial感觉写的挺好的,所以这次把它大致用自己的语言描述一下。不过稀疏编码是前两年比较火的东西,现在火的是deep learning了。

1、What is sparse coding?

       1988年,神经稀疏编码的概念由Mitchison提出,由牛津大学的Rolls等正式引用。灵长目动物颚叶视觉皮层和猫视觉皮层的电生理实验报告和一些相关模型的研究结果都说明了视觉皮层复杂刺激的表达是采用稀疏编码原则的。研究表明:初级视觉皮层V1区第四层有5000万个(相当于基函数),而负责视觉感知的视网膜和外侧膝状体的神经细胞只有100万个左右(理解为输出神经元)。说明稀疏编码是神经信息群体分布式表达的一种有效策略。1996年,加州大学伯克利分校的Olshausen等在Nature杂志发表论文指出:自然图像经过稀疏编码后得到的基函数类似V1区简单细胞感受野的反应特性(空间局部性、空间方向性、信息选择性)。

       典型的sparse coding的过程分为训练和测试。

       Training:给定一些训练样本(training samples)[ x1, x2, …, xm(in Rd)],学习一本字典的基(bases)[Φ1,Φ2……(also in Rd)]。可是用k-means等无监督的方法,也可以用优化的方法(这时training完了同时也得到了这些training samples的codes,这是一个LASSO和QP问题的循环迭代);

       Coding:用优化的方法求解测试样本的codes(此时字典已经学得)。经典的方法是求解LASSO:

理解稀疏编码sparse coding_第1张图片                  (1)

        自我学习就是在Training的时候采用大量无标注的自然图像训练字典,然后对带标注的图像进行编码得到特征codes。

 

2、Connections to RBMs, autoencoders

      (1)式(经典的稀疏编码)有几个特点:

            ——系数a是稀疏的;

            ——a的维数一般比x的维数大;

            ——编码过程a=f(x)是一个非线性的关于x的隐函数(即我们没有f(x)的显示表达,因为求解LASSO没有解析解);

            ——重建过程x'=g(a)是一个线性的显示的关于a的函数(X’=ΣaiΦi)。

理解稀疏编码sparse coding_第2张图片

         而RBM和自编码的特点则是:

           ——有显示的f(x);

           ——不会必然得到稀疏的a,但是如果我们增加稀疏的约束(如稀疏自编码,稀疏RBM),通常能得到更好的效果(进一步说明sparse helps learning)。

         从广义上说,满足这么几个条件的编码方式a=f(x)都可以叫稀疏编码:

           1) a是稀疏的,且通常具有比x更高的维数;

           2) f(x)是一个非线性的映射;(jiang1st2010注:该条要求存疑,见下面解释。

           3) 重建的过程x'=g(a),使得重建后的x'与x相似。

          因此,sparse RBM,sparse auto-encoder,甚至VQ都可以算是一种sparse coding。(jiang1st2010注:第二条要求称f(x)是一个非线性映射,然而SPM中用到的VQ是一个线性映射,原因可以参见这里这里。余凯老师也是LLC论文的作者,似乎存在矛盾?不过这是个小问题了,没必要深究

 

3、Sparse activations vs. sparse models

         现在可以用a=f(x)表示稀疏编码的问题了。它可以分解成两种情况:

         1)sparse model:f(x)的参数是稀疏的

                  --例如:LASSO f(x)=,其中w要求是稀疏的。(jiang1st2010注:这个例子中f(x)也是线性的!)

                  --这是一个特征选择的问题:所有的x都挑选相同的特征子集。

                  --hot topic.

         2)sparse activation:f(x)的输出是稀疏的

                  --就是说a是稀疏的。

                  --这是特征学习的问题:不同的x会激活不懂的特征子集。

                         理解稀疏编码sparse coding_第3张图片                  理解稀疏编码sparse coding_第4张图片

 

4、Sparsity vs. locality

       其实这个问题在这里已经谈过了。简单的说就是sparsity不一定导致locality,而locality肯定是sparse的。sparse不比locality好,因为locality具有smooth的特性(即相邻的x编码后的f(x)也是相邻的),而仅仅sparse不能保证smooth。smooth的特性对classification会具有更好的效果,并且设计f(x)时,应尽量保证相似的x在它们的codes中有相似的非0的维度。

理解稀疏编码sparse coding_第5张图片

 

         Tutorial上展示了(1)中取不同的λ,字典中各项呈现的效果:

理解稀疏编码sparse coding_第6张图片   理解稀疏编码sparse coding_第7张图片   

理解稀疏编码sparse coding_第8张图片   理解稀疏编码sparse coding_第9张图片

        作者想说明的问题是分类效果越好的情况下,basis会更清晰地表现出属于某几个特定的类。但是我没太看明白。

 

5、Hierarchical sparse coding

        这里图3曾说明了SIFT本身就是一个Coding+Pooling的过程,所以SPM是一个两层的Coding+Pooling。而Hierarchical sparse coding就是两层的coding都是sparse coding,如下图:

理解稀疏编码sparse coding_第10张图片

         整个HSC的第一层就从pixel层级开始(不需要手动设计SIFT特征了),经过两层SC后,形成codes。这个过程可以从无标注的数据中学习,就是self-taught learning。从pixel层级开始,这点和DNN啥的很像了。

理解稀疏编码sparse coding_第11张图片

          从结果来看,HSC的性能会比SIFT+SC稍微好些。

        

           Tutorial的最后列举了关于SC的其他主题,我也不懂,这里就不废话了。


稀疏编码(sparsecode)简单理解

Sparse coding:

  本节将简单介绍下sparse coding(稀疏编码),因为sparse coding也是deep learning中一个重要的分支,同样能够提取出数据集很好的特征。本文的内容是参考斯坦福deep learning教程:Sparse Coding,Sparse Coding: Autoencoder Interpretation,对应的中文教程见稀疏编码,稀疏编码自编码表达。

  在次之前,我们需要对凸优化有些了解,百度百科解释为:”凸优化“ 是指一种比较特殊的优化,是指目标函数为凸函数且由约束条件得到的定义域为凸集的优化问题,也就是说目标函数和约束条件都是”凸”的。

  好了,现在开始简单介绍下sparse coding, sparse coding是将输入的样本集X分解为多个基元的线性组合,然后这些基前面的系数表示的是输入样本的特征。其分解公式表达如下:

   

  而一般情况下要求基的个数k非常大,至少要比x中元素的个数n要大,因为这样的基组合才能更容易的学到输入数据内在的结构和特征。其实在常见的PCA算法中,是可以找到一组基来分解X的,只不过那个基的数目比较小,所以可以得到分解后的系数a是可以唯一确定,而在sparse coding中,k太大,比n大很多,其分解系数a不能唯一确定。一般的做法是对系数a作一个稀疏性约束,这也就是sparse coding算法的来源。此时系统对应的代价函数(前面的博文都用损失函数表示,以后统一改用代价函数,感觉这样翻译更贴切)表达式为:

   

  其中的第一项是重构输入数据X的代价值,第二项的S(.)为分解系数的系数惩罚,lamda是两种代价的权重,是个常量。但是这样还是有一个问题,比如说我们可以将系数a减到很小,且将每个基的值增加到很大,这样第一项的代价值基本保持不变,而第二项的稀疏惩罚依旧很小,达不到我们想要的目的——分解系数中只有少数系数远远大于0,而不是大部分系数都比0大(虽然不会大太多)。解决这个问题的通用方法是是对基集合中的值也做了一个约束,约束后的系统代价函数为:

   

 

  Sparse coding的概率解释:

  主要是从概率的角度来解释sparse coding方法,不过这一部分的内容还真没太看明白,只能讲下自己的大概理解。如果把误差考虑进去后,输入样本X经过sparse coding分解后的表达式则如下:

   

  而我们的目标是找到一组基Ф,使得输入样本数据出现的概率与输入样本数据的经验分布概率 最相近,如果用KL距离来衡量其相似度的话,就是满足他们的KL距离最小,即下面表达式值最小:

   

  由于输入数据的经验分布函数概率是固定值,所以求上式值最小相当等价于求最大。

  经过对参数a的先验估计和函数积分值估计等推导步骤,最后等价于求下面的能量函数值最小:

   

  而这就很好的和sparse coding的代价函数公式给联系起来了。

  到目前为止我们应该知道sparse coding的实际使用过程中速度是很慢的,因为即使我们在训练阶段已经把输入数据集的基Ф学习到了,在测试阶段时还是要通过凸优化的方法去求得其特征值(即基组合前面的系数值),所以这比一般的前向神经网络速度要慢(一般的前向算法只需用矩阵做一下乘法,然后做下加法,求个函数值等少数几步即可完成)。

 

  Sparse coding的autoencoder解释:

  首先来看看向量X的Lk规范数,其值为:  由此可知,L1范数为各元素之和,L2范数为该向量到远点的欧式距离。 

  用矩阵的形式来表达sparse coding的代价函数如下:

   

  和前面所讲的一样,这里也对基值s做了稀疏性惩罚,用的是L1范数来约束,同时也防止系数矩阵A过大,对其用的是L2范数的平方来约束。但是基值处的L1范数在0点是无法求导的,所以不能用梯度下降等类似的方法来对上面的代价函数求最优参数,于是为了在0处可导,可将公式变成如下:

   

 

  拓扑sparse coding:

  拓扑sparse coding主要是模仿人体大脑皮层中相邻的神经元对能提取出某一相近的特征,因此在deep learning中我们希望学习到的特征也具有这样“拓扑秩序”的性质。如果我们随意的将特征排列成一个矩阵,则我们希望矩阵中相邻的特征是相似的。也就是把原先那些特征系数的稀疏性惩罚项L1范数更改为不同小组L1范数惩罚之和,而这些相邻小组之间是有重叠值的,因此只要重叠的那一部分值改变就意味着各自组的惩罚值也会改变,这也就体现出了类似人脑皮层的特性,因此此时系统的代价函数为:

   

  改成矩阵的形式后如下:

   

 

  总结:

  在实际编程时,为了写出准确无误的优化函数代码并能快速又恰到好处地收敛到最优值,可以采用下面的技巧:

  1. 将输入样本集分成多个小的mini-batches,这样做的好处是每次迭代时输入系统的样本数变少了,运行的时间也会变短很多,并且也提高了整体收敛速度。(暂时还没弄明白原因)。
  2. S的初始化值不能随机给。一般都是按照下面的方法进行:

             

  最后,在实际优化该代价函数时步骤大致如下: 

  1. 随机初始化A
  2. 重复以下步骤直至收敛
    1. 随机选取一个有小的mini-batches。
    2. 按照前面讲的方法来s。
    3. 根据上一步给定的A,求解能够最小化J(A,s)的s
    4. 根据上一步得到的s,求解能够最小化J(A,s)的A

注:本文学习自CVPRLinear Spatial Pyramid Matching Using Sparse Coding
for Image Classification》、《Image classification By non-negative sparse coding, low-rank and sparse decomposition》及《基于稀疏编码的图像视觉特征提取及应用》

本文学习笔记是自己的理解,如有不对的地方,请大家指正批评,共同进步!

在提取完所有训练图像的SIFT特征后,需要对每幅图像进行视觉特征编码。视觉特征编码的目的在于对原始特征向量进行选择和变换,得到图像中最具表现力和区分度的视觉特征向量,使得计算机可以更高效的进行处理。一般编码方式是向量量化,另一种视觉编码方式稀疏编码能更好的表示图像。

1、向量量化

向量量化的基本思想是在基向量空间中寻找目标向量的最近邻,然后用该基向量的编号表示原目标向量:


其中x为某个SIFT特征向量,di为基向量空间中的第i个向量。其实基向量就是对所有训练图像的所有SIFT特征向量进行聚类,得到的K个聚类中心,这K个特征向量最后作为基向量。然后对于每一幅图像,寻找每个SIFT特征向量属于哪个基向量,来进行映射。

在向量量化的过程中,基本步骤如下:
1) 将全部的训练样本进行归一化;
2) 对训练样本进行聚类,得到若干个类中心,构成基向量空间:
3) 在所有类中心中为目标向量寻找最近邻。

BOW模型中,先聚类产生视觉关键词,然后进行向量量化编码。对于用SIFT特征

理解稀疏编码sparse coding_第12张图片

就是这幅图像的稀疏编码。
向量量化的优点在于计算简单,数据压缩率高,缺点在于精度损失比较大,在某些应用中难以满足要求。

2、稀疏编码

稀疏编码的本质是一个目标向量可以由少量的基向量经线性拟合而成,且基向量空间存在一定的冗余。与向量量化的区别是向量量化的每个目标向量只能由一个基向量表示。也就是说向量量化方式的约束条件太严格,会引起重构误差。二者区别可表示如下:

理解稀疏编码sparse coding_第13张图片
理解稀疏编码sparse coding_第14张图片

对图像的稀疏编码一般分为两个过程:

一是基向量的训练过程,也称为字典的学习。在这个过程中,我们利用大量的训练样本,通过无监督学习方法学习获得一组冗余的基向量,这组基向量通常反映了训练样本中一些带有本质特性的基元,如图像中的边界、角点,实验表明,字典的学习过程模拟了人类视觉皮层对信息的处理过程。

最优化问题(1)变成了二次约束的最小二乘问题,即:


这个最优化问题,在给定X情况下,交替固定一个变量,训练另一个变量,如此迭代。

   二是线性拟合的求解过程。即任意目标向量xn都可以由字典V内的若干个条目经线性组合拟合而成,该过程根据不同的约束条件,可以得到不同的拟合系数un,然后用该系数向量表示图像特征。

此时V已知,对图像X稀疏编码得到U,问题变为如下求解:


3、实验过程:

1、从每张图像中随机提取一个特征点向量,凑出一个初始训练样本X。(128*2600
for ii = 1:2600

     fpath = training.path{ii};

      load(fpath);

      num_fea = size(feaSet.feaArr, 2);

       rndidx = randperm(num_fea);

       X(:, ii) = feaSet.feaArr(:, rndidx(ii));

end;

2、视觉字典V的学习
  a、初始视觉字典V通过随机函数给出,先随机产生一个128*300的矩阵作为初始视觉 字典

V = rand(128, 300)-0.5;%先随机生成一个视觉词典V

    V = V - repmat(mean(V,1), size(V,1),1);

     V = V*diag(1./sqrt(sum(V.*V)));

  b、使用刚刚得到的V,对样本X计算得到U

  U = L1QP_FeatureSign_Set(X, V, lambda);

此函数在已知训练样本X和给出的视觉字典V的前提下,学习得到此时样本的稀


  c、使用刚刚得到的U,再训练得到V
V = l2ls_learn_basis_dual(X, U, pars.VAR_basis);

此函数在已知训练样本X和样本稀疏编码U的前提下,学习得到V。在条件


  d、迭代50bc过程,最终得到视觉词典V及训练样本X的稀疏编码U

3、对每张图像,应用得到的视觉字典V,得到其稀疏编码U

4、如下代码用某种方式(sc_approx_pooling)对每幅图像的稀疏编码进行了处理,然后用21*300(300是视觉关键词的个数)维向量来表示这幅图像。以前是对向量量化编码U按关键词出现的频次计算直方图来表示这幅图像,现在改用最大池处理,即对于稀疏编码得到的U,Uij表示了第iSIFT特征区域对第j个关键词的归属程度,取每个关键词中归属程度的最大值来表示这个关键词,得到K维特征向量来表示这幅图像。

sc_fea = zeros(6300, 2600);%%所有训练图像的稀疏编码

sc_label = zeros(2600, 1);

for iter1 = 1:2600,  

     fpath = database.path{iter1};

     load(fpath);

     %%对每张图像给出一个稀疏编码矩阵(这里需要对每张图片每金字塔层每个网格给出一个300*N 稀疏编码矩阵,最后按 权值串联该幅图的所有稀疏编码作为最终稀疏编码来表示这幅图像)

     sc_fea(:, iter1) = sc_approx_pooling(feaSet, V, pyramid, gamma);

    sc_label(iter1) = database.label(iter1);

end;

 

 

总结一下,稀疏编码其实就是先对所有图像的所有SIFT特征进行训练,得到基向量也即视觉关键词V。之后对于每一幅图像,计算其每个特征点所属的基向量索引uu中含有多个非零系数用来拟合多个基向量,得到一幅图像的系数编码U。用U乘以基向量V就能表示一幅图像X。之后再用方法(sc_approx_pooling)对每幅图像的稀疏表示U进行了处理,得到300(视觉关键词的个数)维向量来表示这幅图像。


你可能感兴趣的:(数学基础)