深度学习笔记1 : 稀疏自编码器

神经网络

概述

神经元

$$
h{W,b}(x)=f(\sum{i=1}^3 w_ix+b)\
f \quad \mathbb R \to \mathbb R$$
: 激活函数
选取sigmoid 作为激活函数
$ f(z)=1\over {1+ e^{-z} } $

需要注意的是
$$
f’(z)=f(z)*(1-f(z))
$$

sigmoid function

神经网络模型

神经网络模型

+1 称为偏置节点
输入层 最左边
输出层 最右边
隐藏层 中间
三个输入单元1个输出单元 三个隐藏单元
$n_l$ 表示层数,将第l层记为$L_l$
输入层是$L1$, 输出层是$L{n_l}$
上图神经网络参数如下
${\ W^{(1)}, b^{(1)},W^{(2)},b^{(2)}}$

其中 $W_{ij}^{l}$代表着第l层的$x_j$ 与第l+1层的$x_{i}$之间的关系
$b^l_i$是第l+1层的i单元的偏置项偏置项

在上图例子中 $$W^{(1)} \in \mathbb R^{3\times 3}\
W^{(2)} \in \mathbb R^{13}
$$
偏置单元没有输入,输出总为+1,在计算节点数时,偏置单元也不计算在内.
用$a^l_i$ 表示第l层的第i个单元的激活值,即*输出值
,但l=1时,$a_i^1$等于$x_i$ 也就是第i个输入值
$$
\begin{cases}
a1^{(2)}=f(w^{(1)}{11}x1+w{12}^{(1)}x2+w^{(1)}{13}x3+b{1}^{(1)} )\
a2^{(2)}=f(w^{(1)}{21}x1+w^{()}{22}x2+w^{(1)}{23}x_3+b^{1}_2)\
a3^{(2)}=f(w^{(1)}{31}x1+w^{(1)}{32}x2+w^{(1)}{33}x_3+b^{(1)}3)
\end{cases}
$$
$$
\begin{align}
h
{w,b}(x)&=a1^{(3)} \
&=f(w^{(2)}
{11}a1^{(2)}+w^{(2)}{(12)}a2^{(2)}+w^{(2)}{13}a_3^{(2)}+b_1^{(2)}) \
\end{align}
$$

如果我们用$z^{(l)}_{i}$表示第l层的第i 个单元的加权输入和, 那么$a_i^{(l)}=f(z_i^{(l)})$.
如果我们将f扩展成向量表示:
$$f([z_1,z_2,z_3])=[f(z_1),f(z_2),f(z3)]$$
则,上述结论有一种更加简洁的表示:
$$
z^{(2)}={w^{(1)}x +b^{(1)} }\
a(2)=f(z^{(2)})\
z^{(3)}=w^{(2)}a^{(2)}\
h
{(w,b)}(x)=a^{(3)}=f(z^{(3)})
$$
我们把上面的步骤称之为前向传播(forward propagation),

  1. 给定第1层的激活值$a^{(1)}=x^{(1)}$.
  2. 对于任何给定的第l层激活值,可以通过下面公式计算得到第l+1层的激活值:
    $$ z^{(1+1)}=W^{(l)}X^{(l)}\
    a^{(l+1)}=f(z^{(l+1)})
    $$
    通过参数矩阵化,使用矩阵-向量的运算方式,我们就可以利用线性代数来对神经网络进行快速求解.

我们还可以构建多种神经网络结构(结构指的是神经元之间的连接方式)

反向传导算法

假设有一个固定的样本集${ (x^{(1)},y^{(1)}), (x^{(2)},y^{(2)}) … (x^{(m)},y^{(m)}) }$ 包含m个样例.我们定义总体代价函数如下:
$$
\begin{align}
J(w,b)&=\left [ {1\over m} \sum{i=1}^{m} J(w,b:x^{(i)},y^{(i)}) \right ]+{\lambda \over 2}{\sum {l=1}^{nl} \sum {i=1}^{sl} \sum {j=1}^{s{l+1}} (W^{(l)}{ij})^2 }\
&=\left [ {1\over m} \sum{i=1}^{m} {1\over 2}{ \mid h{w,b}(x^{(i)} ) -y^{(i)} \ \mid ^{2}} \right ]+{\lambda \over 2}{\sum _{l=1}^{nl} \sum {i=1}^{sl} \sum {j=1}^{s{l+1}} (W^{(l)}{ji})^2 }
\end{align}
$$
注意$W_{ji}$下标顺序
第一项是均方差项,第二项是规则化项,也叫权重衰减项,防止过度拟合,记住权重衰减项不考虑b
以上的代价函数经常被用于分类和回归问题。在分类问题中,我们用 y = 0 或 1,来代表两种类型的标签(回想一下,这是因为 sigmoid激活函数的值域为 [0,1];如果我们使用双曲正切型激活函数,那么应该选用 -1 和 +1 作为标签)。对于回归问题,我们首先要变换输出值域(译者注:也就是 y),以保证其范围为 [0,1] (同样地,如果我们使用双曲正切型激活函数,要使输出值域为 [-1,1])。

