稀疏编码自编码表达
From Ufldl
Line 13: | Line 13: | ||
</math> | </math> | ||
- | ( <math>\lVert x \rVert_k</math>是x的Lk范数,等价于<math>\left( \sum{ \left| x_i^k \right| } \right) ^{\frac{1}{k}}</math>。L2范数即大家熟知的欧几里得范数,L1范数是向量元素的绝对值之和) | + | (<math>\lVert x \rVert_k</math>是x的Lk范数,等价于<math>\left( \sum{ \left| x_i^k \right| } \right) ^{\frac{1}{k}}</math>。L2范数即大家熟知的欧几里得范数,L1范数是向量元素的绝对值之和) |
上式前第一部分是利用基向量将特征集重构为样本数据所产生的误差,第二部分为稀疏性惩罚项(sparsity penalty term),用于保证特征集的稀疏性。 | 上式前第一部分是利用基向量将特征集重构为样本数据所产生的误差,第二部分为稀疏性惩罚项(sparsity penalty term),用于保证特征集的稀疏性。 | ||
Line 29: | Line 29: | ||
但是,以上表达式带来了另一个难题:不能用简单的梯度方法来实现约束条件<math>A_j^TA_j \le 1 \; \forall j</math>。因此在实际问题中,此约束条件还不足以成为“权重衰变”("weight decay")项以保证A的每一项值够小。这样我们就得到一个新的目标函数: | 但是,以上表达式带来了另一个难题:不能用简单的梯度方法来实现约束条件<math>A_j^TA_j \le 1 \; \forall j</math>。因此在实际问题中,此约束条件还不足以成为“权重衰变”("weight decay")项以保证A的每一项值够小。这样我们就得到一个新的目标函数: | ||
- | |||
:<math> | :<math> | ||
Line 60: | Line 59: | ||
理论上,通过上述迭代方法求解目标函数的最优化问题最终得到的特征集(A的基向量)与通过稀疏自编码学习得到的特征集是差不多的。但是实际上,为了获得更好的算法收敛性需要使用一些小技巧,后面的[[ Sparse Coding: Autoencoder Interpretation#稀疏编码实践| 稀疏编码实践]] 稀疏编码实践章节会详细介绍这些技巧。用梯度下降方法求解目标函数也略需技巧,另外使用矩阵演算或[[Deriving gradients using the backpropagation idea | 反向传播算法]]则有助于解决此类问题。 | 理论上,通过上述迭代方法求解目标函数的最优化问题最终得到的特征集(A的基向量)与通过稀疏自编码学习得到的特征集是差不多的。但是实际上,为了获得更好的算法收敛性需要使用一些小技巧,后面的[[ Sparse Coding: Autoencoder Interpretation#稀疏编码实践| 稀疏编码实践]] 稀疏编码实践章节会详细介绍这些技巧。用梯度下降方法求解目标函数也略需技巧,另外使用矩阵演算或[[Deriving gradients using the backpropagation idea | 反向传播算法]]则有助于解决此类问题。 | ||
- | + | == [ 拓扑稀疏编码 ] == | |
- | + | ||
- | == [拓扑稀疏编码] == | + | |
通过稀疏编码,我们能够得到一组用于表示样本数据的特征集。不过,让我们来找些灵感,我们希望学习得到一组有某种“秩序”的特征集。举个例子,视觉特征,如前面所提到的,大脑皮层V1区神经元能够按特定的方向对边缘进行检测,同时,这些神经元(在生理上)被组织成超柱(hypercolumns),在超柱中,相邻神经元以相似的方向对边缘进行检测,一个神经元检测水平边缘,其相邻神经元检测到的边缘就稍微偏离水平方向,沿着超柱,神经元就可以检测到与水平方向相差更大的边缘了。 | 通过稀疏编码,我们能够得到一组用于表示样本数据的特征集。不过,让我们来找些灵感,我们希望学习得到一组有某种“秩序”的特征集。举个例子,视觉特征,如前面所提到的,大脑皮层V1区神经元能够按特定的方向对边缘进行检测,同时,这些神经元(在生理上)被组织成超柱(hypercolumns),在超柱中,相邻神经元以相似的方向对边缘进行检测,一个神经元检测水平边缘,其相邻神经元检测到的边缘就稍微偏离水平方向,沿着超柱,神经元就可以检测到与水平方向相差更大的边缘了。 | ||
Line 85: | Line 82: | ||
该目标函数能够使用之前部分提到的迭代方法进行求解。拓扑稀疏编码得到的特征与稀疏编码得到的类似,只是拓扑稀疏编码得到的特征是以某种方式有“秩序”排列的。 | 该目标函数能够使用之前部分提到的迭代方法进行求解。拓扑稀疏编码得到的特征与稀疏编码得到的类似,只是拓扑稀疏编码得到的特征是以某种方式有“秩序”排列的。 | ||
- | == [稀疏编码实践] == | + | == [ 稀疏编码实践 ] == |
如上所述,虽然稀疏编码背后的理论十分简单,但是要写出准确无误的实现代码并能快速又恰到好处地收敛到最优值,则需要一定的技巧。 | 如上所述,虽然稀疏编码背后的理论十分简单,但是要写出准确无误的实现代码并能快速又恰到好处地收敛到最优值,则需要一定的技巧。 | ||
回顾一下之前提到的简单迭代算法: | 回顾一下之前提到的简单迭代算法: | ||
+ | |||
<ol> | <ol> | ||
<li>随机初始化<math>A</math> | <li>随机初始化<math>A</math> | ||
Line 100: | Line 98: | ||
这样信手拈来地执行这个算法,结果并不会令人满意,即使确实得到了某些结果。以下是两种更快更优化的收敛技巧: | 这样信手拈来地执行这个算法,结果并不会令人满意,即使确实得到了某些结果。以下是两种更快更优化的收敛技巧: | ||
+ | |||
<ol> | <ol> | ||
<li>将样本分批为“迷你块” | <li>将样本分批为“迷你块” | ||
Line 105: | Line 104: | ||
</ol> | </ol> | ||
- | === [将样本分批为“迷你块”]=== | + | === [ 将样本分批为“迷你块” ]=== |
- | 如果你一次性在大规模数据集(比如,有10000 | + | 如果你一次性在大规模数据集(比如,有10000 个patch)上执行简单的迭代算法,你会发现每次迭代都要花很长时间,也因此这算法要花好长时间才能达到收敛结果。为了提高收敛速度,可以选择在迷你块上运行该算法。每次迭代的时候,不是在所有的10000个patchs上执行该算法,而是使用迷你块,即从10000个patch中随机选出2000个patch,再在这个迷你块上执行这个算法。这样就可以做到一石二鸟――第一,提高了每次迭代的速度,因为现在每次迭代只在2000个patch上执行而不是10000个;第二,也是更重要的,它提高了收敛的速度(原因见[[TODO]])。 |
- | === [良好的<math>s</math>初始值] === | + | === [ 良好的<math>s</math>初始值 ] === |
另一个能获得更快速更优化收敛的重要技巧是:在给定<math>A</math>的条件下,根据目标函数使用梯度下降(或其他方法)求解<math>s</math>之前找到良好的特征矩阵<math>s</math>的初始值。实际上,除非在优化<math>A</math>的最优值前已找到一个最佳矩阵<math>s</math>,不然每次迭代过程中随机初始化<math>s</math>值会导致很差的收敛效果。下面给出一个初始化<math>s</math>的较好方法: | 另一个能获得更快速更优化收敛的重要技巧是:在给定<math>A</math>的条件下,根据目标函数使用梯度下降(或其他方法)求解<math>s</math>之前找到良好的特征矩阵<math>s</math>的初始值。实际上,除非在优化<math>A</math>的最优值前已找到一个最佳矩阵<math>s</math>,不然每次迭代过程中随机初始化<math>s</math>值会导致很差的收敛效果。下面给出一个初始化<math>s</math>的较好方法: | ||
+ | |||
<ol> | <ol> | ||
<li>令<math>s \leftarrow W^Tx</math> (<math>x</math> 是迷你块中patches的矩阵表示) | <li>令<math>s \leftarrow W^Tx</math> (<math>x</math> 是迷你块中patches的矩阵表示) | ||
Line 118: | Line 118: | ||
</ol> | </ol> | ||
- | 无疑,这样的初始化有助于算法的改进,因为上述的第一步希望找到满足<math>Ws \approx x</math>的矩阵<math>s</math>;第二步对<math>s</math>作规范化处理是为了保持较小的稀疏惩罚值。这也表明,只采用上述步骤的某一步而不是两步对<math>s</math> | + | 无疑,这样的初始化有助于算法的改进,因为上述的第一步希望找到满足<math>Ws \approx x</math>的矩阵<math>s</math>;第二步对<math>s</math>作规范化处理是为了保持较小的稀疏惩罚值。这也表明,只采用上述步骤的某一步而不是两步对<math>s</math>做初始化处理将严重影响算法性能。([[TODO]]:此链接将会对为什么这样的初始化能改进算法作出更详细的解释) |
- | === [可运行算法] === | + | === [ 可运行算法 ] === |
有了以上两种技巧,稀疏编码算法修改如下: | 有了以上两种技巧,稀疏编码算法修改如下: | ||
+ | |||
<ol> | <ol> | ||
<li>随机初始化<math>A</math> | <li>随机初始化<math>A</math> |