understanding back propagation

8 minute read

接下来的posts可能会focus在deep learning这一块,可能是真的太火了,觉得自己也得具备这个基本的知识库。 自己也算是初学, 望大家指点。

在neutral network的training中 back propagation 算法很关键 我的学习方式是决定直接读 Hindon的那片文章 《Learning representations by back-propagating erros》

对于learning system的描述 直接翻译一小段

最简单的分层网络学习过程通常是:最低层是输入单元, 有任意数目的中间层, 最高层是输出单元, 每一层内单元的不会有互联, 也不会有跨层的互联,但是可以跳过这些中间层。 一个输入向量就是设置输入单元的状态。 每一层的单元的状态就是根据底下一层的输出当作输入由方程(1)和(2)来计算。 每一层的计算被当作是并行, 但是层与层之间是串行, 这样自底往上的计算知道输出单元被决定。

假设 一个 linear 的系统 input-output function

xj=iyiwji  (1)

xj 是 对unit j的全部输入, yi 是unit i的输出 通过一个权重wji 连接到unit j

到state的mapping输出 通常是一个non-linear函数

yj=11+exj  (2)

xj是这个单元的所有输入

其实觉得这里的notation不是很好,不利于后面的思考,读者不妨把j想象成是当前层, 而i是之前的那一层就行了 这里的意思就是说 前一层的输出经过加权就是这一层的输入, 然后再经过方程(2)转成这一层的输出, 方程(2)相当于模拟了神经元 这是一个sigmoid函数 方程(1)还可以加bias这里为了简洁没有写入. 根据 Hinton的 paper 里说的, 第一个函数可以是任意的, 只要有 bounded derivative, 但是一般用一个linear function来combine inputs 到一个unit再用 non-linear 能够简化这个学习的过程。

那么学习的过程其实就是找到一组 weights 能够确保 每一组输入对应的输出能够尽最大可能的贴近真值。

如果有有限的输入和输出, 那么总的错误 E 可以表示为

E=12cj(yj,cdj,c)2  (3)

其中c是所有训练输入的index, j是输出的index, y是实际的输出 d是期待的输出

要想最小化E, 首先需要求导这样可以用梯度下降的方法 因为我们的未知数是权重, 而权重是一个向量, 因此对于每一个维度,我们是求一个偏导

这里有一个 forward pass 是 equations (1)和(2): 每一层的states是尤其从前一层得到的输入来决定的

而 back pass 是指从最高层到最低层来传播的

back pass 始于 从 Error function (3) E 来求对 y 的偏导

E/yj=yjdc

这里有求导的 chain rule 因为我们知道

Exj=Eyjdyjdxj

带入方程 (2)

(1+ex)1dx=1(1+ex)2d(1+ex)dx

d(1+ex)dx=d(ex)dx=exd(x)dx=ex

很多年没做过chain rule求导了 差点脑死亡

结果是稍作变形

Exj=Eyjex(1+ex)2=Eyjyj(1yj)  (5)

这个结果的含义是 我们知道了 当前层的jth unit的total input x 如何影响 error 因为 yj 可以完全用 xj 表示, 然后这个xj其实是由之前一层的(yi)的线性加权wji 所以可以进一步的求出 这些state和权重对于error 的影响。

同样的 对于wji 表示是 前一层 index i 到 这一层 index j 的 weight

Ewji=Exjdxjdwji=Exjyi  (4)

表示 weight wji 和 前一层state 对于 error 的影响

此外还有 前一层 unit i的输出 yi 对于 Eyi 的 从 前一层i 到 这一层j 的 贡献, Exjxjyi=Exjwji

所以做一个summation就是前一层unit i发射出的所有connection

Eyi=jExjwji  (6)

现在我们知道如何为倒数第二层计算 Eyi 当我们知道最后一层的 Eyj 的话

因为 Eyi=jExjwji=jEyjyj(1yj)wji

因此我们可以不停的向前计算 结合当前层和前一层之间的权重得到前一层 Ey,用方程 (4)可以来计算 E/w

一开始 weight 都是 random 选取的

更新 weight 的方式, 有每输入一组input-output case就更新 这样不需要存导数

另一种是在输入 input-output case的过程 先accumulate E/w 直到全部输入完 再更新权重

这里就用梯度下降每次减少一点点 Δw=εE/w 这个虽然没有二阶导下降的快,但是简单好实现容易用硬件来并行计算

一种改进是 用当前的gradient来修改其在 weight space 的速度而不是position Δw(t)=εE/w(t)+αΔw(t1) t 每次sweep through the whole set of input-output cases, 加1

α 是 exponential decay factor (0-1),

Example

接下来 用代码来验证一下 代码中标记了和上面方程式的对应关系。

Network如图

Network

Code

{% gist yishanhe/79f06cfa94b0e692698a %}

cost output

[ 0.02553798]
[ 0.02085472]
[ 0.01765256]
[ 0.01538757]
[ 0.01374046]
[ 0.01251489]
[ 0.01158523]
[ 0.01086832]
[ 0.01030757]
[ 0.00986344]
[ 0.00950775]
[Finished in 0.393s]

Reference