我们的目标是求得是J(w,b)最小的w,b. 首先使用随机生成w,b,利用正态分布,均值为0,方差为0.01, 之后利用梯度下降法求得最优值.由于J(w,b)是非凸函数,所以未必会下降到最小值,但是实际一般效果还不错.

将参数进行随机初始化,不是全部取0,因为全部取0 的话,或者取相同的值的话将导致每一个隐藏单元的输出值一样, 随机初始化的目的是是对称失效

梯度下降法的的步骤如下:
$$
W^{(l)}{ij}=W^{(l)}{ij} - \alpha {\partial \over \partial {W^{(l)}{ij}} }J(W,b)\
b^{(l)
{i}}=b^{(l)_i}- \alpha
{\partial \over \partial b^{(l)}{i} } J(W,b)
$$
其中$\alpha$ 成为学习速率. 其中计算偏导数比较重要,需要专门讲一讲,反向传导算法
$ {\partial \over \partial {W^{(l)}
{ij}} }J(W,b)$和${\partial \over \partial b^{(l)}{i} } J(W,b)$是最重要的两个计算:
$$
{\partial \over \partial {W^{(l)}
{ij}} }J(W,b)= \left [ {1\over m} \sum{i=1}^{m} {\partial \over \partial W{ij}^{(l)}}J(w,b:x^{(i)},y^{(i)}) \right ]+{\lambda}{ W^{(l)}{ij}}\
{\partial \over \partial b^{(l)}
{i} } J(W,b)= \left [ {1\over m} \sum{i=1}^{m} {\partial \over \partial b{i}^{(l)}} J(w,b:x^{(i)},y^{(i)}) \right ]
$$

反向传播算法的思路如下:

给定一个样例(x,y),

  • 首先进行前向传导计算,计算出每个单元的激活值,包括$h_{w,b}(x)$的输出值,
  • 之后针对第l层的每一个节点i,我们计算其残差$\delta^{(l)}_i $:残差表明该节点对最终输出值的残差产生了多少的影响,

对于输出层,我们可以直接用输出值和 理论值之间的差距,即$\delta_i^{(n_l)}$ 那么对于隐藏层我们做什么处理呢? 我们将基于节点(l+1层)的残差加权计算$\delta_i^{(l)}$,这些节点以$a_I^{(l)}$作为输入:
下面给出计算细节:

  1. 进行前馈传导计算,利用前向传导公式,得到 $L_2,L3…..L{n_l}$
  2. 对于第$n_l$层的(输出层)的每个输出单元i, 我们根据以下公式计算残差:
    $$ \delta_i^{(n_l)} = {\partial \over \partial z_i^{(n_l)} } J(W,b;x,y)= - (y_i-a^{(n_l)}_i )f’(z_i^{(n_l)})$$
  3. 对于隐藏层, 第l层的计算公式如下:
    $\deltai^{(l) } = \left (\sum {j=1}^{s{l+1}} W^{(l)}{ji } \delta_j^{(l) } \right )f’(z_i^{(l)}) $
  4. 计算我们所需要
    $$ {\partial \over \partial {W^{(l)}_{ij}} }J(W,b)= a^{(l)}_j\delta ^{(l)}i$$
    $${\partial \over \partial b^{(l)}
    {i} } J(W,b)= \delta ^{(l+1)}_i$$

如果用矩阵和向量来表示反向传播算法:

  1. 利用前馈传导算法,得到$L_2,L3$直到$L{n_l}$的激活值
  2. 对输出层,计算:
    $\delta^{(n_l)}_i=-(y-a^{(n_l)})*f’(z^{(n_l)})$
  3. 对于隐藏层,计算:
    $\delta^{(l)}= ( (W^{(l)} )^{T} \delta^{(l+1)})*f’(z^{(l)})$
  4. 计算最终的偏导数值:
    $ \nabla {W^{(t)}} J = \delta^{(l+1)} (a^{(l)})^T$
    $ \nabla
    {b^{(t)}} J = \delta^{(l+1)} $

