# 1 神经网络基础

## 1.1 单个神经元

\begin{align*}
a = \frac{1}{1 + \exp(-(w^T x + b))}
\end{align*}

\begin{align*}
\end{align*}

## 1.2 单层神经元

\begin{align*}
a_1 &= \frac{1}{1 + \exp(-((w^{(1)})^T x + b_1))} \\
&\vdots \\
a_m &= \frac{1}{1 + \exp(-((w^{(m)})^T x + b_m))}
\end{align*}

\begin{align*}
&W = \begin{bmatrix} - & w^{(1)T} & -\\ & \cdots & \\ - & w^{(m)T} & - \end{bmatrix} \in \mathbb{R}^{m \times n} \\
&b = \begin{bmatrix} b_1\\ \vdots \\ b_m \end{bmatrix} \in \mathbb{R}^m \\
&z = Wx + b \\
&\sigma(z) = \begin{bmatrix} \frac{1}{1 + \exp(-z_1)}\\ \vdots \\ \frac{1}{1 + \exp(-z_m)} \end{bmatrix} \\
&\begin{bmatrix} a^{(1)}\\ \vdots \\ a^{(m)} \end{bmatrix} = \sigma(z) = \sigma(Wx + b)
\end{align*}

## 1.3 前馈计算

\begin{align*}
s = U^T a = U^T f(Wx + b)
\end{align*}

## 1.4 最大间隔目标函数

\begin{align*}
J = \max(s_c-s,0)
\end{align*}

\begin{align*}
J = \max(s_c - s + \Delta ,0)
\end{align*}

\begin{align*}
J = \max(s_c - s + 1 ,0)
\end{align*}

## 1.5 反向传播训练模型

\begin{align*}
\theta^{(t+1)} = \theta^{(t)} - \alpha \nabla_{\theta^{(t)}} J
\end{align*}

• $x_i$是神经网络的一个输入
• $s$是神经网络的输出
• 第$k$层的第$j$个神经元接受标量输入$z^{(k)}_j$并产生标量激活输出$a^{(k)}_j$
• 将$z^{(k)}_j$算出的反向传播误差记做$\delta^{(k)}_j$
• 第一层是指输入层，而不是第一个隐层。对于输入层，$x_j = z^{(1)}_j = a^{(1)}_j$
• $W^{(k)}$是转移矩阵，将第$k$层的输出映射为第$k+1$层的输入

\begin{align*}
\frac{\partial J}{\partial s} = -\frac{\partial J}{\partial s_c} = -1
\end{align*}

\begin{align*}
\frac{\partial s}{\partial w^{(1)}_{ij}} &= \frac{\partial W^{(2)} a^{(2)}}{\partial w^{(1)}_{ij}} \tag{1} \\
&= \frac{\partial W^{(2)}_i a^{(2)}_i}{\partial w^{(1)}_{ij}} \tag{2} \\
&= W^{(2)}_i \frac{\partial a^{(2)}_i}{\partial w^{(1)}_{ij}} \tag{3} \\
\end{align*}

\begin{align*}
W^{(2)}_i \frac{\partial a^{(2)}_i}{\partial w^{(1)}_{ij}} &= W^{(2)}_i \frac{\partial a^{(2)}_i}{\partial z^{(2)}_i} \frac{\partial z^{(2)}_i}{\partial w^{(1)}_{ij}} \\
&= W^{(2)}_i \frac{\partial f(z^{(2)}_i)}{\partial z^{(2)}_i} \frac{\partial z^{(2)}_i}{\partial w^{(1)}_{ij}} \\
&= W^{(2)}_i f'(z^{(2)}_i) \frac{\partial z^{(2)}_i}{\partial w^{(1)}_{ij}} \\
&= W^{(2)}_i f'(z^{(2)}_i) \frac{\partial}{\partial w^{(1)}_{ij}} (b^{(1)}_i + a^{(1)}_1W^{(1)}_{i1} + a^{(1)}_2W^{(1)}_{i2} + a^{(1)}_3W^{(1)}_{i3} + a^{(1)}_4W^{(1)}_{i4}) \\
&= W^{(2)}_i f'(z^{(2)}_i) a^{(1)}_j \\
&= \delta^{(2)}_i \cdot a^{(1)}_j
\end{align*}

$\delta^{(2)}_i$本质上是第2层第$i$个神经元反向传回的误差。

