深度学习笔记第一门课第二周:神经网络的编程基础(上)

本文是吴恩达老师的深度学习课程[1]笔记部分。

作者:黄海广[2]

主要编写人员:黄海广、林兴木(第四所有底稿,第五课第一二周,第三周前三节)、祝彦森:(第三课所有底稿)、贺志尧(第五课第三周底稿)、王翔、胡瀚文、 余笑、 郑浩、李怀松、 朱越鹏、陈伟贺、 曹越、 路皓翔、邱牧宸、 唐天泽、 张浩、 陈志豪、 游忍、 泽霖、沈伟臣、 贾红顺、 时超、 陈哲、赵一帆、 胡潇杨、段希、于冲、张鑫倩

参与编辑人员:黄海广、陈康凯、石晴路、钟博彦、向伟、严凤龙、刘成 、贺志尧、段希、陈瑶、林家泳、王翔、 谢士晨、蒋鹏

备注:笔记和作业(含数据、原始作业文件)、视频都在 github[3]中下载。

我将陆续将课程笔记发布在公众号“机器学习初学者”,敬请关注。

第二周:神经网络的编程基础(Basics of Neural Network programming)

2.1 二分类(Binary Classification)

这周我们将学习神经网络的基础知识,其中需要注意的是,当实现一个神经网络的时候,我们需要知道一些非常重要的技术和技巧。例如有一个包含个样本的训练集,你很可能习惯于用一个for循环来遍历训练集中的每个样本,但是当实现一个神经网络的时候,我们通常不直接使用for循环来遍历整个训练集,所以在这周的课程中你将学会如何处理训练集。

另外在神经网络的计算中,通常先有一个叫做前向暂停(forward pause)或叫做前向传播(foward propagation)的步骤,接着有一个叫做反向暂停(backward pause) 或叫做反向传播(backward propagation)的步骤。所以这周我也会向你介绍为什么神经网络的训练过程可以分为前向传播和反向传播两个独立的部分。

在课程中我将使用逻辑回归(logistic regression)来传达这些想法,以使大家能够更加容易地理解这些概念。即使你之前了解过逻辑回归,我认为这里还是有些新的、有趣的东西等着你去发现和了解,所以现在开始进入正题。

逻辑回归是一个用于二分类(binary classification)的算法。首先我们从一个问题开始说起,这里有一个二分类问题的例子,假如你有一张图片作为输入,比如这只猫,如果识别这张图片为猫,则输出标签 1 作为结果;如果识别出不是猫,那么输出标签 0 作为结果。现在我们可以用字母 来 表示输出的结果标签,如下图所示:

深度学习笔记第一门课第二周:神经网络的编程基础(上)

我们来看看一张图片在计算机中是如何表示的,为了保存一张图片,需要保存三个矩阵,它们分别对应图片中的红、绿、蓝三种颜色通道,如果你的图片大小为 64x64 像素,那么你就有三个规模为 64x64 的矩阵,分别对应图片中红、绿、蓝三种像素的强度值。为了便于表示,这里我画了三个很小的矩阵,注意它们的规模为 5x4 而不是 64x64,如下图所示:

深度学习笔记第一门课第二周:神经网络的编程基础(上)

为了把这些像素值放到一个特征向量中,我们需要把这些像素值提取出来,然后放入一个特征向量为了把这些像素值转换为特征向量 ,我们需要像下面这样定义一个特征向量  来表示这张图片,我们把所有的像素都取出来,例如 255、231 等等,直到取完所有的红色像素,接着最后是 255、134、…、255、134 等等,直到得到一个特征向量,把图片中所有的红、绿、蓝像素值都列出来。如果图片的大小为 64x64 像素,那么向量  的总维度,将是 64 乘以 64 乘以 3,这是三个像素矩阵中像素的总量。在这个例子中结果为 12,288。现在我们用,来表示输入特征向量的维度,有时候为了简洁,我会直接用小写的来表示输入特征向量的维度。所以在二分类问题中,我们的目标就是习得一个分类器,它以图片的特征向量作为输入,然后预测输出结果为 1 还是 0,也就是预测图片中是否有猫:

深度学习笔记第一门课第二周:神经网络的编程基础(上)

