继续对吴恩达的《深度学习工程师》做笔记总结。
向量化
上一篇笔记中,已经通过数学公式归纳出一个样本输入到神经网络中,并计算其输出递归公式,这一篇继续学习如何将 m 个样本整合到一个矩阵中,也就是吴恩达课程中的 向量化 的内容。
为什么要向量化?
主要目的是为了提升计算速度。向量化编程(或称矢量化编程)最早出现在Matlab编程语言中,因为Matlab或者Python都是解析执行的,使用for循环的效率较低,通过使用向量化编程来用编译后的向量化计算库来替代for循环的解析执行,并加上对并行计算的特性的利用,计算性能会大大提高。
按照吴恩达的套路,一定会举个例子,以下面这个网络为例:
按照之前给出的公式:
这里稍微有点变化,用 g[l](z[l]) 代替了 σ(z[l]),因为每一个隐层的激活函数可能都不一样。
对于一个样本:
对于 m 个样本,将 (3, 1) 的列向量组合成 (3, m) 的矩阵:
这里的 x(i) 表示第 i 个样本。
用 Z[1] 来表示对 m 个样本的第一层的加权求和:
其中的 z[1](i) 是 (3, 1) 的列向量,因此 Z[1] 是一个(3, m) 的矩阵。将其中每一列展开:
这里的 w[1](i) 以及 b[1](i) 是一样的,因为对于 m 个样本来讲,神经元的参数是一致的。所以,可以简化为:
以此类推:
这就是 所有样本 输入 神经网络 的递归公式了。
矩阵的维度
前文中,我们说矩阵的维度时用 3x5 来表达,现在我们用 (3, 5) 来表达,在Python中这样的数据结构是 Tuple 类型。在NumPy中numpy.array
对象的shape
属性返回的就是就是这样一个结构:
import numpy as np;
ary = 10 * np.random.rand(4,3)
print(ary.shape) # 输出:(4, 3)
以图1 - 4层神经网络为例,回顾一下各种表达:
- L,表示神经网络的层数,这里 L=4。
- n[l],表示神经网络第 l 层的神经元个数,在这个例子中,n[1]=4, n[2]=5, n[3]=3, n[4]=1。同时,也可以用 n[0]=3 表示输入层的特征(feature)数。
- a[l]表示第l层的所有神经元的激活状态(也就是输出),a[l]=g[l](z[l]),同时 a[0] = x 是输入层,ŷ = a[L] 表示最终的输出。
- w[l],表示第 l 层的每个输入的权重。
- b[l],表示第 l 层每个神经元的内部强度。
以 一个样本x输入 为例下面来计算下 z, w, b的维度,以第一层 z[1] = w[1]x + b[1] 为例:
z[1] | w[1] | x | b[1] | |
---|---|---|---|---|
维度 | (4,1) | (4,3) | (3,1) | (4,1) |
归纳 | (n[1], 1) | (n[1], n[0]) | (n[0], 1) | (n[1], 1) |
以此类推,得出:
- w[l] 的维度为 (n[l], n[l-1]),dw[l]的维度也一样。
- b[l] 的维度为 (n[l], 1),db[l]的维度也一样。
- z[l] 的维度为 (n[l], 1),dz[l]的维度也一样。
- a[l] 的维度为 (n[l], 1),da[l]的维度也一样。
这里也新出现了两个变量,后面在梯度下降法中会用到。
以m个样本的输入为例,向量化后公式为:Z[l]=w[l]X[l-1] + b[l],其中, w[l] 和 b[l] 的维度与向量化之前一样(向量化一节的推导过程可以清楚的表明这一点)。
Z[1] | w[1] | X | b[1] | |
---|---|---|---|---|
维度 | (4,m) | (4,3) | (3,m) | (4,m) |
归纳 | (n[1], m) | (n[1], n[0]) | (n[0], m) | (n[1], m) |
- Z[l] 的维度为 (n[l], m),dZ[l]的维度也一样。
- A[l] 的维度为 (n[l], m),dA[l]的维度也一样。
这里需要的注意的是,虽然上b[l] 是一个 (n[1], m) 的矩阵,但实际上,是 (n[1], 1) 的矩阵水平扩展到 m 列的,每一列都一样。而且在Python中,因为Python的Broadcasting功能,在计算“矩阵+向量”的时候,Python会将向量自动水平扩展到和矩阵同样的维度,所以吴恩达的课程中仍然将 b[l] 认为是 (n[1], 1) 的向量。
成本函数
我们先回顾下单个神经元的 Logistic Regresion ,公式是这样的:
如果我们希望让我们的机器学习结果能更准确,也就是希望对于样本{(x(1), y(1)), (x(2), y(2)),...,(x(m), y(m))}来说,要找到一组w和b的值,使得根据x(i)计算出来的结果 ŷ(i) 能尽可能接近 y(i)。
可是,“尽可能接近”这种说法有点说不清、摸不着,所以我们就把问题转化一下,引出损失函数的概念。
Loss function
对于一个样本(x, y),输出为 ŷ,一般情况下,我们可以误差的平方来定义 损失函数(Loss function 或者 Error function),我印象中大学物理就是用这种方法,形式如下:
吴恩达说,在 Logsitic Regression 中一般不这么做,因为当求解参数的时候优化问题会变成 非凸 的,会导致有很多局部最优解,进而导致 梯度下降法 无法找到全局最优解。
在 Logistic Regression 中,一般使用这样一个损失函数:
在这个公式中,当ŷ越接近于y时,这个函数的值就越小。吴恩达并没有给出严谨的数学证明,只是简单地代入两个极限值0和1来举例(还记得σ(z)的最大值上限和最小值下限分别就是1和0吗?):
- 如果 y=1,则 L(ŷ, y)=-log(ŷ),只有当ŷ趋近于最大值1时,-log(ŷ) 才达到最小
- 如果 y=0,则 L(ŷ, y)=-log(1-ŷ),只有当 ŷ 趋近于最小值0时,-log(1-ŷ) 才达到最小
Cost function
上面的 损失函数(Lost function) 是针对一个样本的,对于 m 个样本,我们定义 成本函数(Cost function) 为:
特别注意的是,前面的 Loss function 的参数是 y 和 ŷ,但是 Cost function 的参数是 w 和 b,也就是说,我们会通过一些方法来求解 w 和 b 使得全局的 Cost function J(w,b) 最小。而这个“方法”就是梯度下降法。
小结
这一部分我总结了向量化、矩阵的维度以及Cost function。我们的学习脉络是:一个神经元到一层神经网络,再到多层神经网络,再到多样本输入的神经网络,这个过程梳理清楚了,学习就容易了。
下一步要学习和总结 计算图,以及如何通过 梯度下降法 求解 w[l] 和 b[l],会涉及到一些 导数、偏导数。本文中已经逐渐开始学习到 numpy 的用法了,如果不了解的话,对吴恩达课程讲解的公式会不容易理解,下一篇也会总结。
如果你喜欢本文,请不要吝啬你的点赞或打赏~ 同时,欢迎你通过评论来一起交流或指正文中的错误
请关注我的账号,预计会以一周一篇的频率进行更新~
下一篇已更新,请戳:《AI学习笔记:[3]梯度下降和反向传播》