Forward and Backward Propagation
Last updated
Was this helpful?
Last updated
Was this helpful?
在上节课里 我们学习了搭建深度神经网络时所需的基本模块 比如每层都有前向传播的步骤 以及对应的反向传播的步骤 这节课我们会讲一下如何实现这些步骤 首先 我们来说前向传播 回忆一下 这一步做的是输入a[l-1] 输出a[l] 以及将z[l]放入缓存 而在实践中 我们也同样会把w[l]和b[l]放入缓存 这样调用起来会比较容易 下面这个的公式大家应该很熟悉了 前向函数就是z[l]=w[l]a[l-1]+b[l] 其中a[l]是作用于z[l]的激活函数 如果你想用向量化来实现 那就是Z[l]=W[l]A[l-1]+b[l] 这里加上的b能通过python的广播来实现 (详见第二周Broadcasting in Python课程) A[l]是将激活函数作用于矩阵Z[l]每一个元素后得到的结果 你应该还记得 在前向传播的计算导图中 我们曾经画了这样一个前向流程图 通过输入a[0]来进行初始化 这里的a[0]就是X 所以初始化的这个 就是最上面这个输入值 如果你只有一个训练样本 a[0]就是这个训练样本的输入特征 如果你在处理整个训练集 代表整个训练集的输入特征 这就是前向传播计算导图的初始输入值 然后以此类推 就能从左到右计算前向传播 接着 我们来讨论反向传播 这个代表输入da[l] 输出da[l-1]和dW[l]以及db[l] 我来写一下需要用到计算步骤 dz[l]=da[l]g[l]'(z[l]) da[l]与g矩阵元素依次相乘 然后 计算导数 dW[l]=dz[l]a[l-1] 这里我没有写把它们放入缓存 但是你要记得这是必须的 接着db[l]=dz[l] 最后da[l-1]=W[l]转置乘以dz[l] 在这里我不会把求导过程写出来 但结果是 若将da的定义代入这里 你会得到一个我们之前上课见过的公式 即用之前的dz[l]来计算新的dz[l] 如果我在这里代入 你会得到dz[l]=w[l+1]转置乘以dz[l+1]乘以g[l]‘(z[l]) 我知道这里看起来有很多公式 不用担心 这些公式以前都出现过 就是上周我们 在学习单隐藏层神经网络时 见过的反向传播等式 注意 这里是矩阵元素依次相乘 所以其实只需要这四个等式来进行反向函数计算 最后 我们来写一下向量化的版本 第一行就是dZ[l]=dA[l]与 g[l]'(Z[l])的元素乘积 这比较容易理解 dW[l]等于1/m乘以dZ[l]*A[l-1]转置 然后db[l]等于1/m乘以np.sum(dZ[l]) np.sum(dZ[l], axis=1, keepdims=True) 上周我们讲过使用np.sum来计算db的方法 最后dA[l-1]等于W[l]转置乘以dZ[l] 这个公式模型能通过输入da[l] 这里 和这里 来输出dW[l]和db[l] 以及da[l-1] 这些你需要的导数 这就是构建反向函数的方法 总结一下 对于输入x 第一层 也许有一个ReLU激活函数 第二层 可能会使用另一个ReLU激活函数 到第三层 如果你要做二元分类 可能会用Sigmoid激活函数 以及输出结果y帽 通过y帽 可以计算出损失 然后就可以开始向后迭代了 我们先把箭头都画好 这样之后就不用一直换笔了 这里我们会用反向传播计算导数 来得到dw[3] db[3] dw[2] db[2] dw[1] db[1] 在此过程中 缓存输出z[1] z[2] z[3] 这里会反向传播da[2]和da[1] 然后就可以计算da[0] 但这并没有意义 所以我们直接将它去掉就好了 以上就是实现一个三层神经网络 前向传播和反向传播的流程 现在 还有最后一个细节没讲 当前向传播时 我们会用输入数据X来进行初始化 那反向传播又是如何初始化的呢? 当你使用逻辑回归 做二元分类时 da[l] 等于 -y/a+(1-y)/(1-a) 可以得出最终输出的 损失函数对y帽求导 结果就是这样的形式 如果你熟悉微积分 可以尝试推导损失函数L 对y帽或者a求导 你就会得到这个公式 这个输出da的公式会用在最终层L上 当然 如果要使用向量化实现 先要初始化反向传播 在L层用dA[l]代表这个公式 即使对不同的例子来说 这也是一样的 对第一个训练样本dA[l]=(-y[1]/a[1]) 加上(1-y[1])/(1-a[1]) 从第一个训练样本 一直到第m个训练样本 最后除以(1-a[m]) 这是实现向量化的方法 也就是如何初始化一个向量化版本反向传播的方法 现在 我们已经学习了前向传播 以及反向传播的基础知识 如果你尝试使用这些公式 可以通过前向传播以及反向传播 来得到你需要的导数 你也许会觉得公式过多不便于理解 开始迷茫 不知道这些公式能干什么 如果你有这样的困扰 我建议 当你在本周的编程实践时 亲手实现这些步骤 这会让你的理解更加深刻 这节课有很多公式 也有些公式不容易弄懂 如果有条件的话 你最好自己用微积分 和线性代数知识来推导一遍 我知道这有难度 所以这并不强求 事实上 这已经是机器学习中比较困难的推导了 这些课程中列出的公式 或者说微积分公式 仅仅是反向传播中的导数计算 再强调一下 如果你觉得这些公式看起来有点抽象 不容易理解 我的建议是 认真完成作业 然后就会豁然开朗 但我不得不说 即便是现在 当我实现一个机器学习算法的时候 有时我也会惊讶 我的机器学习算法被证明有效 是因为机器学习的复杂度来源于数据而非一行行的代码 所以 有时候你会觉得 你写了几行代码 但不确定代码在干什么 最后它们竟然产生了神奇的结果 因为实际上大部分神奇的地方并不在你写的 几行短短的代码中 可能并不是真的那么短 但不会是成千上万行 的代码 而是碰巧输入了大量数据 即使我已经从事机器学习很多年了 有时候我依然感到意外 我的机器学习算法起效是因为算法的复杂度来源于数据 而不一定是 你写的成千上万行的代码 好了 这就是实现深度神经网络的方法 再提醒大家一下 你完成课后作业就会更了解一些 在进入下一个话题前 下个视频中 我们会讨论超参数和参数 当你在训练深度网络时 若能正确调整超参数 会让深度神经网络开发工作更为高效 我们下期见 翻译 | 审阅:Cousera Global Translator Community