接下来我们说明一些在余下课程中,需要用到的一些符号。

符号定义 :

:表示一个维数据,为输入数据,维度为

:表示输出结果,取值为

:表示第组数据,可能是训练数据,也可能是测试数据,此处默认为训练数据;

:表示所有的训练数据集的输入值,放在一个 的矩阵中,其中表示样本数目;

:对应表示所有训练数据集的输出值,维度为

用一对来表示一个单独的样本,代表维的特征向量, 表示标签(输出结果)只能为 0 或 1。 而训练集将由个训练样本组成,其中表示第一个样本的输入和输出,表示第二个样本的输入和输出,直到最后一个样本,然后所有的这些一起表示整个训练集。有时候为了强调这是训练样本的个数,会写作,当涉及到测试集的时候,我们会使用来表示测试集的样本数,所以这是测试集的样本数:

深度学习笔记第一门课第二周:神经网络的编程基础(上)

最后为了能把训练集表示得更紧凑一点,我们会定义一个矩阵用大写的表示,它由输入向量等组成,如下图放在矩阵的列中,所以现在我们把作为第一列放在矩阵中,作为第二列,放到第列,然后我们就得到了训练集矩阵。所以这个矩阵有列,是训练集的样本数量,然后这个矩阵的高度记为,注意有时候可能因为其他某些原因,矩阵会由训练样本按照行堆叠起来而不是列,如下图所示:的转置直到的转置,但是在实现神经网络的时候,使用左边的这种形式,会让整个实现的过程变得更加简单:

深度学习笔记第一门课第二周:神经网络的编程基础(上)

现在来简单温习一下:是一个规模为乘以的矩阵,当你用Python实现的时候,你会看到X.shape,这是一条Python命令,用于显示矩阵的规模,即X.shape等于是一个规模为乘以的矩阵。所以综上所述,这就是如何将训练样本(输入向量的集合)表示为一个矩阵。

那么输出标签呢?同样的道理,为了能更加容易地实现一个神经网络,将标签放在列中将会使得后续计算非常方便,所以我们定义大写的等于,所以在这里是一个规模为 1 乘以的矩阵,同样地使用Python将表示为Y.shape等于,表示这是一个规模为 1 乘以的矩阵。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

当你在后面的课程中实现神经网络的时候,你会发现,一个好的符号约定能够将不同训练样本的数据很好地组织起来。而我所说的数据不仅包括  或者  还包括之后你会看到的其他的量。将不同的训练样本的数据提取出来,然后就像刚刚我们对  或者  所做的那样,将他们堆叠在矩阵的列中,形成我们之后会在逻辑回归和神经网络上要用到的符号表示。如果有时候你忘了这些符号的意思,比如什么是 ,或者什么是 ,或者忘了其他一些东西,我们也会在课程的网站上放上符号说明,然后你可以快速地查阅每个具体的符号代表什么意思,好了,我们接着到下一个视频,在下个视频中,我们将以逻辑回归作为开始。 备注:附录里也写了符号说明。

2.2 逻辑回归(Logistic Regression)

在这个视频中,我们会重温逻辑回归学习算法,该算法适用于二分类问题,本节将主要介绍逻辑回归的Hypothesis Function(假设函数)。

对于二元分类问题来讲,给定一个输入特征向量,它可能对应一张图片,你想识别这张图片识别看它是否是一只猫或者不是一只猫的图片,你想要一个算法能够输出预测,你只能称之为,也就是你对实际值  的估计。更正式地来说,你想让  表示  等于 1 的一种可能性或者是机会,前提条件是给定了输入特征。换句话来说,如果是我们在上个视频看到的图片,你想让  来告诉你这是一只猫的图片的机率有多大。在之前的视频中所说的,是一个维的向量(相当于有个特征的特征向量)。我们用来表示逻辑回归的参数,这也是一个维向量(因为实际上是特征权重,维度与特征向量相同),参数里面还有,这是一个实数(表示偏差)。所以给出输入以及参数之后,我们怎样产生输出预测值,一件你可以尝试却不可行的事是让

深度学习笔记第一门课第二周:神经网络的编程基础(上)

