UFLDL:稀疏自编码器

吴恩达的 CS294A 是一门很好的深度学习入门课程,打算接下来的学习以这个课程的内容为主。UFLDL Tutorial 是 CS294A 课程的 wiki 页,包含了课程讲义和作业。如果你对 监督学习逻辑回归梯度下降 等基础概念并不熟悉,可以先学习 之前的课程

关于课程作业的 Python 代码已经放到了 Github 上,点击 课程代码 就能去 Github 查看( 无法访问 Github 的话可以点击 Coding 查看 ),代码中的错误和改进欢迎大家指出。

稀疏自编码器

大家知道现在深度学习在计算机视觉领域全面开花结果,得到了许多之前无法想象的好结果。而就在这之前大家还要花费很大的精力来人工设计特征。下面要学习的 稀疏自编码器 正是向自动学习特征迈出的第一步。( 下图为作业中的神经网络,左图为输入图像,右图为训练后的输出图像 )

稀疏自编码器 的基本模型是一个三层的神经网络,在学习时让网络输出的目标值接近于输入的图像本身,从而学习图像中的特征。直接学习一个恒等函数的话没有什么意义,所以我们要对隐含层做出一些限制,比如减小神经元的个数,网络就会被迫压缩数据并尝试重建输入图像。当我们加入惩罚让神经元在大部分情况下都不激活的时候,网络能够学习到十分有趣的边缘特征。隐含层的神经元在观察到输入图像中某个特定角度的边缘特征时才会被激活( 这和神经科学发现的人类视觉皮层V1中的神经元的激活方式相似 )。

代价函数

根据机器学习的一般模式,首先给出 稀疏自编码器 的代价函数:

J_{sparse}(W,b)= \frac{1}{m}\sum\limits_{i=1}^{m}\big(\frac{1}{2}||h_{W,b}(x^{(i)})-y^{(i)}||^2\big)
+ \frac{\lambda}{2}\sum\limits_{l=1}^{L-1}\sum\limits_{i=1}^{s_l}\sum\limits_{j=1}^{s_{l+1}}\big(\Theta_{ji}^{(l)}\big)^2 \\
+ \beta\sum\limits_{j=1}^{s_2}KL(\rho||\hat\rho_j)

比起熟悉的前两项,代价函数新增了对于隐含层的惩罚,式中 s_2 表示隐含层的神经元个数。\hat\rho_j 表示 隐含层神经元 j 对于所有训练数据的平均激活度,\hat\rho_j=\sum\limits_{i=1}^{m}\big[a_j^{(2)}(x^{(i)})\big]( 注意这里的 a_j^{(2)}(x) 表示一个函数,值为数据 x 对应的 a_j^{(2)} ),\rho\hat\rho_j 的目标值,目的就是之前说的让神经元在大多数时间不激活。

按照 Ng 的说法,新的惩罚项有多种函数可以选择,而这里用来衡量 \rho\hat\rho_j 差异的度量为 KL \ divergence 又称为 相对熵,定义为:

KL(P||Q) = \sum\limits_{i}P(i)log\Big(\frac{Q(i)}{P(i)}\Big)

它所度量的是两个概率分布间的距离( 我也不是太懂,有机会再做深入的研究 )。 有了代价函数,接下来看下原先的反向传播算法有什么变化~

梯度下降

在之前 反向传播算法 课程中已经说过它该算法的两个重点,一个是它的目的:更快速地计算代价函数的梯度,另一个是它的计算依赖于多元函数求导的链式法则。

由于代价函数的增加项直接为隐含层的函数,所以隐含层的误差:

\delta^{(2)}_j = \frac{\partial J_{sparse}}{\partial z^{(2)}_j} = \frac{\partial J}{\partial z^{(2)}_j} + \frac{\partial KL}{\partial z^{(2)}_j}

其中后一项可化为:

\frac{\partial KL}{\partial z^{(2)}_j}= \sum\limits_{k=1}^{s_{2}} \frac{\partial KL}{\partial a_k^{(2)}} \frac{\partial a_k^{(2)}}{\partial z^{(2)}_j} = \beta\Big(-\frac{\rho}{\hat\rho_j}+\frac{1-\rho}{1-\hat\rho_j}\Big)g'(z^{(2)}_j)

因此 反向传播算法 中的 \delta^{(2)}_j 计算变为:

\delta^{(2)}_j = \Big(\sum\limits_{k=1}^{s_3} \Theta_{kj}^{(2)} \delta^{(3)}_k +\Big(-\frac{\rho}{\hat\rho_j}+\frac{1-\rho}{1-\hat\rho_j}\Big)\Big)a_j^{(2)} (1-a_j^{(2)})

其余的计算都和原先的算法相同。 搞定代价函数和梯度计算,剩下的就是调用带优化的梯度下降算法了~

可视化

最后稍微提下课程作业,它让我们在 10 张风景图片中随机取 10000 个 8x8 的局部图,然后让稀疏自编码器学习其中的特征。神经网络的隐含层神经元个数为 25,输入输出维度都为 64。下图为每个隐含层神经元对应的输入层权重,大致可看成该神经元检测到这种特征时会被激活。( tip: 作业中的学习算法和梯度检查函数在之前的课程中都写过,因此可以直接拿来用。 )

So~,稀疏自编码器的内容就是这些了,谢谢大家耐心阅读。

P.S. 封面图为猴子视觉皮层 V1 区的方向柱