神经网络中的正向传播与反向传播

1. 正向传播

1. 概述

我们知道, 一个简单的神经网络可以是这样的, 分为多个层, 输入层、隐藏层和输出层. 在层与层之间, 有权重 $w_{ij}^k$ , 表示第k层的第i个节点到下一层的第j个节点的权重. 再每一层, 都会有个激活函数, 用于归一化, 也可以说是计算该层节点的输出.

所谓正向传播, 就是依据这一过程由输入层一直延续到输出层.

2. 例

以下图所示为例. neural-network 在Input Layer,输出项就是4个元素 $x_1, x_2, x_3, x_4$

在Hidden Layer, 输入项是: $$ h_{in_j} = \sum_i^4{x_i*w_{ij}^{in_h}} (j=1,2,3) $$ 于是, 输出项为: $$ h_{out_j} = f_h(h_{in_j}) (j=1,2,3) $$

在Output Layer, 输入项是: $$ y_{in} = \sum_i^3{h_{out_j}*w_{i}^{h_out}} $$ 于是, 输出项为: $$ y_{out} = f_o(y_{in}) $$

从 $x_i$ 到 $y_{out}$ 的整个过程便是正向传播的过程.

2. 反向传播

1. 概述

反向传播是神经网络的精髓所在, 将整个神经网络反转过来, 由后向前递推, 进而将误差值向输入层推进, 由此算出每个 $w_{ij}^k$ , 正是反向传播的算法, 使得优化 $w_{ij}^k$ 变得有效.

2. 简析

由梯度下降算法可以推出以下图为例的$w_i$的优化公式为: $$ \frac{\partial E}{\partial w_i} = \frac{1}{2}*\frac{\partial (y - f(h))^2}{\partial w_i} = -(y-f(h)) * f^{'}(h) * x_i = -\delta * x_i $$ $$ \Delta w_i = \eta * \delta * x_i $$ enter image description here 而这是远远不够的, 一个神经网络是多层的, 这个只能计算出输出层的前一层的 $w_i$.

以一个两层神经网络为例(仅有隐藏层和输出层,不包含输入层).

为了通过梯度下降算法更新隐藏层的权重, 我们需要知道每个隐藏层单元对最终输出层的贡献. 既然输出层取决于前面每层之间的权重, 那么误差也是取决于正向传播中的权重, 既然我们已经知道输出层的误差了, 便可以通过权重反向传播到隐藏层.

比如, 在输出层, 我们知道每个节点的误差$\delta_k^o$, 我们就可以把误差贡献到隐藏层: $$ \delta_j^h = \sum_k{w_{jk}^h * \delta_k^o * f^{'}(h_j)} $$ 接下来, 像之前那样, 通过新的误差, 更新由输入层到隐藏层之间的权重 $$ \Delta w_{ij} = \eta * \delta_j^h * x_i $$ 这样的方法同样适用于多层的网络, 权重改变等于 步长大小(学习率) * 该层输出误差 * 该层输入. $$ \Delta w_{pq} = \eta * \delta_{output} * V_{in} $$ 值得注意的是: 此处的 $\delta_{output}$ 指的是通过反向传播更新过的误差, $V_{in}$ 指的是该层的输入值.

3. 例

以一个两层神经网络为例(仅有隐藏层和输出层,不包含输入层)来演示一下如何计算权重的更新值. 假定有两个输入, 一个隐藏层单元, 一个输出单元, 在隐藏层和输出层上使用sigmoid激活函数. 网络描述如下图所示. (注意, 底部的输入层显示为节点, 网络的输出值显示为顶部的 $\hat y$ 输入本身并不被计算为一层, 这也是为什么被认为是两层神经网.)

backprop-network

假定我们想尝试拟合一些数据, 并且目标值是 $y = 1$ . 我们先正向传播, 首先, 我们计算隐藏层单元的输入值: $$ h_{in} = \sum_i{w_i^{i_h}x_i} = 0.1 * 0.4 + (-0.2) * 0.3 = - 0.02 $$ 然后计算隐藏层单元的输出: $$ h_{out} = f(h_{in}) = sigmoid(-0.02) = 0.485. $$ 将此作为输出层单元的输入值, 那么神经网络的输出为: $$ \hat y = f(w^{h_o} * h_{out}) = sigmoid(0.1 * 0.495) = 0.512. $$ 根据神经网络的输出, 我们便可以进行反向传播来计算两层的权重更新了,使用sigmoid函数的导函数作为因子 $f^{'}(w^{h_o} * h_{out}) = f(w^{h_o} * h_{out}) * (1 - f(w^{h_o} * h_{out}))$ , 那么输出单元的误差项为: $$ \delta_{o} = (y - \hat y)f^{'}(w^{h_o} * h_{out}) = (1 - 0.512) * 0.512 * (1 - 0.512) = 0.122. $$ 现在, 我们需要通过反向传播计算隐藏层的误差项. 对于隐藏层, 误差项, $\delta_j^h = \sum_k{w_{jk}^h * \delta_k^o * f^{'}(h_j)}$, 由于我们只有一个输出单元和一个隐藏单元, 这会比较简单点. $$ \delta^h = w^{h_o} \delta^o f^{'}(h) = 0.1 * 0.122 * 0.495 * (1 - 0.495) = 0.003 $$ 现在, 我们已经又了这些误差了, 便可以计算梯度下降步长了. 隐藏层到输出层的权重步长为: 学习率 * 输出单元误差 * 隐藏层激活函数值(输出层的输入值). $$ \Delta w^{h_o} = \eta * \delta^o * h_{out} = 0.5 * 0.122 * 0.495 = 0.0302 $$ 对于输入层到隐藏层的权重 $w_i^{i_h}$ , 它等于学习率 * 隐藏层误差 * 输入值. $$ \Delta w_1^{i_h} = \eta * \delta^h * x_1 = 0.5 * 0.003 * 0.1= 0.00015 \newline \Delta w_2^{i_h} = \eta * \delta^h * x_2 = 0.5 * 0.003 * 0.3 = 0.00045 $$

以上就是整个反向传播的过层了. 同样, 这是一次更新的过程, 经过多次迭代, 就能得到优化后的各个层之间的权重.


发表评论

    

最新评论

    还没有人评论...

Powered by Django 2. Copyright © 2014.

huchengbei.com. All rights reserved.