这时候我们得到的是一个关于输入的线性函数,实际上这是你在做线性回归时所用到的,但是这对于二元分类问题来讲不是一个非常好的算法,因为你想让表示实际值等于 1 的机率的话, 应该在 0 到 1 之间。这是一个需要解决的问题,因为可能比 1 要大得多,或者甚至为一个负值。对于你想要的在 0 和 1 之间的概率来说它是没有意义的,因此在逻辑回归中,我们的输出应该是等于由上面得到的线性函数式子作为自变量的sigmoid函数中,公式如上图最下面所示,将线性函数转换为非线性函数。

下图是sigmoid函数的图像,如果我把水平轴作为轴,那么关于sigmoid函数是这样的,它是平滑地从 0 走向 1,让我在这里标记纵轴,这是 0,曲线与纵轴相交的截距是 0.5,这就是关于sigmoid函数的图像。我们通常都使用来表示的值。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

关于sigmoid函数的公式是这样的,,在这里是一个实数,这里要说明一些要注意的事情,如果非常大那么将会接近于 0,关于sigmoid函数将会近似等于 1 除以 1 加上某个非常接近于 0 的项,因为 的指数如果是个绝对值很大的负数的话,这项将会接近于 0,所以如果很大的话那么关于sigmoid函数会非常接近 1。相反地,如果非常小或者说是一个绝对值很大的负数,那么关于这项会变成一个很大的数,你可以认为这是 1 除以 1 加上一个非常非常大的数,所以这个就接近于 0。实际上你看到当变成一个绝对值很大的负数,关于sigmoid函数就会非常接近于 0,因此当你实现逻辑回归时,你的工作就是去让机器学习参数以及这样才使得成为对这一情况的概率的一个很好的估计。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

继续进行下一步之前,介绍一种符号惯例,可以让参数和参数分开。在符号上要注意的一点是当我们对神经网络进行编程时经常会让参数和参数分开,在这里参数对应的是一种偏置。在之前的机器学习课程里,你可能已经见过处理这个问题时的其他符号表示。比如在某些例子里,你定义一个额外的特征称之为,并且使它等于 1,那么现在就是一个加 1 维的变量,然后你定义sigmoid函数。在这个备选的符号惯例里,你有一个参数向量,这样就充当了,这是一个实数,而剩下的 直到充当了,结果就是当你实现你的神经网络时,有一个比较简单的方法是保持分开。但是在这节课里我们不会使用任何这类符号惯例,所以不用去担心。 现在你已经知道逻辑回归模型是什么样子了,下一步要做的是训练参数和参数,你需要定义一个代价函数,让我们在下节课里对其进行解释。

2.3 逻辑回归的代价函数(Logistic Regression Cost Function)

在上个视频中,我们讲了逻辑回归模型,这个视频里,我们讲逻辑回归的代价函数(也翻译作成本函数)。

为什么需要代价函数:

为了训练逻辑回归模型的参数参数和参数我们,需要一个代价函数,通过训练代价函数来得到参数和参数。先看一下逻辑回归的输出函数:

深度学习笔记第一门课第二周:神经网络的编程基础(上)

为了让模型通过学习调整参数,你需要给予一个样本的训练集,这会让你在训练集上找到参数和参数,,来得到你的输出。

对训练集的预测值,我们将它写成,我们更希望它会接近于训练集中的值,为了对上面的公式更详细的介绍,我们需要说明上面的定义是对一个训练样本来说的,这种形式也使用于每个训练样本,我们使用这些带有圆括号的上标来区分索引和样本,训练样本所对应的预测值是,是用训练样本的然后通过sigmoid函数来得到,也可以把定义为,我们将使用这个符号注解,上标来指明数据表示或者或者或者其他数据的第个训练样本,这就是上标的含义。

损失函数:

损失函数又叫做误差函数,用来衡量算法的运行情况,Loss function:.

我们通过这个称为的损失函数,来衡量预测输出值和实际值有多接近。一般我们用预测值和实际值的平方差或者它们平方差的一半,但是通常在逻辑回归中我们不这么做,因为当我们在学习逻辑回归参数的时候,会发现我们的优化目标不是凸优化,只能找到多个局部最优值,梯度下降法很可能找不到全局最优值,虽然平方差是一个不错的损失函数,但是我们在逻辑回归模型中会定义另外一个损失函数。