1. 首先从$a^{(3)}_1$反向传回误差1
2. 这个误差乘以把$z^{(3)}_1$映射到$a^{(3)}_1$的神经元的导数。由于输出层没有激活函数，$z^{(3)}_1 = a^{(3)}_1$，因此这一导数刚好是1，乘积依然是1，也就是$\delta^{(3)}_1 = 1$
3. 目前误差已经反向传播到了$z^{(3)}_1 = 1$，我们需要将误差“公平分配”给$a^{(2)}_1 = 1$
4. 到达$a^{(2)}_1$的误差是$\delta^{(3)}_1 \times W^{(2)}_1 = W^{(2)}_1$
5. 和第2不一样，求得将$z^{(2)}_1$映射到a^{(2)}_1$的神经元的导数$f'(z^{(2)}_1)$6. 到达$z^{(2)}_1$的误差$f'(z^{(2)}_1)W^{(2)}_1$，也就是$\delta^{(2)}_1 = 1$7. 然后需要将误差“公平分配”给$W^{(1)}_{14}$，也就是上一步的误差乘以$a^{(4)}_1$8. 因此，最终得到损失函数关于$W^{(1)}_{14}$的偏导数$a^{(4)}_1 f'(z^{(2)}_1) W^{(2)}_{1}$以上我们用链式法则和误差分配反向传播得到的结果是一样的。 偏置项更新：偏置项也可以看成输入向量的一个维度，只不过这个维度始终为1（这种1.1小节中的第二个公式就可以看出）。因此，第$k$层第$i$个神经元偏置项的偏导数直接就是$\delta^{(k)}_i$。例如，在上面我们是要更新$b^{(1)}_1$，而不是$W^{(1)}_{14}$，那么梯度直接就是$f'(z^{(2)}_1) W^{(2)}_{1}$。 将$\delta^{(k)}$到$\delta^{(k-1)}$的误差计算一般化： 图5 从$\delta^{(k)}$到$\delta^{(k-1)}$的误差传播 1. 我们已经有了从$z^{(k)}_i$传回的误差$\delta^{(k)}$，如图5左侧所示 2. 计算反向传给$a^{(k-1)}_j$的误差，通过$\delta^{(k)}_i$乘以路径权重$W^{(k-1)}_{ij}$3. 因此，$a^{(k-1)}_j$接收到的误差就是$\delta^{(k)}_i W^{(k-1)}_{ij}$4. 然而，$a^{(k-1)}_j$可能会前馈到下一层的多个节点，如图5右侧所示。这样的话，$a^{(k-1)}_j$还要接收从$k$层的节点$m$反向传回的误差。 5. 一次，$a^{(k-1)}_j$接收到的误差是$\delta^{(k)}_i W^{(k-1)}_{ij} + \delta^{(k)}_m W^{(k-1)}_{mj}$6. 事实上，这可以一般化为$\sum_i \delta^{(k)}_i W^{(k-1)}_{ij}$7. 现在已经有了$a^{(k-1)}_j$的误差，并且$a^{(k-1)}_j$关于$z^{(k-1)}_j$的导数为$f'(z^{(k-1)}_j)$8. 因此，误差传到了$z^{(k-1)}_j$，记做$\delta^{(k-1)}_j$，大小为$f'(z^{(k-1)}_j) \sum_i \delta^{(k)}_i W^{(k-1)}_{ij}$## 1.6 反向传播训练向量化 用向量化的代码取代for循环，有助于提高代码的执行效率（可以充分利用GPU加速吧？）。 上面我们给出了如何计算一个参数的梯度，现在我们介绍更一般化的方法，一次性地更新整个权重矩阵和偏置向量。这一简单的扩张有助于为我们建立一种直觉，误差传播可以抽象到矩阵-向量级别。 给出一个权重$W^{(k)}_{ij}$，我们定义其误差梯度为$\delta^{(k+1)}_i \cdot a^{(k)}_j$。$W^{(k)}$是将$a^{(k)}$映射为$z^{(k+1)}$的权重矩阵。我们可以建立整个矩阵$W^{(k)}的误差梯度： \begin{align*} \nabla_{W^{(k)}} = \begin{bmatrix} \delta^{(k+1)}_1 a^{(k)}_1 & \delta^{(k+1)}_1 a^{(k)}_2 &\cdots \\ \delta^{(k+1)}_2 a^{(k)}_1 & \delta^{(k+1)}_2 a^{(k)}_2 &\cdots \\ \vdots & \vdots & \ddots \end{bmatrix} = \delta^{(k+1)} a^{(k)T} \end{align*} 下面我们来看如何计算误差向量\delta^{(k)}$。在图5中我们已经知道，$\delta^{(k)}_j = f'(z^{(k)}_j) \sum_i \delta^{(k+1)}_i W^{(k)}_{ij}，这可以一般化为如下的矩阵形式： \begin{align*} \delta^{(k)} = f'(z^{(k)}) \circ (W^{(k)T}\delta^{(k+1)}_i) \end{align*} 其中，\circ$运算符是指矩阵点乘（$\mathbb{R}^N \circ \mathbb{R}^N \rightarrow \mathbb{R}^N$）。 计算效率：我们探索了基于元素的更新和基于矩阵的更新。我们必须意识到，向量化的实现在科学运算环境里效率更高，比如MATLAB和Python的NumPy/SciPy包。因此，我们应该使用向量化的实现。更进一步，在反向传播时应该避免重复计算。比如，$\delta^{(k)}$直接依赖于$\delta^{(k+1)}$。我们应该确保，在使用$\delta^{(k+1)}$更新完$W^{(k)}$之后，不能丢弃，而是要保存训练，用于后面计算$\delta^{(k)}$。重复这一过程$(k-1) \cdots (1)\$。最终得到了一个计算上还负担得起的递归过程。

posted on 2018-06-07 22:05  royhoo  阅读(15104)  评论(0编辑  收藏  举报