那么我们如何使用 Python 实现梯度下降呢?在本节我们就一起来看一下。
已知函数 y=x2 以及它的导数 y′=2x
接下来我们想一下如何用编程的思想实现这个算法。
Python实现代码如下。
def grad(x,alpha,iter):
x_list=[]
y_list=[]
x__list=[]
g_list=[]
for i in range(iter):
y=x*x
x_=2*x
gradient=alpha*x_
x_list.append(x)
y_list.append(y)
x__list.append(x_)
g_list.append(gradient)
x=x-gradient
return x_list,y_list,x__list,g_list
初始值的选择依托于所假设的数学模型,具体的数学模型会在后面的章节讨论。不同的数学模型反映在二次函数上则会是随机的初始点。本节主要学习速率 α 详细介绍。
上述代码中,速率 α 的选择是梯度下降思想的核心,α 直接影响了最后结果的好坏以及整个算法的效率。
选择点(100,100)作为初始点,如图 1 所示。当 α=0.003 时,移动了 100 次,才到达 x=55 附近。虽然在这种情况下我们仍可以通过增加移动次数最终到达最小值的点,但是会耗费大量的时间和算力。特别是在工程应用中,时间和算力决定了一个算法是否有实际价值。
在极端情况下,当α足够小时,将无法到达最小值点。
选择点(100,100)作为初始点,如图 2 所示。当 α=0.5 时,只移动了 2 次就到达了最小值。
选择点(40,1600)作为初始点,如图 3 所示。当 α=0.9 时,将从两端收敛到最小值,详见表 1。
α=0.9 时从两端收敛到最小值(保留2位小数)
步数 | x坐标 | y坐标 |
---|---|---|
1 | 100 | 10000 |
2 | -80 | 6400 |
3 | 64 | 4096 |
4 | - 51.2 | 2621.44 |
5 | 40.96 | 1677.72 |
6 | -32.77 | 1073.74 |
7 | 26.21 | 687.19 |
8 | - 20.97 | 439.8 |
9 | 16.78 | 281.47 |
10 | -13.42 | 180.14 |
选择点(40,1600)作为初始点,如图 4 所示。当α=1时,移动点将在点(40,1600)和点(-40,1600)之间来回振动。
α 过小,虽然可能到达不了最小值的点,但是移动的方向仍是正确的,即向着最小值方向移动。但α过大,则可能造成偏离最小值的情况,即向着最小值的反方向移动。
选择点(20,400)作为初始点,如图 5 所示。当 α=1.1 时,每次移动都跨越了最小值,而且越来越偏离最小值。
详见下表:
步数 | x坐标 | y坐标 |
---|---|---|
1 | 20 | 400 |
2 | -24 | 576 |
3 | 28.8 | 829.44 |
4 | -34.56 | 1194.39 |
5 | 41.47 | 1719.93 |
6 | -49.77 | 2476.69 |
7 | 59.72 | 3566.44 |
8 | - 71.66 | 5135.67 |
9 | 86 | 7395.37 |
10 | - 103.2 | 10649.33 |
综上所述,学习速率 α 的选择规律为:随着学习速率 α 的递增,学习过程从速度极慢,到两边振荡收敛,再到两边振荡发散。那么在实际应用中我们应该如何选择 α 呢?这要根据不同的应用场景来具体设置。
到目前为止,我们已经详细了解了机器学习中的一个重要思想,即“梯度下降”。它是线性回归、逻辑回归以及神经网络的核心思想,接下来就让我们一起学习梯度下降是如何应用到这 3 类算法中的。