我们在逻辑回归中用到的损失函数是:

为什么要用这个函数作为逻辑损失函数?当我们使用平方误差作为损失函数的时候,你会想要让这个误差尽可能地小,对于这个逻辑回归损失函数,我们也想让它尽可能地小,为了更好地理解这个损失函数怎么起作用,我们举两个例子:

时损失函数,如果想要损失函数尽可能得小,那么就要尽可能大,因为sigmoid函数取值,所以会无限接近于 1。

时损失函数,如果想要损失函数尽可能得小,那么就要尽可能小,因为sigmoid函数取值,所以会无限接近于 0。

在这门课中有很多的函数效果和现在这个类似,就是如果等于 1,我们就尽可能让变大,如果等于 0,我们就尽可能让  变小。损失函数是在单个训练样本中定义的,它衡量的是算法在单个训练样本中表现如何,为了衡量算法在全部训练样本上的表现如何,我们需要定义一个算法的代价函数,算法的代价函数是对个样本的损失函数求和然后除以 损失函数只适用于像这样的单个训练样本,而代价函数是参数的总代价,所以在训练逻辑回归模型时候,我们需要找到合适的,来让代价函数  的总代价降到最低。 根据我们对逻辑回归算法的推导及对单个样本的损失函数的推导和针对算法所选用参数的总代价函数的推导,结果表明逻辑回归可以看做是一个非常小的神经网络,在下一个视频中,我们会看到神经网络会做什么。

2.4 梯度下降法(Gradient Descent)

梯度下降法可以做什么?

在你测试集上,通过最小化代价函数(成本函数)来训练的参数

深度学习笔记第一门课第二周:神经网络的编程基础(上)

如图,在第二行给出和之前一样的逻辑回归算法的代价函数(成本函数)

梯度下降法的形象化说明

深度学习笔记第一门课第二周:神经网络的编程基础(上)

这个图中,横轴表示你的空间参数,在实践中,可以是更高的维度,但是为了更好地绘图,我们定义,都是单一实数,代价函数(成本函数)是在水平轴上的曲面,因此曲面的高度就是在某一点的函数值。我们所做的就是找到使得代价函数(成本函数)函数值是最小值,对应的参数

深度学习笔记第一门课第二周:神经网络的编程基础(上)

如图,代价函数(成本函数)是一个凸函数(convex function),像一个大碗一样。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

如图,这就与刚才的图有些相反,因为它是非凸的并且有很多不同的局部最小值。由于逻辑回归的代价函数(成本函数)特性,我们必须定义代价函数(成本函数)为凸函数。初始化

深度学习笔记第一门课第二周:神经网络的编程基础(上)

以用如图那个小红点来初始化参数,也可以采用随机初始化的方法,对于逻辑回归几乎所有的初始化方法都有效,因为函数是凸函数,无论在哪里初始化,应该达到同一点或大致相同的点。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

我们以如图的小红点的坐标来初始化参数

2. 朝最陡的下坡方向走一步,不断地迭代

深度学习笔记第一门课第二周:神经网络的编程基础(上)

我们朝最陡的下坡方向走一步,如图,走到了如图中第二个小红点处。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

我们可能停在这里也有可能继续朝最陡的下坡方向再走一步,如图,经过两次迭代走到第三个小红点处。

3.直到走到全局最优解或者接近全局最优解的地方

通过以上的三个步骤我们可以找到全局最优解,也就是代价函数(成本函数)这个凸函数的最小值点。

梯度下降法的细节化说明(仅有一个参数)

深度学习笔记第一门课第二周:神经网络的编程基础(上)

假定代价函数(成本函数) 只有一个参数,即用一维曲线代替多维曲线,这样可以更好画出图像。

深度学习笔记第一门课第二周:神经网络的编程基础(上)深度学习笔记第一门课第二周:神经网络的编程基础(上)

迭代就是不断重复做如图的公式:

表示更新参数,

 表示学习率(learning rate),用来控制步长(step),即向下走一步的长度 就是函数 求导(derivative),在代码中我们会使用表示这个结果

深度学习笔记第一门课第二周:神经网络的编程基础(上)

