吴恩达机器学习:神经网络 | 反向传播算法
上一周我们学习了 神经网络 | 多分类问题。我们分别使用 逻辑回归 和 神经网络 来解决多分类问题,并了解到在特征数非常多的情况下,神经网络是更为有效的方法。这周的课程会给出训练 神经网络 所使用的 代价函数,并使用 反向传播 算法来计算梯度。笔者会给出 反向传播 算法中重要的思路和推导,但不会包含所有的计算步骤。
点击 课程视频 你就能不间断地学习 Ng 的课程,关于课程作业的 Python 代码已经放到了 Github 上,点击 课程代码 就能去 Github 查看,代码中的错误和改进欢迎大家指出。
以下是 Ng 机器学习课程第四周的笔记。
代价函数
假设我们的多分类问题有 K 个分类,神经网络共有 L 层,每一层的神经元个数为 sl,那么神经网络的 代价函数 为:
J(Θ)=−1mm∑i=1K∑k=1(y(i)klog(hΘ(x(i)))k+(1−y(i)k)log(1−(hΘ(x(i)))k))+λ2mL−1∑l=1sl∑i=1sl+1∑j=1(Θ(l)ji)2其中的第二项为 正则化 项,是网络中所有权值的平方和。第一项与逻辑回归中的 代价函数 类似,但这里我们需要累加所有输出神经元的误差。
梯度计算
为了能够使用 梯度下降 算法来训练网络,我们需要计算代价函数的梯度。一种很直观的方法就是使用数值计算,对于某个 Θij,给它加上减去一个很小的量 ϵ 来计算梯度:
∂J(θ)∂θj≈J(θ1,⋯,θj+ϵ,⋯,θn)−J(θ1,⋯,θj−ϵ,⋯,θn)2ϵ但稍微分析一下算法的复杂度就能知道,这样的方法十分缓慢。对于每一组数据,我们需要计算所有权值的梯度,总的计算次数 = 训练数据个数 x 网络权值个数 x 前向传播计算次数 。在通常情况下这样的复杂度是无法接受的,所以我们仅使用这个方法来验证 反向传播 算法计算的梯度是否正确。
链式法则
为了能够理解之后对于 反向传播 公式的推导,我们首先要了解一个关于多元复合函数求导的 链式法则。对于多元函数 z=f(u,v),其中 u=h(x,y),v=g(x,y),那么:
∂z∂x=∂z∂u∂u∂x+∂z∂v∂v∂x∂z∂y=∂z∂u∂u∂y+∂z∂v∂v∂y链式法则 告诉我们有多个层次的多元复合函数,下一层次的导数可以由上一层次推得。
上图中笔者有意多加了一层,这里 p 是 u,v 的函数,q 是 u,v 的函数,z 是 p,q 的函数。对于要计算的 ∂z∂x 与 ∂z∂y,上式仍成立,原因是我们可以把 z 看作 u,v 的函数。这相当于我们把:
简化为了只与上一层相关,利用上一层计算完成的结果 ∂z∂u 和 ∂z∂v 而不用从头算起:
∂z∂x=∂z∂u∂u∂x+∂z∂v∂v∂x一般的,对于函数 y,如果它能看做 z1,z2⋯,zn 的函数,而 zi 为 t 的函数,则:
∂y∂t=n∑i=1∂y∂zi∂zi∂t神经网络就是一个层次很多的多元函数,我们可以隐约从 链式法则 中感觉到反向传播的意味。
公式推导
为了施展 反向传播 的魔法,我们首要要引入一个中间变量 δ,定义为:
δlj=∂J∂zlj其中 l 为第几层,j 表示第 l 层的第几个神经元,z 为上次课程提到的中间变量( 为了让式子看上去更清晰,反向传播 中的公式上标不使用括号 )。δ 被称为第 l 层第 j 个神经元的误差。反向传播 就是先计算每一层每个神经元的误差,然后通过误差来得到梯度的。
首先来看输出层的误差:
δLj=∂J∂zLj对它使用 链式法则 得到:
δLj=K∑k=1∂J∂aLk∂aLk∂zLj而只有当 k==j 时,右边部分才不为 0,所以:
δLj=∂J∂aLj∂aLj∂zLj=∂J∂aLjg′(zLj)=aLj−yLj对于其它层的误差:
δlj=∂J∂zlj使用 链式法则:
δlj=sl+1∑k=1∂J∂zl+1k∂zl+1k∂zlj=sl+1∑k=1δl+1k∂zl+1k∂zlj而其中:
zl+1k=sl∑p=1Θlkpg(zlp)+blk求偏导得:
∂zl+1k∂zlj=Θlkjg′(zlj)所以:
δlj=sl+1∑k=1Θlkjδl+1kg′(zlj)=sl+1∑k=1Θlkjδl+1kalj(1−alj)最后同样使用 链式法则 来计算:
∂JΘlij=sl+1∑k=1∂J∂zl+1k∂zl+1k∂Θlij=sl∑k=1δl+1k∂zl+1k∂Θlij由于:
zl+1k=sl∑p=1Θlkpg(zlp)+blk只有当 k=i,p=j 时留下一项:
∂JΘlij=g(zlj)δl+1i=aljδl+1i反向传播
有了 (1) (2) (3) 式,就可以来完成 反向传播 算法了( 需要注意的是刚才所推导的式子都是针对一组训练数据而言的 )。
- 对于所有的 l,i,j 初始化 Δlij=0
- 对于 m 组训练数据,k 从 1 取到 m:
- 令 a1=x(k)
- 前向传播,计算各层激活向量 al
- 使用 (1) 式,计算输出层误差 δL
- 使用 (2) 式,计算其它层误差 δL−1,δL−2,...,δ2
- 使用 (3) 式,累加 Δlij,Δlij:=Δlij+aljδl+1i
- 计算梯度矩阵:Dlij={1mΔlij+λmΘlijif j≠01mΔlijif j=0
- 更新权值 Θl:=Θl+αDl
权值初始化
最后提一下权值的初始化。对于神经网络,不能像之前那样使用相同的 0 值来初始化,这会导致每层的 逻辑单元 都相同。因此我们使用随机化的初始化方法,使得 −δ≤Θlij≤δ。
So~,这周学完了 神经网络 和它的学习算法,大家有没有觉得很神奇呢?
拼搭小怪
2018-04-14