实际中因注意: 在以上(2)和(3)中要计算f’(z), 可以利用f’(z)=f(z)(1-f(z))
$f’(z_i^{(l)})= a_i^{(l)} (1-a_i^{(l)})$

总结:
梯度下降法的一次迭代:

  1. 对所有的l, 令$\Delta W$和$\Delta b $全部为0;
  2. 对于i=1到m:
    a. 利用反向传播算法计算$ \nabla {W^{(t)}} J \qquad \nabla {b^{(t)}} J$
    b. 计算$\Delta W=\Delta W + \nabla {W^{(t)}} J$
    c. 计算$\Delta b =\Delta b + \nabla
    {b^{(t)}} J$
  3. 更新权重参数:
    • $W^{(l)} = W^{(l)} -\alpha \left [ ({1 \over m} \Delta W^{(l)})+\lambda W^{(l)} \right ] $
    • $b^{(l)}= b^{(l)} -\alpha \left [ {1 \over m } \Delta b^{(l)}\right ] $

重复梯度下降法的迭代步骤即可减小代价函数 J,继而求得神经网络的

梯度检验与高级优化

索引的缺位错误(off-by-one error)会导致只有部分层的权重得到训练,再比如忘记计算偏置项。这些错误会使你得到一个看似十分合理的结果(但实际上比正确代码的结果要差)。因此,但从计算结果上来看,我们很难发现代码中有什么东西遗漏了.本节将介绍一种对求导结果进行数值检验的方法,该方法可以验证求导代码是否正确。另外,使用本节所述求导检验方法,可以帮助你提升写正确代码的信心
缺位错误: for (i=0;i<m;i++)写成了for (for (i=0;i<=m;i++))
比如在梯度下降法当中$\theta := \theta - \alpha {\partial \over \partial \theta}J(\theta) $
而导数的定义如下:
${d J(\theta)\over d(\theta)} =lim_{\epsilon\to 0 }{J(\theta + \epsilon )-J(\theta - \epsilon ) \over 2 \epsilon} $
如果我们取$\epsilon $很小 比如$10^{-4}$ 那么计算出来的结果应当和实际求导出来的结果小数至少前四位一样. 注意$\epsilon $ 不能取太小,否则会有舍入误差

如果是向量的话,也是类似,
将W,b 扩展成一个向量 J:$\mathbb {R^n \mapsto R}$

自编码算法与稀疏性

输入是无标签数据,学习一个函数 $ h_{w,b}(x)=x$
自编码神经网络
如果我们加以限制,假设某个自编码神经网络的输入 $\textstyle x$ 是一张 $\textstyle 10 \times 10 $图像(共100个像素)的像素灰度值,于是 $\textstyle n=100 $,其隐藏层$ \textstyle L_2 $中有50个隐藏神经元。注意,输出也是100维的 $\textstyle y \in \Re^{100}$ 。由于只有50个隐藏神经元,我们迫使自编码神经网络去学习输入数据的压缩表示,也就是说,它必须从50维的隐藏神经元激活度向量 $\textstyle a^{(2)} \in \Re^{50}$ 中重构出100维的像素灰度值输入 $\textstyle x$ 。
如果网络的输入数据是完全随机的,比如每一个输入 \textstyle x_i 都是一个跟其它特征完全无关的独立同分布高斯随机变量,那么这一压缩表示将会非常难学习。但是如果输入数据中隐含着一些特定的结构,比如某些输入特征是彼此相关的,那么这一算法就可以发现输入数据中的这些相关性。事实上,这一简单的自编码神经网络通常可以学习出一个跟主元分析(PCA)结果非常相似的输入数据的低维表示。

