Processing math: 100%
Home

拼搭小怪

智能体设计师


Blog Github

吴恩达机器学习:神经网络 | 反向传播算法

上一周我们学习了 神经网络 | 多分类问题。我们分别使用 逻辑回归神经网络 来解决多分类问题,并了解到在特征数非常多的情况下,神经网络是更为有效的方法。这周的课程会给出训练 神经网络 所使用的 代价函数,并使用 反向传播 算法来计算梯度。笔者会给出 反向传播 算法中重要的思路和推导,但不会包含所有的计算步骤。

点击 课程视频 你就能不间断地学习 Ng 的课程,关于课程作业的 Python 代码已经放到了 Github 上,点击 课程代码 就能去 Github 查看,代码中的错误和改进欢迎大家指出。

以下是 Ng 机器学习课程第四周的笔记。

代价函数

假设我们的多分类问题有 K 个分类,神经网络共有 L 层,每一层的神经元个数为 sl,那么神经网络的 代价函数 为:

J(Θ)=1mmi=1Kk=1(y(i)klog(hΘ(x(i)))k+(1y(i)k)log(1(hΘ(x(i)))k))+λ2mL1l=1sli=1sl+1j=1(Θ(l)ji)2

其中的第二项为 正则化 项,是网络中所有权值的平方和。第一项与逻辑回归中的 代价函数 类似,但这里我们需要累加所有输出神经元的误差。

梯度计算

为了能够使用 梯度下降 算法来训练网络,我们需要计算代价函数的梯度。一种很直观的方法就是使用数值计算,对于某个 Θij,给它加上减去一个很小的量 ϵ 来计算梯度:

J(θ)θjJ(θ1,,θj+ϵ,,θn)J(θ1,,θjϵ,,θn)2ϵ

但稍微分析一下算法的复杂度就能知道,这样的方法十分缓慢。对于每一组数据,我们需要计算所有权值的梯度,总的计算次数 = 训练数据个数 x 网络权值个数 x 前向传播计算次数 。在通常情况下这样的复杂度是无法接受的,所以我们仅使用这个方法来验证 反向传播 算法计算的梯度是否正确。

链式法则

为了能够理解之后对于 反向传播 公式的推导,我们首先要了解一个关于多元复合函数求导的 链式法则。对于多元函数 z=f(u,v),其中 u=h(x,y)v=g(x,y),那么:

zx=zuux+zvvxzy=zuuy+zvvy

链式法则 告诉我们有多个层次的多元复合函数,下一层次的导数可以由上一层次推得。

上图中笔者有意多加了一层,这里 pu,v 的函数,qu,v 的函数,zp,q 的函数。对于要计算的 zxzy,上式仍成立,原因是我们可以把 z 看作 u,v 的函数。这相当于我们把:

zx=zppuux+zppvvx+zqquux+zqqvvx

简化为了只与上一层相关,利用上一层计算完成的结果 zuzv 而不用从头算起:

zx=zuux+zvvx

一般的,对于函数 y,如果它能看做 z1,z2,zn 的函数,而 zit 的函数,则:

yt=ni=1yzizit

神经网络就是一个层次很多的多元函数,我们可以隐约从 链式法则 中感觉到反向传播的意味。

公式推导

为了施展 反向传播 的魔法,我们首要要引入一个中间变量 δ,定义为:

δlj=Jzlj

其中 l 为第几层,j 表示第 l 层的第几个神经元,z 为上次课程提到的中间变量( 为了让式子看上去更清晰,反向传播 中的公式上标不使用括号 )。δ 被称为第 l 层第 j 个神经元的误差。反向传播 就是先计算每一层每个神经元的误差,然后通过误差来得到梯度的。

首先来看输出层的误差:

δLj=JzLj

对它使用 链式法则 得到:

δLj=Kk=1JaLkaLkzLj

而只有当 k==j 时,右边部分才不为 0,所以:

δLj=JaLjaLjzLj=JaLjg(zLj)=aLjyLj

对于其它层的误差:

δlj=Jzlj

使用 链式法则

δlj=sl+1k=1Jzl+1kzl+1kzlj=sl+1k=1δl+1kzl+1kzlj

而其中:

zl+1k=slp=1Θlkpg(zlp)+blk

求偏导得:

zl+1kzlj=Θlkjg(zlj)

所以:

δlj=sl+1k=1Θlkjδl+1kg(zlj)=sl+1k=1Θlkjδl+1kalj(1alj)

最后同样使用 链式法则 来计算:

JΘlij=sl+1k=1Jzl+1kzl+1kΘlij=slk=1δl+1kzl+1kΘlij

由于:

zl+1k=slp=1Θlkpg(zlp)+blk

只有当 k=ip=j 时留下一项:

JΘlij=g(zlj)δl+1i=aljδl+1i

反向传播

有了 (1) (2) (3) 式,就可以来完成 反向传播 算法了( 需要注意的是刚才所推导的式子都是针对一组训练数据而言的 )。

  1. 对于所有的 l,i,j 初始化 Δlij=0
  2. 对于 m 组训练数据,k1 取到 m
    • a1=x(k)
    • 前向传播,计算各层激活向量 al
    • 使用 (1) 式,计算输出层误差 δL
    • 使用 (2) 式,计算其它层误差 δL1,δL2,...,δ2
    • 使用 (3) 式,累加 ΔlijΔlij:=Δlij+aljδl+1i
  3. 计算梯度矩阵:Dlij={1mΔlij+λmΘlijif j01mΔlijif j=0
  4. 更新权值 Θl:=Θl+αDl

权值初始化

最后提一下权值的初始化。对于神经网络,不能像之前那样使用相同的 0 值来初始化,这会导致每层的 逻辑单元 都相同。因此我们使用随机化的初始化方法,使得 δΘlijδ

So~,这周学完了 神经网络 和它的学习算法,大家有没有觉得很神奇呢?


拼搭小怪

2018-04-14

Blog Github