对于导数更加形象化的理解就是斜率(slope),如图该点的导数就是这个点相切于 的小三角形的高除宽。假设我们以如图点为初始化点,该点处的斜率的符号是正的,即,所以接下来会向左走一步。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

整个梯度下降法的迭代过程就是不断地向左走,直至逼近最小值点。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

假设我们以如图点为初始化点,该点处的斜率的符号是负的,即,所以接下来会向右走一步。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

整个梯度下降法的迭代过程就是不断地向右走,即朝着最小值点方向走。

梯度下降法的细节化说明(两个参数)

逻辑回归的代价函数(成本函数)是含有两个参数的。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

  表示求偏导符号,可以读作round,  就是函数 对 求偏导,在代码中我们会使用 表示这个结果,  就是函数 求偏导,在代码中我们会使用 表示这个结果, 小写字母 用在求导数(derivative),即函数只有一个参数, 偏导数符号 用在求偏导(partial derivative),即函数含有两个以上的参数。

2.5 导数(Derivatives)

这个视频我主要是想帮你获得对微积分和导数直观的理解。或许你认为自从大学毕以后你再也没有接触微积分。这取决于你什么时候毕业,也许有一段时间了,如果你顾虑这点,请不要担心。为了高效应用神经网络和深度学习,你并不需要非常深入理解微积分。因此如果你观看这个视频或者以后的视频时心想:“哇哦,这些知识、这些运算对我来说很复杂。”我给你的建议是:坚持学习视频,最好下课后做作业,成功的完成编程作业,然后你就可以使用深度学习了。在第四周之后的学习中,你会看到定义的很多种类的函数,通过微积分他们能够帮助你把所有的知识结合起来,其中有的叫做前向函数和反向函数,因此你不需要了解所有你使用的那些微积分中的函数。所以你不用担心他们,除此之外在对深度学习的尝试中,这周我们要进一步深入了解微积分的细节。所有你只需要直观地认识微积分,用来构建和成功的应用这些算法。最后,如果你是精通微积分的那一小部分人群,你对微积分非常熟悉,你可以跳过这部分视频。其他同学让我们开始深入学习导数。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

一个函数,它是一条直线。下面我们来简单理解下导数。让我们看看函数中几个点,假定,那么的 3 倍等于 6,也就是说如果,那么函数。假定稍微改变一点点的值,只增加一点,变为 2.001,这时将向右做微小的移动。0.001 的差别实在是太小了,不能在图中显示出来,我们把它右移一点,现在等于的 3 倍是 6.003,画在图里,比例不太符合。请看绿色高亮部分的这个小三角形,如果向右移动 0.001,那么增加 0.003,的值增加 3 倍于右移的,因此我们说函数,.是这个导数的斜率,或者说,当时,斜率是 3。导数这个概念意味着斜率,导数听起来是一个很可怕、很令人惊恐的词,但是斜率以一种很友好的方式来描述导数这个概念。所以提到导数,我们把它当作函数的斜率就好了。更正式的斜率定义为在上图这个绿色的小三角形中,高除以宽。即斜率等于 0.003 除以 0.001,等于 3。或者说导数等于 3,这表示当你将右移 0.001,的值增加 3 倍水平方向的量。

现在让我们从不同的角度理解这个函数。 假设 ,此时。 把右移一个很小的幅度,增加到 5.001,。 即在 时,斜率是 3,这就是表示,当微小改变变量的值, 。一个等价的导数表达式可以这样写 ,不管你是否将放在上面或者放在右边都没有关系。 在这个视频中,我讲解导数讨论的情况是我们将偏移 0.001,如果你想知道导数的数学定义,导数是你右移很小的值(不是 0.001,而是一个非常非常小的值)。通常导数的定义是你右移(可度量的值)一个无限小的值,增加 3 倍(增加了一个非常非常小的值)。也就是这个三角形右边的高度。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

那就是导数的正式定义。但是为了直观的认识,我们将探讨右移 这个值,即使 0.001 并不是无穷小的可测数据。导数的一个特性是:这个函数任何地方的斜率总是等于 3,不管或 ,这个函数的斜率总等于 3,也就是说不管的值如何变化,如果你增加 0.001,的值就增加 3 倍。这个函数在所有地方的斜率都相等。一种证明方式是无论你将小三角形画在哪里,它的高除以宽总是 3。