即使隐藏神经元的数量较大(可能比输入像素的个数还要多),我们仍然通过给自编码神经网络施加一些其他的限制条件来发现输入数据中的结构。比如稀疏性: 如果当神经元的输出接近于1的时候我们认为它被激活,而输出接近于0的时候认为它被抑制,那么使得神经元大部分的时间都是被抑制的限制则被称作稀疏性限制。
$$\begin{align}
\hat\rhoj = \frac{1}{m} \sum{i=1}^m \left[ a^{(2)}_j(x^{(i)}) \right]
\end{align}$$ 表示表示隐藏神经元 $\textstyle j$ 的平均活跃度
我们可以加入一条限制
\begin{align}
\hat\rhoj = \rho,
\end{align}
$\textstyle \rho$ 是稀疏性参数, $\rho$称之为稀疏性参数,通常很小,比如0.05,. 为了实现这个目标,我们常常加入一个惩罚因子
\begin{align}
\sum
{j=1}^{s_2} \rho \log \frac{\rho}{\hat\rho_j} + (1-\rho) \log \frac{1-\rho}{1-\hat\rhoj}.
\end{align}
这其实是相对熵[^相对熵],相对熵是一种标准的用来测量两个分布之间差异的方法
于是新的J函数编程如下:
\begin{align}
J
{\rm sparse}(W,b) = J(W,b) + \beta \sum_{j=1}^{s_2} {\rm KL}(\rho || \hat\rho_j),
\end{align}

为了对相对熵进行导数计算,我们可以使用一个易于实现的技巧,
前面在后向传播算法中计算第二层( \textstyle l=2 )更新的时候我们已经计算了
\begin{align}
\delta^{(2)}i = \left( \sum{j=1}^{s{2}} W^{(2)}{ji} \delta^{(3)}_j \right) f’(z^{(2)}_i),
\end{align}
现在我们将其换成
\begin{align}
\delta^{(2)}i =
\left( \left( \sum
{j=1}^{s{2}} W^{(2)}{ji} \delta^{(3)}_j \right)

  • \beta \left( - \frac{\rho}{\hat\rho_i} + \frac{1-\rho}{1-\hat\rho_i} \right) \right) f’(z^{(2)}_i) .
    \end{align}

可视化自编码器训练结果

训练完(稀疏)自编码器,我们还想把这自编码器学到的函数可视化出来,好弄明白它到底学到了什么。我们以在10×10图像(即n=100)上训练自编码器为例。在该自编码器中,每个隐藏单元i对如下关于输入的函数进行计算:
\begin{align}
a^{(2)}i = f\left(\sum{j=1}^{100} W^{(1)}_{ij} x_j + b^{(1)}i \right).
\end{align}
我们将要可视化的函数,就是上面这个以2D图像为输入、并由隐藏单元i计算出来的函数。它是依赖于参数$\textstyle W^{(1)}
{ij}$的(暂时忽略偏置项bi)。需要注意的是,$\textstyle a^{(2)}_i$可看作输入$\textstyle x$的非线性特征。不过还有个问题:什么样的输入图像$\textstyle x$可让$\textstyle a^{(2)}i$得到最大程度的激励?(通俗一点说,隐藏单元$\textstyle i$要找个什么样的特征?)。这里我们必须给$\textstyle x$加约束,否则会得到平凡解。若假设输入有范数约束$\textstyle ||x||^2 = \sum{i=1}^{100} x_i^2 \leq 1$,则可证(请读者自行推导)令隐藏单元$\textstyle i$得到最大激励的输入应由下面公式计算的像素$\textstyle x_j$给出(共需计算100个像素,j=1,…,100):
\begin{align}
xj = \frac{W^{(1)}{ij}}{\sqrt{\sum{j=1}^{100} (W^{(1)}{ij})^2}}.
\end{align}
当我们用上式算出各像素的值、把它们组成一幅图像、并将图像呈现在我们面前之时,隐藏单元$\textstyle i$所追寻特征的真正含义也渐渐明朗起来。
当我们对稀疏自编码器(100个隐藏单元,在10X10像素的输入上训练 )进行上述可视化处理之后,结果如下所示:
结果

上图的每个小方块都给出了一个(带有有界范数 的)输入图像 x,它可使这100个隐藏单元中的某一个获得最大激励。我们可以看到,不同的隐藏单元学会了在图像的不同位置和方向进行边缘检测

[^相对熵]: 在概率论或信息论中,KL散度( Kullback–Leibler divergence),又称相对熵(relative entropy),是描述两个概率分布P和Q差异的一种方法。它是非对称的,这意味着D(P||Q) ≠ D(Q||P)。特别的,在信息论中,D(P||Q)表示当用概率分布Q来拟合真实分布P时,产生的信息损耗,其中P表示真实分布,Q表示P的拟合分布。
有人将KL散度称为KL距离,但事实上,KL散度并不满足距离的概念,因为:1)KL散度不是对称的;2)KL散度不满足三角不等式。