上一篇回顾:《AI学习笔记:[2]神经网络向量化和成本函数》
回忆一下:要求解的问题
上一节学到成本函数 J(w,b) ,我们的目标是:求解 w 和 b 使得全局的成本J(w,b) 最小。
回顾一下成本函数 J(w,b):
再回顾一下神经网络的递推公式:
这里:
- w[l] 的维度为 (n[l], n[l-1])
- b[l] 的维度为 (n[l], 1)
因此,对于 L 层神经网络,我们要求出 (n[0] * n[1] + n[1] * n[2] + ... + n[L-1] * n[L]) 个 w[l](i) 以及 (n[1]+...+n[L]) 个 b[l](i),这里的 w[l] 和 b[l](i) 都是实数。
以如下这个2层的神经网络为例:
其中:
- L=2,n[0]=2, n[1]=4, n[2]=1
- 要求解的对象 w[1] 为 (2, 4) 的矩阵,w[2] 为 (4, 1) 的矩阵,共 8 个 w;
- 要求解的对象 b[1] 为 (4, 1) 的列向量,b[2] 为 (1, 1) 的列向量,共 5 个 b。
梯度下降法
梯度下降法是一种求最优解(但并不一定是真正的解,只是无限接近真正解)的算法。用负梯度方向为搜索方向,最速下降法越接近目标值,步长越小,前进越慢。详见 维基百科-梯度下降法
举个例子可能更好理解。
比如函数:f(x)=x2-2x,高中数学告诉我们,这个函数的顶点为 (1, -1),其最小值为-1。
首先求解f '(x):
我们尝试用梯度下降法求解其最小值的方法 Python 代码为:
def f(x):
return x**2 - 2*x
def df(x):
return 2*x - 2
def gd(start_x, step_x, iter_cnt, df):
"""
Args:
start_x 起点
step_x 迭代步长,也称为learing rate
iter_cnt 迭代次数
df 函数f(x)的导数
"""
x = start_x
for i in range(iter_cnt):
g = df(x)
x -= g * step_x
print('[%2d] x=%f df(x)=%f f(%f)=%f' %(i, x, g, x, f(x)))
if abs(g) < 1e-6:
break;
return x
# 从x=5起步,每次往前走0.05,迭代100次,前面定义的df当做导数函数传入
gd(5, 0.05, 100, df)
输出结果为:
[ 0] x=4.600000 df(x)=8.000000 f(4.600000)=11.960000
[ 1] x=4.240000 df(x)=7.200000 f(4.240000)=9.497600
[ 2] x=3.916000 df(x)=6.480000 f(3.916000)=7.503056
[ 3] x=3.624400 df(x)=5.832000 f(3.624400)=5.887475
[ 4] x=3.361960 df(x)=5.248800 f(3.361960)=4.578855
[ 5] x=3.125764 df(x)=4.723920 f(3.125764)=3.518873
[ 6] x=2.913188 df(x)=4.251528 f(2.913188)=2.660287
[ 7] x=2.721869 df(x)=3.826375 f(2.721869)=1.964832
...
[24] x=1.287159 df(x)=0.638132 f(1.287159)=-0.917540
...
[35] x=1.090114 df(x)=0.200252 f(1.090114)=-0.991880
...
[99] x=1.000106 df(x)=0.000236 f(1.000106)=-1.000000
可以看到,开始的时候,梯度较大,因此下降速度很快,0到24步就逼近了1.9,而后面的35到99步才缓慢逼近到1.0,f(x) 找到的点(1.000106, -1.0) 非常接近于(1, -1)。
在神经网络中,由于变量 w 和 b 都是多维度的,因此问题从“求一个自变量函数的导数”转变成“多变量函数的偏导数”。如下图所示:
用三维的图形表示就是,实际上神经网络远远比三维图形要复杂,用直观的方式无法表达。
数学回顾(1):导数以及链式法则
梯度下降法里面很重要的一步是求导数,然而并不是所有的函数都像x2-2x这么规范、这么容易求导的,这时候就要用到反向传播。但在学习反向传播之前,我们先重拾一下 导数 以及在神经网络中非常重要的 求导链式法则。
导数的计算公式和四则运算法则:
导数的链式法则:
数学回顾(2):偏导数以及计算方法
偏导数的定义详见:偏导数
正向传播以及反向传播
我们再来看一下整个神经网络的计算过程,先以 Logistic Regression 为例。
始终牢记在心里:我们最终是为了求解 w 和 b,使得 J(w,b) 最小。因此,我们要先求解 dw 和 db,然后通过梯度下降法,每个迭代中通过 w=w-dw,不断地往前找,一直找到 dw 接近0为止(梯度为0,为最小值)。
再强调一下,在吴恩达的课程中,dw表示的是dL(a,y)/dw,可以认为只取了分母而忽略了分子。
如下图所示,正向传播分成三个步骤:
- 计算z
- 计算a
- 计算L(a, y)
相反,我们需要计算的 dw, db,使用链式法则可以计算出,如图所示:
对图中的公式进行整理,如下:
所以,我们最终需要计算如下四个算子:
da、dz、dw、db的计算步骤如下图所示,注意其中计算 dσ(z)/dz 的计算过程和前文中的一样。
最终得到:
最终,我们得到了 dw 和 db 的计算公式,将其代入到梯度下降算法,当 dw 趋近于
0 以及 db 趋近于 0 时对应的 w 和 b 就是我们要找的值。
不知不觉中又写了不少了,这里只讲解到逻辑斯蒂回归的反向传播,多层神经网络网络的反向传播以及对应的伪代码就留到下次继续了。
提到反向传播,最近有一个比较有意思的新闻是《被Geoffrey Hinton抛弃,反向传播为何饱受质疑?(附BP推导)》,至少学习完这个课程,你可以看懂这篇新闻了。的确,像Hinton所说的那样,人类大脑的原理并不是反向传播,其实吴恩达也在各种各样的场合反复撇清深度学习和人类大脑的关系,虽然人工智能的概念被炒作得非常火,但是我们还是应该意识到,深度学习只是一种更好的机器学习方法而已,至于人类大脑是怎么运作的,我们还知之甚少,更不用说去模拟或者仿造了。但是我们也应该感到自豪的是,人类已经开始往这个方向努力,就和文艺复兴一样,多年以后回首会认为这是一个非常了不起的时代。
下一步
学到这里,一直是比较枯燥的数学推导,吴恩达非常讲究实战与理论结合,因此下一周首先将反向传播学习完,然后开始做课后练习了。我看GitHub上有人将课后Programming Assignments & Quiz Solutions,也是非常贴心的。
如果你喜欢本文,请不要吝啬你的点赞或打赏~ 同时,欢迎你通过评论来一起交流或指正文中的错误
请关注我的账号,预计会以一周一篇的频率进行更新~