我希望带给你一种感觉:什么是斜率?什么是导函数?对于一条直线,在例子中函数的斜率,在任何地方都是 3。在下一个视频让我们看一个更复杂的例子,这个例子中函数在不同点的斜率是可变的。

2.6 更多的导数例子(More Derivative Examples)

在这个视频中我将给出一个更加复杂的例子,在这个例子中,函数在不同点处的斜率是不一样的,先来举个例子:

深度学习笔记第一门课第二周:神经网络的编程基础(上)

我在这里画一个函数,,如果 的话,那么。让我们稍稍往右推进一点点,现在 ,则 (如果你用计算器算的话,这个准确的值应该为 4.004。0.001 我只是为了简便起见,省略了后面的部分),如果你在这儿画,一个小三角形,你就会发现,如果把往右移动 0.001,那么将增大四倍,即增大 0.004。在微积分中我们把这个三角形斜边的斜率,称为在点 处的导数(即为 4),或者写成微积分的形式,当 的时候,  由此可知,函数,在取不同值的时候,它的斜率是不同的,这和上个视频中的例子是不同的。

这里有种直观的方法可以解释,为什么一个点的斜率,在不同位置会不同如果你在曲线上,的不同位置画一些小小的三角形你就会发现,三角形高和宽的比值,在曲线上不同的地方,它们是不同的。所以当 时,斜率为 4;而当时,斜率为 10 。如果你翻看微积分的课本,课本会告诉你,函数的斜率(即导数)为。这意味着任意给定一点,如果你稍微将,增大 0.001,那么你会看到将增大,即增大的值为点在处斜率或导数,乘以你向右移动的距离。

现在有个小细节需要注意,导数增大的值,不是刚好等于导数公式算出来的值,而只是根据导数算出来的一个估计值。

为了总结这堂课所学的知识,我们再来看看几个例子:

深度学习笔记第一门课第二周:神经网络的编程基础(上)

假设 如果你翻看导数公式表,你会发现这个函数的导数,等于。所以这是什么意思呢,同样地举一个例子:我们再次令,所以 ,如果我们又将增大一点点,你会发现, 你可以自己检查一遍,如果我们取 8.012,你会发现 ,和 8.012 很接近,事实上当时,导数值为,即。所以导数公式,表明如果你将向右移动 0.001 时, 将会向右移动 12 倍,即 0.012。

来看最后一个例子,假设,有些可能会写作,函数 的斜率应该为,所以我们可以解释如下:如果取任何值,比如又取,然后又把向右边移动 0.001 那么将增大,如果你借助计算器的话,你会发现当 ;而时,。所以增大了 0.0005,如果你查看导数公式,当的时候,导数值。这表明如果你把 增大 0.001,将只会增大 0.001 的二分之一,即 0.0005。如果你画个小三角形你就会发现,如果 轴增加了 0.001,那么 轴上的函数,将增大 0.001 的一半 即 0.0005。所以  ,当时这里是 ,就是当时这条线的斜率。这些就是有关,导数的一些知识。

在这个视频中,你只需要记住两点:

第一点,导数就是斜率,而函数的斜率,在不同的点是不同的。在第一个例子中 ,这是一条直线,在任何点它的斜率都是相同的,均为 3。但是对于函数 ,或者,它们的斜率是变化的,所以它们的导数或者斜率,在曲线上不同的点处是不同的。

第二点,如果你想知道一个函数的导数,你可参考你的微积分课本或者*,然后你应该就能找到这些函数的导数公式。

最后我希望,你能通过我生动的讲解,掌握这些有关导数和斜率的知识,下一课我们将讲解计算图,以及如何用它来求更加复杂的函数的导数。

2.7 计算图(Computation Graph)

可以说,一个神经网络的计算,都是按照前向或反向传播过程组织的。首先我们计算出一个新的网络的输出(前向过程),紧接着进行一个反向传输操作。后者我们用来计算出对应的梯度或导数。计算图解释了为什么我们用这种方式组织这些计算过程。在这个视频中,我们将举一个例子说明计算图是什么。让我们举一个比逻辑回归更加简单的,或者说不那么正式的神经网络的例子。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

