梯度下降 我们看到了成本函数 的可视化,以及如何尝试选择不同的参数 和 。如果我们有一种更系统的方法来找到 和 的值,从而得到、 的最小成本 。事实证明,有一种称为梯度下降 的算法可实现这一点。梯度下降 在机器学习中随处可见,不仅用于线性回归 ,还用于训练一些最先进的神经网络模型,也称为深度学习模型 。
梯度下降 奠定机器学习中最重要的基石之一。这里有最小化的 的成本函数 。目前看到的例子中,这是线性回归 的成本函数 ,事实证明,梯度下降 是一种可用于尝试最小化任何函数的算法,而不仅仅是线性回归 的成本函数 。梯度下降 适用于更一般的函数,包括两个以上参数的模型的成本函数 。例如,如果你有一个成本函数 ,它是 和 的函数,你的目标是最小化参数 和 上的 。换句话说,你想为 和 选择值,从而给出 的最小可能值。事实证明,梯度下降 是一种可用于尝试最小化成本函数 的算法。你要做的只是从 和 的一些初始猜测开始。在线性回归 中,初始值是什么并不重要,因此常见的选择是将它们都设置为0
。例如,您可以将 设置为0
,将 设置为0
作为初始猜测。使用梯度下降算法 ,您要做的就是,每次都稍微改变参数 和 ,以尝试降低 的成本 ,直到 稳定在最小值或接近最小值。我应该注意的一件事是,对于某些可能不是弓形或吊床形的函数 ,可能存在多个可能的最小值。让我们看一个更复杂的曲面图 的示例,看看梯度在做什么。
此函数不是平方误差成本函数 。对于具有平方误差成本函数的线性回归 ,您总是会得到弓形或吊床形。但如果您训练神经网络模型,您可能会得到这种类型的成本函数。注意轴,即底部轴上的 和 。对于不同的 和 值,你会得到这个曲面上的不同点, 的 ,其中曲面在某个点的高度是成本函数 的值。现在,让我们想象一下,这个曲面图实际上是一个略微丘陵的户外公园,其中高点是山丘,低点是山谷,就像这样。想象一下,你现在正站在山上的这个点上。如果这能帮助你放松,想象一下有很多非常漂亮的绿草、蝴蝶和鲜花,这是一座非常漂亮的山。你的目标是从这里出发,尽可能高效地到达其中一个山谷的底部。梯度下降算法 的作用是,你要旋转360
度,环顾四周,问自己,如果我要朝一个方向迈出一小步,我想尽快下坡到其中一个山谷。我会选择朝哪个方向迈出这一小步?如果你想尽可能高效地走下这座山,那么如果你站在山上的这个点上环顾四周,你会发现,你下一步下山的最佳方向大致就是那个方向。从数学上讲,这是下降速度最快的方向。意味着,当你迈出一小步时,这会比你朝其他方向迈出一小步的速度更快。迈出第一步后,你现在就站在山上的这个点上。现在让我们重复这个过程。站在这个新的点上,你将再次旋转360
度,问自己,下一步我要朝哪个方向迈出一小步才能下山?如果你这样做,再迈出一步,你最终会朝那个方向移动一点,然后你就可以继续走下去了。从这个新的点开始,你可以再次环顾四周,决定哪个方向可以让你最快地下山。再走一步,再走一步,等等,直到你发现自己到了山谷的底部,到了这个局部最小值,就在这里。你刚才做的是经过多步梯度下降 。梯度下降 有一个有趣的特性。你可以通过选择参数 和 的起始值来选择表面的起点。刚才执行梯度下降 时,你是从这里的这个点开始的。现在,想象一下,如果你再次尝试梯度下降,但这次你选择一个不同的起点,通过选择将你的起点放在这里右边几步的参数。如果你重复梯度下降过程,这意味着你环顾四周,朝着最陡峭的上升方向迈出一小步,你就会到达这里。然后你再次环顾四周,再迈出一步,依此类推。如果你第二次运行梯度下降 ,从我们第一次执行的位置的右边几步开始,那么你最终会到达一个完全不同的山谷。右边这个不同的最小值。第一个和第二个山谷的底部都称为局部最小值 。因为如果你开始沿着第一个山谷向下走,梯度下降不会带你到第二个山谷,同样,如果你开始沿着第二个山谷向下走,你会停留在第二个最小值,而不会找到进入第一个局部最小值的路。
让我们看看如何实现梯度下降算法 。在每一步中,参数 都会更新为 。这个表达式的意思是,取 的当前值并对其进行少量调整,也就是右边的这个表达式,减去 乘以这里的这个项。
具体来说,在这个上下文中,如果你写的代码是 ,这意味着取值 并将其存储在你的计算机中,在变量 中。或者你写 ,意味着将 的值设置为 。在Python
和其他编程语言中,真值断言有时写成等于,所以如果你在测试 是否等于 。在这个等式中, 也称为学习率 。学习率 通常是0~1
之间的一个正数,比如0.01
。 的作用是,它基本上控制你下坡的步数。如果 非常大,那么这相当于一个非常激进的梯度下降 过程。如果 非常小,那么你就会小步走下坡路。最后,这里的这个项是成本函数 的导数项。结合学习率 ,它还决定了你想要走下坡路的步数。记住模型有两个参数,不仅仅是 ,还有 。你还有一个赋值操作来更新看起来非常相似的参数 。 。记住,在曲面图的图形中,你一步步地走,直到到达值的底部,对于梯度下降算法 ,你将重复这两个更新步骤,直到算法收敛。所谓收敛 ,意思是你到达局部最小值,此时参数 和 不再随着你采取的每个额外步骤而发生很大变化。现在,关于如何正确地进行语义梯度下降 ,还有一个更微妙的细节,你将更新两个参数 和 。一个重要的细节是,对于梯度下降 ,你想同时更新 和 ,在这个表达式中,你将把 从旧的 更新为新的 ,你还将把 从最旧值更新为新的 值。实现的方法是计算右边,计算 和 的值,同时将 和 更新为新值。这是实现梯度下降 的正确方法,它会同时进行更新。当你听到有人谈论梯度下降 时,是指执行参数同步更新的梯度下降 。
这个希腊符号 ,是学习率 。学习率 控制更新模型参数 和 时采取的步长。这个 ,是一个导数项。让我们使用一个稍微简单的例子,最小化一个参数。假设你只有一个参 的成本函数 ,其中 是一个数字。梯度下降 现在看起来像这样, 。你试图通过调整参数 来最小化成本。现在,我们来初始化梯度下降,并为 设定一个起始值。在这个位置初始化它。你从函数 的这个点开始,梯度下降会将 更新为 。让我们看看这里的导数项是什么意思。考虑直线上这一点的导数的一种方法是画一条切线,它是一条在该点与曲线相切的直线。这条线的斜率是函数 在该点的导数。要得到斜率,你可以画一个像这样的小三角形。如果你计算这个三角形的高度除以宽度,那就是斜率 。例如,这个斜率可能是2/1
,当切线指向右上方时,斜率为正,这意味着这个导数是一个正数,所以大于0
。更新后的 将是 减去学习率乘以某个正数。学习率 始终是正数。如果用 减去一个正数,最终会得到一个较小的 新值。在图表上,向左移动, 的值就会减小。您可能会注意到,如果您的目标是降低成本 ,那么这样做是正确的,因为当我们沿着这条曲线向左移动时,成本 会减小,并且您会越来越接近 的最小值。到目前为止,梯度下降似乎做得对。现在,让我们看另一个例子。让我们采用与上面相同的 函数 ,现在假设您在不同的位置初始化梯度下降。比如说,通过选择 的起始值,它就在左边。这就是函数 的点。导数项是 ,当我们查看此处的切线时,这条线的斜率就是 在此点的导数。但是这条切线是向右下方倾斜的。这条向右下方倾斜的线具有负斜率。换句话说, 在这一点的导数是负数。例如,如果你画一个三角形,那么像这样的高度是-2
,宽度是1
,斜率就是-2/1
,也就是-2
,这是一个负数。当你更新 时,你会得到 减去学习率乘以一个负数。这意味着你从 中减去一个负数。但减去一个负数意味着增加一个正数,所以你最终会增加 。梯度下降的这一步会导致 增加,意味着你正在向图的右侧移动。梯度下降算法 中的另一个关键量是学习率 。
学习率 学习率 的选择将对梯度下降 的效率产生巨大影响。 。要了解有关学习率 的更多信息。让我们看看学习率 太小或太大会发生什么。对于学习率太小的情况。这是一张图表,其中横轴是 ,纵轴是成本 。从此处开始分级下降,如果学习率太小。这个数字非常小,比如0.0000001
。所以你最终会迈出一小步。然后从这一点开始,你将迈出另一个微小的婴儿步。但由于学习率非常小,第二步也微不足道。这个过程的结果是,你最终会降低成本 ,但速度非常慢。但你可能会注意到,你需要很多步才能达到最小值。总结一下,如果学习率太小,那么梯度下降 会起作用,但速度会很慢。这将需要很长时间,因为它需要采取这些微小的婴儿步。而且它需要很多步才能接近最小值。如果学习率太大会发生什么?这是成本函数的另一张图。假设我们从这里的 值开始缓慢下降。实际上,它已经非常接近最小值了。但是,如果学习率太大,那么你就会以非常大的步长更新 。现在,成本变得更糟了。如果学习率太大,那么你又会加速迈出一大步,再次超过最小值。所以现在你到了右边的这个点,再一次进行更新。您可能会注意到,您实际上离最小值越来越远。如果学习率太大,那么创建的感觉可能会超调,并且可能永远无法达到最小值。换句话说,大交叉点可能无法收敛,甚至可能发散 。假设有成本函数 。您在这里看到的不是平方误差成本函数,并且该成本函数有两个局部最小值,对应于您在这里看到的两个谷值。现在假设经过一些梯度下降步骤后,您的参数 就在这里,比如等于5
。这是 的当前值。这意味着你现在处于成本函数 的这个点。如果你注意这个点的函数,就会发现这恰好是一个局部最小值。这条线的斜率为零。如果你已经处于局部最小值,梯度下降将使 保持不变。因为它只是将 的新值更新为与 的旧值完全相同。具体来说,假设 的当前值为5
。一次迭代后,它仍然等于5
。因此,如果你的参数已经将你带到了局部最小值,然后进一步的梯度下降会趋于零。它不会改变参数,这正是你想要的,因为它将解决方案保持在局部最小值。这也解释了为什么梯度下降可以达到局部最小值,即使学习率 固定。这是我们想要最小化的 的成本函数 。让我们在这一点初始化梯度下降。如果我们采取一个更新步骤,也许它会带我们到那个点。而且因为这个导数相当大,所以梯度下降会采取一个相对较大的步骤。现在,我们处于第二个点,我们再迈出一步。你可能会注意到斜率不像第一个点那么陡峭。所以导数没有那么大。所以下一个更新步骤不会像第一步那么大。这里的第三点,导数比上一步要小。当我们接近最小值时,它会采取更小的步骤。越来越接近零。因此,当我们运行梯度下降时,最终我们会采取非常小的步长,直到最终达到局部最小值。当我们接近局部最小值时,梯度下降 将自动采取较小的步长。这是因为当我们接近局部最小值时,导数 会自动变小。这意味着更新步骤也会自动变小。学习率 保持在某个固定值。这就是梯度下降算法 ,你可以用它来尝试最小化任何成本函数 。不仅仅是均方误差成本函数 。
线性回归的梯度下降 如下图所示,这是线性回归模型 。右边是平方误差成本函数 。下面是梯度下降算法 。如果您计算这些导数,您将得到这些项。关于 的导数是 , 的范围是 `。然后是误差项 ,即预测值与实际值之间的差乘以输入特征 。关于 的导数是这里的公式,它看起来与上面的公式相同,只是最后没有那个 项。如果您使用这些公式来计算这两个导数并以这种方式实现梯度下降 ,它就会起作用。现在,你可能想知道,我从哪里得到这些公式?它们是使用微积分 推导出来的。如何计算导数项 。让我们从第一项开始。成本函数 对 的导数。我们首先代入成本函数 的定义 。我们想要做的是计算这个方程的导数,也称为 的偏导数。带入公式推导出:
根据您初始化参数 和 的位置,您可能会得到不同的局部最小值。当你在线性回归 中使用平方误差成本函数 时,成本函数永远不会有多个局部最小值。它只有一个全局最小值 。这个成本函数是一个凸函数。通俗地说,凸函数 是碗状函数,除了单个全局最小值外,它不能有任何局部最小值。当你在凸函数 上实现梯度下降 时,只要你选择适当的学习率 ,它就会一直收敛到全局最小值 。
让我们看看在线性回归 中运行梯度下降 时会发生什么?如下图所示,左上角是模型和数据的图,右上角是成本函数 的轮廓图,底部是同一成本函数的表面图。通常 和 都会初始化为0
,但为了演示,我们初始化 和 。因此这对应于 。如果我们使用梯度下降 迈出一步,最终会从成本函数的这一点向右下方移动到下一点,注意到直线拟合也发生了一点变化。成本函数 现在已移至第三个点,并且函数 也发生了一些变化。随着更多步骤,每次更新的成本都会下降。所以参数 和 遵循这个轨迹。看左边,你会看到相应的直线拟合越来越好,直到我们达到全局最小值。全局最小值对应于这个直线拟合,它与数据的拟合相对较好。这就是梯度下降 ,我们将用它来拟合模型以适配数据。
多元线性回归 如果您不仅有房屋的大小作为预测价格的特征,而且您还知道卧室数量、楼层数量和房屋的年限,会怎么样呢?这似乎会为您提供更多信息来预测价格。为了引入一些新的符号,我们将使用变量 和 来表示这四个特征。为了简单起见,有时会简称为 ,来表示特征列表。 将从1~4
。使用小写 来表示特征总数,因此在此示例中, 。与之前一样,使用 来表示第 个训练示例。这里 实际上是一个包含四个数字的列表,将其称为包含第 个训练示例的所有特征的向量。括号中的 将是第二个训练示例的特征向量,因此它将等于 1416、3、2 和 40,从技术上讲,我将这些数字写成一行,因此有时这被称为行向量而不是列向量。但如果你不知道它们的区别是什么,也不用担心,这对于这个目的来说并不重要。为了引用第 i 个训练示例中的特定特征,例如, 将是第三个特征的值,即第二个训练示例中的层数,因此它将等于2
。有时为了强调 不是一个数字,而是一个数字列表,它是一个向量,我们会在其上方画一个箭头,以直观地显示它是一个向量,这里也是如此,但你不必在你的符号中画出这个箭头。你可以将箭头视为一个可选的符号。它们有时仅用于强调这是一个向量而不是数字。现在我们有了多个特征,让我们来看看模型是什么样子的。我们是这样定义模型的,其中 是一个单一特征,也就是一个数字。但是现在有了多个特征,我们将对其进行不同的定义。相反,模型将是 。具体来说,对于房价预测,一个可能的模型可能是我们将房价估计为 。让我们思考一下如何解释这些参数。如果模型试图预测房屋以千美元为单位的价格,你可以将这个 视为房屋的基本价格从80,000
美元开始,假设房屋没有大小、没有卧室、没有楼层和没有年龄。你可以把这个0.1
想象成,每增加一平方英尺,价格就会增加0.1
美元,因为我们说的是每平方英尺的价格增加0.1
乘以1,000
美元,也就是100
美元。也许每增加一个浴室,价格就会增加4,000
美元,每增加一层楼,价格可能会增加10,000
美元,而房子的年龄每增加一年,价格可能会下降2,000
美元,因为参数是-2
。一般来说,如果你有 个特征,那么模型看起来会像这样。具有 个特征的模型的定义。接下来我们要做的就是引入一些符号,以更简单等效的方式重写这个表达式。让我们将 定义为一个数字列表,其中列出了参数 。在数学中,这被称为向量 。接下来, 是单个数字而不是向量,因此这个向量 和数字 一起构成了模型的参数。让我将 写成一个列表或向量,同样是一个行向量,它列出了所有特征 。现在可以更简洁地将模型重写为 的 等于向量 的点,这个点指的是向量 的线性代数的点积,加上数字 。这个点积 是什么?两个数字列表 和 的两个向量的点积 是通过检查相应的数字对 来计算的, 和 相乘, 相乘, 相乘,一直到 和 相乘,然后将所有这些乘积相加。最后将 相加。点流量符号允许您以更紧凑的形式和更少的字符编写模型。这种具有多个输入特征 的线性回归模型 的名称为多元线性回归 。这与只有一个特征的单变量回归形成对比。把这个模型称为多元线性回归 。就是具有多个特征的线性回归 。为了实现这一点,有一个非常巧妙的技巧叫做矢量化 。
您将看到一个非常有用的概念,即矢量化 。使用矢量化 既可以使代码更短,也可以使其运行得更高效。学习如何编写矢量化代码将使您能够利用现代数值线性代数库,甚至是代表图形处理单元的GPU
硬件。这种硬件的设计是为了加速计算机中的计算机图形处理,当您编写矢量化代码时,它也可以用于帮助您更快地执行代码。让我们看一个具体的例子来说明矢量化的含义。这是一个带有参数 和 的示例,表达式如下: ,其中 是一个包含三个数值的向量,您还有一个包含三个数值的特征 向量。这里 。在线性代数中,索引或计数从1
开始,因此第一个值是下标 和 。在Python
代码中,您可以使用这样的数组定义这些变量、 和 。在这里,使用了Python
中一个名为NumPy
的数值线性代数库。因为在Python
中,数组的索引计数时从0
开始,所以你可以使用 的第一个值。第二个值使用 ,第三个值使用 。同样,要访问 的各个特征,你将使用 和 。包括Python
在内的许多编程语言都从0
开始计数,而不是从1
开始。让我们看一个没有矢量化的实现,用于计算模型的预测。你取每个参数 并将其乘以其相关的特征。现在,您可以像这样编写代码,但如果 不是3
而是 或 ,那么对于您的代码和计算机计算来说,这两者都效率低下。不使用矢量化 ,而是使用for
循环。在数学中,您可以使用求和运算符 将 和 的所有乘积相加,其中 。然后在末尾添加 求和。求和从 。对于 ,因此 。在代码中,您可以从0
开始初始化。您可以将 的乘积添加到 中。最后,在for
循环之外,添加b
。让我们看看如何使用矢量化来实现这一点。这是函数 ,Python
代码实现为:f = np.dot(w,x) + b
。这个NumPy
点积函数是两个向量之间点积运算的矢量化实现,尤其是当n
很大时,它的运行速度会比前面两个代码示例快得多。矢量化有两个明显的好处。首先,它使代码更短。其次,它还使你的代码运行速度比之前两个没有使用矢量化 的实现快得多。矢量化 实现速度更快的原因在于。NumPy
点积函数能够使用计算机并行计算,无论你是在普通计算机(即普通计算机CPU
)上运行它,还是在使用GPU
(图形处理器单元)上运行都是如此。NumPy
点积函数利用并行计算的能力使其比for
循环或顺序计算效率高得多。
同样的算法,矢量化 后运行速度会快得多。让我们深入了解一下矢量化 是如何在计算机上工作的。看看这个for
循环。像这样的for
循环在没有矢量化的情况下运行。如果 ,这段代码会一个接一个地执行。在第一个时间戳上,我将写为 。它首先对索引0
处的值进行操作。在下一个时间步,它计算与索引1
相对应的值,依此类推,直到第15
步。相比之下,NumPy
中的这个函数是在计算机硬件中使用矢量化 实现的。计算机可以获取向量 和 ,并在一个步骤中将每对 和 并行地相乘。然后,计算机将这16
个数值使用专门的硬件非常高效地加在一起,而不是需要逐个执行不同的加法来将这16
个数值相加。意味着具有矢量化的代码比没有矢量化的代码更少的时间内执行计算。当您在大数据集上运行算法或尝试训练大模型时,这一点尤为重要,而机器学习通常就是这种情况。这就是为什么能够矢量化学习算法,是让学习算法高效运行的关键步骤,因此可以很好地扩展到许多现代机器学习算法的大数据集上。现在,让我们看一个具体的例子,看看它如何帮助实现多元线性回归 以及具有多个输入特征的线性回归。假设除了参数 之外,还有16
个特征和16
个参数( )。你为这16
个权重计算16
个导数项,你将 和 的值存储在两个np.arrays
中, 用来存储导数的值。在这个例子中,忽略参数 。,以类似方式更新 ,依此类推,直到 ,更新为 。如果不进行矢量化 ,则可以对 在(0,16)
范围内使用for
循环。相反,如果进行因式分解,则可以将计算机的并行处理硬件想象成这样。它获取向量 中的16
个值并行减去向量 中的16
个值的 ( ),然后将所有16
个计算同时且一次性地分配回 。在代码中,您可以按如下方式实现此操作: 。在后台,计算机获取这些NumPy
数组 和 ,并使用并行处理硬件高效地执行这16
个计算。使用矢量化实现,您可以获得更高效的线性回归 实现。如果有16
个特征,速度差异可能并不大,但如果您有数千个特征,并且训练集可能非常大,这种矢量化 实现将对学习算法的运行时间产生巨大影响。
梯度下降应用于线性回归 我们有参数 以及 。但不要将 视为单独的数值,即单独的参数,将所有 收集到向量 w 中,这样现在 w 就是长度为 n 的向量。我们将这个模型的参数视为向量 w 以及 b,其中 b 仍然是与之前相同的数字。而之前我们必须像这样找到多元线性回归,现在使用向量符号,我们可以将模型写为 f_w,x 的 b 等于向量 与向量 加 的点积 。请记住,这里的点积表示.product
。成本函数 可以定义为 。反复更新每个参数 ,使其为 。让我们看看在实现梯度下降时它是什么样子,特别是让我们看看导数项。我们将看到,与只有一个特征相比,梯度下降 在多个特征下会变得略有不同。这是我们使用一个特征进行梯度下降时得到的结果。我们有一条针对 的更新规则和一条针对 的单独更新规则。希望你对这些规则很熟悉。这里的这一项是成本函数 对参数 的导数。类似地,我们有一个针对参数 的更新规则,对于单变量回归,我们只有一个特征。我们将该特征称为 ,不带任何下标。现在,这里有一个表示法,表示我们有 个特征,其中 为2
或更大。我们得到了梯度下降的更新规则: ,右边公式实际上是成本 对 的导数。误差项仍然取 减去目标 的预测 。一个区别是 和 是向量,就像左边的 现在变成了右边的 一样,左边的 现在变成了右边的 。对于多元线性回归, ,更新参数 ,然后像之前一样,更新 。这样,就会得到多元回归 的梯度下降 。
特征缩放 特征缩放 的技术将使梯度下降 运行得更快。让我们首先看一下特征的大小与其相关参数的大小之间的关系。作为一个具体的例子,让我们使用两个特征 (房屋大小)和 (卧室数量)来预测房屋的价格。假设 的面积通常在300~2000
平方英尺之间。数据集中的 的范围是0~5
个卧室。对于这个例子, 取值范围相对较大,而 取值范围相对较小。一栋面积为2000
平方英尺的房子有五个卧室,价格为500k
或500,000
美元。对于这个训练示例,您认为参数 和 的大小是多少?让我们看一组可能的参数。假设 , , 。在这种情况下,以千美元计算的估价是 。略高于1
亿美元。因此,这显然与500,000
美元的实际价格相差甚远。因此,对于 和 来说,这不是一组很好的参数选择。现在让我们看看另一种可能性。假设 和 反过来。 , 。在 和 的选择中, 相对较小, 相对较大,50
比0.1
大得多。所以这里预测的价格是 。第一项变成 200k
,第二项变成250k
,再加上50
。所以这个版本的模型预测价格为500,000
美元,这是一个更合理的估计,恰好与房屋的真实价格相同。所以您可能会注意到,当特征的值范围很大时,例如面积和平方英尺,一直到2000
。一个好的模型更有可能学会选择一个相对较小的参数值,例如0.1
。同样,当特征的可能值很小时,例如卧室数量,其参数的合理值将相对较大,例如50
。那么这与分级下降 有何关系?
让我们看一下特征的散点图,其中面积平方英尺是横轴 ,卧室数量是纵轴。如果你绘制训练数据,你会注意到与纵轴相比,横轴的尺度或值范围要大得多。接下来让我们看看成本函数 在等高线图中的样子。您可能会看到等高线图中横轴的范围要窄得多,比如在0~1
之间,而纵轴的值要大得多,比如在10~100
之间。因此,等高线形成椭圆形,它们一边短,另一边长。这是因为对 的微小更改会对估计价格产生非常大的影响,而这会对成本 产生非常大的影响。因为 往往会乘以一个非常大的数字,即面积和平方英尺。相比之下,需要对 进行更大的更改才能改变预测。因此,对 的微小更改几乎不会改变成本函数 。那么这给我们带来了什么?如果您在dissent
中运行良好,并且按原样使用训练数据,最终可能会发生这种情况。由于轮廓线太高,梯度下降 可能会反复来回很长时间,然后才能最终找到全局最小值 。在这种情况下,一个有用的方法是缩放特征 。意味着对训练数据进行一些变换,这样 的范围从0~1
, 的范围从0~1
。所以数据点现在看起来更像这样,你可能会注意到底部图的比例现在与顶部图的比例完全不同。关键在于,重新缩放 和 现在都取了彼此可比较的值范围。如果您在成本函数 上运行梯度下降法 ,找到此结果,使用转换后的数据重新缩放 和 ,那么轮廓看起来会更像圆形,而不是又高又瘦。梯度下降法 可以找到一条更直接的路径,到达全局最小值 。总结一下,当您拥有不同的特征,它们取的值范围非常不同时,梯度下降法 运行缓慢,但重新缩放不同的特征,使它们都取可比较的值范围。
让我们看看如何实现特征缩放 ,将取值范围相差很大的特征转换为具有可比值范围的特征。如何缩放特征?如果 的范围是3~2,000
,则获取 缩放版本的一种方法是取每个原始 (范围的最大值)。 的缩放范围从0.15~1
。同样,由于 的范围是0~5
,您可以通过取每个原始 (这也是最大值)来计算 的缩放版本。因此, 的缩放范围现在为0~1
。如果您将 和 的缩放绘制在图表上,它可能看起来像这样。除了除以最大值之外,您还可以执行所谓的均值归一化 。具体做法是,先从原始特征开始,然后重新调整它们的比例,使它们都以零为中心。之前,它们只有大于零的值,而现在它们同时具有负值和正值,这些值通常介于-1
和1
之间。要计算 的平均归一化 ,首先找到平均值,也称为训练集上 的均值,我们将其称为均值 。例如,您可能会发现特征 的均值 为600
平方英尺。 ,其中2,000
是最大值,300
是最小值,如果这样做,您将得到归一化的 ,范围为-0.18~0.82
。类似地,要计算归一化x_2
的平均值,您可以计算特征 的平均值。例如, 。然后, 。平均归一化 的范围是-0.46~0.54
。如果您使用平均归一化 和 绘制训练数据。最后一种常见的重新缩放方法称为Z分值归一化 。要实现Z分值归一化,您需要计算每个特征的标准差 。如果您听说过正态分布 或钟形曲线 (有时也称为高斯分布 ),这就是正态分布的标准差。那么为了实现Z分值标准化 ,你首先要计算平均值 ,以及标准差,通常用每个特征的小写希腊字母 表示。例如,特征 的标准差是450
,平均值是600
,那么为了对 进行Z分值标准化 ,取 ,减去 ,然后除以标准差,将其表示为 。你可能会发现Z分值标准化 的 现在的范围是-0.67~3.1
。类似地,如果您计算出第二个特征的标准差为1.4
,平均值为2.3
,那么您可以计算 ,在这种情况下, 归一化的Z
分值可能在-1.6~1.9
之间。如果您在图表上绘制归一化 和 上的训练数据,它可能看起来像这样。根据经验,在执行特征缩放 时,您可能希望使特征的范围从(-1, 1)
。如果特征范围从(-3,-3)
或(-0.3, 0.3)
。如果您有一个特征 最终介于0~3
之间,那不是问题。您可以根据需要重新缩放它,但如果您不重新缩放它,它应该正常工作。或者,如果你有一个不同的特征 ,其值介于-2~0.5
之间,那么重新缩放它也没有问题,但如果你不改变它,也没问题。但是,如果另一个特征(比如这里的 )的范围是-100~100
,那么它的范围就会大不相同,比如说从-1~1
。你最好重新缩放这个特征 ,使其范围更接近 -1~1
。同样,如果你有一个特征 ,它的值非常小,比如说介于-0.001~0.001
之间,那么这些值就太小了。这意味着你可能重新缩放它。最后,如果你的特征 (比如医院患者体温测量值)的范围是98.6~105
华氏度,该怎么办?在这种情况下,这些值约为100
,与其他尺度特征相比,这实际上相当大,这实际上会导致梯度下降 运行得更慢。在这种情况下,特征重新缩放可能会有所帮助。执行特征重新缩放几乎没有任何坏处。这就是特征缩放的全部内容。使用这个小技巧,通常可以让梯度下降运行得更快。这就是特征缩放 。无论有没有特征缩放 ,当您运行梯度下降 时,如何检查梯度下降 是否真的有效?
梯度下降的收敛性 运行梯度下降 时,如何判断它是否正在收敛 ?也就是说,它是否能帮助你找到接近成本函数全局最小值的参数。关键是学习率 的选择。回想一下,梯度下降的工作是找到参数 和 ,希望它们能最小化成本函数 。每次迭代意味着在每次同时更新参数 和 。在这个图中,横轴是你到目前为止运行的梯度下降迭代次数。您可能会得到一条如下所示的曲线。请注意,横轴是梯度下降的迭代次数,而不是 或 等参数。这与您之前看到的图表不同,其中纵轴是成本 。这条曲线也称为学习曲线 。机器学习中使用了几种不同类型的学习曲线,具体来说,如果您查看曲线上的这一点,意味着在您运行梯度下降100
次迭代后,即同时更新100
次参数后,您会学到一些 和 的值。如果您计算 和 的值的成本 。这就是纵轴上的这个点。这里的这个点对应于在200
次梯度下降迭代后得到的参数的 值。查看此图可帮助您了解梯度下降每次迭代后成本 的变化情况。如果梯度下降正常,则成本 应在每次迭代后降低。如果 在一次迭代后增加,则意味着 选择不当(通常意味着 太大),或者代码中可能存在错误。如果您查看此曲线,当您达到大约300
次迭代时,成本 趋于平稳,不再大幅下降。到400
次迭代时,曲线似乎已经变平。这意味着梯度下降 或多或少已经收敛 ,因为曲线不再下降。梯度下降转换所需的迭代次数在不同的应用程序之间可能有很大差异。在一个应用程序中,它可能仅在30
次迭代后就收敛。在其它的应用中,可能需要1,000
或100,000
次迭代。事实证明,很难提前知道梯度下降 需要多少次迭代才能收敛,这就是为什么你可以创建这样的一个图表,即学习曲线 。
另一种确定你的模型何时完成训练的方法是使用自动收敛测试 。这是希腊字母 。我们让 成为代表小数的变量,例如 或 。如果成本 在一次迭代中减少的幅度小于这个数字 ,那么你很可能处于左侧曲线的平坦部分,说明已经收敛。请记住,收敛,在你找到接近 最小值的参数 和 的情况下。发现选择正确的阈值 非常困难。这时候可以选择查看学习曲线图表 ,而不是依赖自动收敛测试 。
选择学习率 选择合适的学习率 ,学习算法会运行得更好。如果学习率 太小,它会运行得非常慢,如果学习率 太大,它甚至可能无法收敛。让我们来看看如何为你的模型选择一个好的学习率 。具体来说,如果你绘制了多次迭代的成本图,并注意到成本有时上升,有时下降,你应该把它看作是梯度下降 不正常工作的明显迹象。这可能意味着代码中有一个错误。或者有时它可能意味着你的学习率太大。所以这里有一种可能发生的情况。这里的纵轴是成本函数 ,横轴代表一个参数,比如 ,如果学习率太大,你的更新迭代可能会超过最小值并结束,在下一个更新迭代中,你的增益会超出,依此类推。这就是为什么成本有时会上升而不是下降。为了解决这个问题,你可以使用较小的学习率。然后你的更新迭代开始,然后一点点下降,我们希望它能持续下降,直到达到全局最小值。 有时你会看到成本在每次迭代后持续增加,就像这里的曲线一样。这也是由于学习率太大,可以通过选择较小的学习率来解决。但像这样的学习率也可能是代码损坏的标志。例如,如果编写的代码是将 更新为 ,这可能会导致成本在每次迭代中持续增加。这是因为导数项会使你的成本 远离全局最小值 而不是更接近。所以请记住,你想使用减号,所以代码应该将 更新为 。正确实现梯度下降的一个调试技巧是,如果学习率足够小,成本函数 应该在每次迭代中下降。因此,如果梯度下降 不起作用,我经常会做的一件事是将 设置为一个非常小的数字,看看这是否会导致每次迭代的成本降低。如果即使将 设置为非常小的数字, 也不会在每次迭代中减少,而是有时会增加,那么这通常意味着代码中某个地方有错误。请注意,将 设置为非常小在这里是作为调试步骤,非常小的 值并不是实际训练学习算法的最有效选择。
一个重要的权衡是,如果你的学习率太小,那么梯度下降可能需要很多次迭代才能收敛。所以当运行梯度下降 时,通常会尝试一组学习率 值。可能会从尝试 的学习率开始,也可能尝试10
倍的学习率,比如0.01
和 0.1
等等。对于每个 值,只运行梯度下降法几次迭代,并绘制成本函数 与迭代次数的关系,在尝试了几个不同的值之后,可能会选择一个 值,这个值似乎会迅速降低学习率 ,但也会保持一致。尝试0.001
后,我会将学习率提高三倍至0.003
。之后,我会尝试0.01
,这又是0.003
的三倍。所以这些都是尝试,每个 值大约是前一个值的三倍。慢慢尝试选择最大的学习率,或者只是比找到的最大合理值略小的值。当这样做时,它通常会为模型提供一个很好的学习率。
特征工程 特征的选择会对学习算法的性能产生巨大影响。事实上,对于许多实际应用来说,选择或输入正确的特征是算法正常工作的关键。让我们看看如何为学习算法选择最合适的特征 。假设每栋房子有两个特征。 是房屋地块的宽度。这在现实中也称为地块的正面,第二个特征 是地块的长度,假设房屋建在矩形地块上。给定这两个特征 ,您可以构建这样的模型,其中 。这个模型可以正常工作。但是,您还有另一种选择,可以选择以不同的方式在模型中使用这些特征,这种方式可能会更有效。土地面积可以通过正面宽度乘以长度来计算。与将正面宽度和长度作为单独特征相比,土地面积更能预测价格。您可以将新特征 定义为 。这个新特征 等于地块的面积。有了这个特征,您就可以得到一个模型 ,这样模型可以选择参数 ,具体取决于数据是否显示正面宽度、长度或地块面积 是预测房价的最重要因素。刚才所做的创建新特征就是特征工程 的一个例子,在特征工程 中,你可以利用对问题的知识或直觉来设计新特征,通常是通过转换或组合问题的原始特征,以便让学习算法更容易做出准确的预测。根据你对应用程序的了解,有时通过定义新特征,而不仅仅是采用刚开始使用的特征,这样可能会得到一个更好的模型。这就是特征工程 。事实证明,这种特征工程 不仅可以让你拟合直线 ,还可以拟合曲线 和非线性函数 。
多项式回归 到目前为止,我们只是用直线拟合 数据。让我们利用多元线性回归 和特征工程 的思想,提出一种称为多项式回归 的新算法,该算法可让您将曲线(非线性函数)拟合到数据中。假设您有一个如下所示的房屋数据集,其中特征 是平方英尺的大小。看起来直线不太适合这个数据集。也许您想用曲线(也许是二次函数)拟合数据,模型表示为 。也许这样可以更好地拟合数据。但可能二次模型实际上没有意义,因为二次函数最终会回落。我们不会真的期望房价在面积增加时下降。大房子似乎通常应该更贵。那么您可以选择一个三次函数 ,现在我们不仅有 ,还有 。也许这个模型会生成这样的曲线,它与数据的拟合度更高,因为随着尺寸的增加,尺寸最终会回升。这些都是多项式回归的例子,因为你选取了可选特征 ,并将其提升到2
次方、3
次方或任何其他次方。在三次函数的情况下,第一个特征是尺寸,第二个特征是尺寸的平方,第三个特征是尺寸的立方。如果你创建的特征是原始特征的平方幂,那么特征缩放 就变得越来越重要。如果房子的大小范围是1~1,000
平方英尺,那么第二个特征(即尺寸的平方)的范围将从1~100
万,第三个特征(即尺寸的立方)的范围将从1~10
亿。这两个特征( 和 )与原始特征 相比具有不同的值范围。如果您使用梯度下降 ,应用特征缩放 使特征进入可比较的值范围非常重要。
取尺寸平方和尺寸立方的另一种合理替代方法是使用 的平方根。您的模型看起来像 。随着 的增加,它的陡峭程度会降低一些,但它永远不会完全平坦,而且肯定永远不会回落。这将是另一种也适用于此数据集的特征选择。