为了实现梯度下降,您需要计算关于每个模型参数的代价函数的梯度。换句话说,你需要计算如果你改变一点的话,代价函数会发生多少变化。这个规程也就是数学中的求偏导数。这就像问“如果我面对东方,我脚下的山的坡度是多少?”然后再面向北方,问同样的问题,如果你能想象一个有三个维度的宇宙,那么在所有其他维度上也是如此。
方程4-5计算了代价函数关于参数的偏导数,记为:
方程4 - 5。代价函数的偏导数
与其使用这个公式单独的计算梯度,你可以使用公式4-6来一次计算出来。这个梯度向量,被记为: MSE(θ),它包含了成本函数的所有偏导数(每个模型参数一个)。
方程4 - 6 成本函数的梯度向量
注意,这个公式涉及到在每一个梯度下降步子中,要在整个训练集X上计算!这就是为什么这个算法被称为批量梯度下降法【Batch Gradient Descent】:它在每一步上都使用了全部的训练数据。因此,在非常大的训练集上,它的速度非常慢(但很快我们就会看到更快的梯度下降算法)。然而,梯度下降与特性的数量有很好的关系;在有成千上万个特征的情况下,使用梯度下降法比使用正规方程可以更快地训练线性回归模型。
一旦你有了梯度向量,它指向上坡的话,就向向着相反的方向走。这以为着。你应该从θ减去 MSE(θ)减小的方向走。这就是学习速率 η发挥作用的地方:将梯度向量乘以η,以确定步长(方程式4-7)
方程4 - 7
= θ - η MSE(θ)
让我们来看看这个算法的快速实现:
eta = 0.1 # learning rate
n_iterations = 1000
m = 100
theta = np.random.randn(2,1) # random initialization
for iteration in range(n_iterations):
gradients = 2/m * X_b.T.dot(X_b.dot(theta) - y)
theta = theta - eta * gradients
这不是太困难了!我们来看看得到的theta:
>>> theta
array([[ 4.21509616],
[ 2.77011339]])
嘿,这就是正规方程的结果!梯度下降工作完美。但是如果你使用的是一个不同的学习速率,结果会怎么样呢?图4-8显示了使用三种不同的学习速率(虚线表示起始点)的梯度下降的前10个步移。
图4 - 8。具有不同学习率的梯度下降
在左边,学习率太低了:算法最终会找到到解决方案,但这需要很长时间。
在中间,学习速率看起来相当不错:在几次迭代中,它已经聚合到解决方案中。
在右边,学习率太高了:算法发散,跳跃到各处,实际上在每一步都离解决方案越来越远。
为了找到一个好的学习速率,你可以使用网格搜索(见第二章)。但是,你可能想要限制迭代的次数,这样网格搜索就可以消除那些花了太长时间才收敛的模型。
您可能想知道如何设置迭代的数量。如果它太低,当算法停止时,您仍然距离您的最优解很远,但是如果它太高,当模型参数不再改变的时候您,将浪费时间。一个简单的解决方案是设置大量的迭代,但是当梯度向量变得很小时-------------也就是说,当它的范数变得比ϵ值(称为公差)还要小时,就中断算法,因为当梯度下降(几乎)达到最小值时就会发生这种情况。
收敛速度
当成本函数是凸的,它的斜率不会突然改变(就像MSE代价函数的情况一样),可以证明,具有固定学习速率的批量梯度下降具有收敛速度:O(1/iterations),换句话说,如果你把公差除以10(为了得到一个更精确的解决方案),那么这个算法将不得不运行大约10倍的迭代。