我们尝试计算函数是由三个变量组成的函数,这个函数是 。计算这个函数实际上有三个不同的步骤,首先是计算  乘以 ,我们把它储存在变量中,因此; 然后计算;最后输出,这就是要计算的函数。我们可以把这三步画成如下的计算图,我先在这画三个变量,第一步就是计算,我在这周围放个矩形框,它的输入是,接着第二步,最后一步。 举个例子:  ,就是 6, ,就是 5+6=11。是 3 倍的 ,因此。即。如果你把它算出来,实际上得到 33 就是的值。 当有不同的或者一些特殊的输出变量时,例如本例中的和逻辑回归中你想优化的代价函数,因此计算图用来处理这些计算会很方便。从这个小例子中我们可以看出,通过一个从左向右的过程,你可以计算出的值。为了计算导数,从右到左(红色箭头,和蓝色箭头的过程相反)的过程是用于计算导数最自然的方式。 概括一下:计算图组织计算的形式是用蓝色箭头从左到右的计算,让我们看看下一个视频中如何进行反向红色箭头(也就是从右到左)的导数计算,让我们继续下一个视频的学习。

2.8 使用计算图求导数(Derivatives with a Computation Graph)

在上一个视频中,我们看了一个例子使用流程计算图来计算函数 J。现在我们清理一下流程图的描述,看看你如何利用它计算出函数的导数。

下面用到的公式:

 ,  , 

这是一个流程图:

深度学习笔记第一门课第二周:神经网络的编程基础(上)

假设你要计算,那要怎么算呢?好,比如说,我们要把这个值拿过来,改变一下,那么的值会怎么变呢?

所以定义上,现在,所以如果你让增加一点点,比如到 11.001,那么,所以我这里增加了 0.001,然后最终结果是上升到原来的 3 倍,所以,因为对于任何  的增量都会有 3 倍增量,而且这类似于我们在上一个视频中的例子,我们有,然后我们推导出,所以这里我们有,所以,这里扮演了的角色,在之前的视频里的例子。

在反向传播算法中的术语,我们看到,如果你想计算最后输出变量的导数,使用你最关心的变量对的导数,那么我们就做完了一步反向传播,在这个流程图中是一个反向步骤。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

我们来看另一个例子,是多少呢?换句话说,如果我们提高的数值,对的数值有什么影响?

好,我们看看这个例子。变量,我们让它增加到 5.001,那么对 v 的影响就是,之前,现在变成 11.001,我们从上面看到现在 就变成 33.003 了,所以我们看到的是,如果你让增加 0.001,增加 0.003。那么增加,我是说如果你把这个 5 换成某个新值,那么的改变量就会传播到流程图的最右,所以最后是 33.003。所以 J 的增量是 3 乘以的增量,意味着这个导数是 3。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

要解释这个计算过程,其中一种方式是:如果你改变了,那么也会改变,通过改变,也会改变,所以值的净变化量,当你提升这个值(0.001),当你把值提高一点点,这就是的变化量(0.003)。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

首先 a 增加了,也会增加,增加多少呢?这取决于,然后的变化导致也在增加,所以这在微积分里实际上叫链式法则,如果影响到影响到,那么当你让变大时,的变化量就是当你改变时,的变化量乘以改变的变化量,在微积分里这叫链式法则。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

我们从这个计算中看到,如果你让增加 0.001,也会变化相同的大小,所以。事实上,如果你代入进去,我们之前算过,所以这个乘积 3×1,实际上就给出了正确答案,

这张小图表示了如何计算,就是对变量的导数,它可以帮助你计算,所以这是另一步反向传播计算。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

现在我想介绍一个新的符号约定,当你编程实现反向传播时,通常会有一个最终输出值是你要关心的,最终的输出变量,你真正想要关心或者说优化的。在这种情况下最终的输出变量是 J,就是流程图里最后一个符号,所以有很多计算尝试计算输出变量的导数,所以输出变量对某个变量的导数,我们就用命名,所以在很多计算中你需要计算最终输出结果的导数,在这个例子里是,还有各种中间变量,比如,当你在软件里实现的时候,变量名叫什么?你可以做的一件事是,在python中,你可以写一个很长的变量名,比如,但这个变量名有点长,我们就用,但因为你一直对求导,对这个最终输出变量求导。我这里要介绍一个新符号,在程序里,当你编程的时候,在代码里,我们就使用变量名,来表示那个量。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

好,所以在程序里是表示导数,你关心的最终变量的导数,有时最后是,对代码中各种中间量的导数,所以代码里这个东西,你用表示这个值,所以,你的代码表示就是

深度学习笔记第一门课第二周:神经网络的编程基础(上)

好,所以我们通过这个流程图完成部分的后向传播算法。我们在下一张幻灯片看看这个例子剩下的部分。

我们清理出一张新的流程图,我们回顾一下,到目前为止,我们一直在往回传播,并计算,再次,是代码里的变量名,其真正的定义是。我发现,再次,是代码里的变量名,其实代表的值。

深度学习笔记第一门课第二周:神经网络的编程基础(上)

大概手算了一下,两条直线怎么计算反向传播。

好,我们继续计算导数,我们看看这个值,那么是多少呢?通过和之前类似的计算,现在我们从出发,如果你令增加到 6.001,那么之前是 11,现在变成 11.001 了, 就从 33 变成 33.003,所以 增量是 3 倍,所以。对的分析很类似对 a 的分析,实际上这计算起来就是,有了这个,我们可以算出,最终算出结果是

深度学习笔记第一门课第二周:神经网络的编程基础(上)

所以我们还有一步反向传播,我们最终计算出,这里的当然了,就是

现在,我们仔细看看最后一个例子,那么呢?想象一下,如果你改变了的值,你想要然后变化一点,让 值到达最大或最小,那么导数是什么呢?这个函数的斜率,当你稍微改变值之后。事实上,使用微积分链式法则,这可以写成两者的乘积,就是,理由是,如果你改变一点点,所以变化比如说 3.001,它影响 J 的方式是,首先会影响,它对的影响有多大?好,的定义是,所以时这是 6,现在就变成 6.002 了,对吧,因为在我们的例子中,所以这告诉我们当你让增加 0.001 时,就增加两倍。所以,现在我想的增加量已经是的两倍,那么是多少呢?我们已经弄清楚了,这等于 3,所以让这两部分相乘,我们发现

好,这就是第二部分的推导,其中我们想知道  增加 0.002,会对 有什么影响。实际上,这告诉我们 u 增加 0.002 之后,上升了 3 倍,那么 应该上升 0.006,对吧。这可以从推导出来。

如果你仔细看看这些数学内容,你会发现,如果变成 3.001,那么就变成 6.002,变成 11.002,然后,对吧?这就是如何得到

深度学习笔记第一门课第二周:神经网络的编程基础(上)

为了填进去,如果我们反向走的话,,而其实是Python代码中的变量名,表示

深度学习笔记第一门课第二周:神经网络的编程基础(上)

我不会很详细地介绍最后一个例子,但事实上,如果你计算,这个结果是 9。

我不会详细说明这个例子,在最后一步,我们可以推出

深度学习笔记第一门课第二周:神经网络的编程基础(上)

所以这个视频的要点是,对于那个例子,当计算所有这些导数时,最有效率的办法是从右到左计算,跟着这个红色箭头走。特别是当我们第一次计算对的导数时,之后在计算对导数就可以用到。然后对的导数,比如说这个项和这里这个项:

深度学习笔记第一门课第二周:神经网络的编程基础(上)

可以帮助计算对的导数,然后对的导数。

所以这是一个计算流程图,就是正向或者说从左到右的计算来计算成本函数 J,你可能需要优化的函数,然后反向从右到左计算导数。如果你不熟悉微积分或链式法则,我知道这里有些细节讲的很快,但如果你没有跟上所有细节,也不用怕。在下一个视频中,我会再过一遍。在逻辑回归的背景下过一遍,并给你介绍需要做什么才能编写代码,实现逻辑回归模型中的导数计算。

参考资料

[1]

深度学习课程: https://mooc.study.163.com/university/deeplearning_ai

[2]

黄海广: https://github.com/fengdu78

[3]

github: https://github.com/fengdu78/deeplearning_ai_books

深度学习笔记第一门课第二周:神经网络的编程基础(上)