梯度下降的场景假设
一个人被困在山上,需要从山上下到山谷。但此时山上的雾很大,导致可视度很低。因此,下山的路径就无法确定,他必须利用自己周围的信息去找到下山的路径。这个时候,他就可以利用梯度下降算法来帮助自己下山。以他当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着山的高度下降的地方走,如果我们的目标是上山,也就是爬到山顶,那么此时应该是朝着最陡峭的方向往上走。然后每走一段距离,都反复采用同一个方法,最后就能成功的抵达山谷。
模拟下山.png梯度下降简介
梯度下降是迭代法的一种,可以用于求解最小二乘问题(线性和非线性都可以)。在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient Descent)是最常采用的方法之一,另一种常用的方法是最小二乘法。在求解损失函数的最小值时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。反过来,如果我们需要求解损失函数的最大值,这时就需要用梯度上升法来迭代了。
求解过程
梯度下降法的计算过程就是沿梯度下降的方向求解极小值(也可以沿梯度上升方向求解极大值)。
梯度方向我们可以通过对函数求导得到,步长的确定比较麻烦,太大了的话可能会发散,太小收敛速度又太慢。一般确定步长的方法是由线性搜索算法来确定。
梯度向量为0的话说明是到了一个极值点,此时梯度的幅值也为0.而采用梯度下降算法进行最优化求解时,算法迭代的终止条件是梯度向量的幅值接近0即可,可以设置个非常小的常数阈值。
梯度下降.png
代码实现梯度下降算法
造测试数据代码如下:
import numpy as np
import matplotlib.pyplot as plt
plot_x = np.linspace(-1, 6 , 200)
plot_y = (plot_x - 2.5) ** 2 - 1
plt.plot(plot_x, plot_y)
plt.show()
可视化测试数据:
测试数据.png
梯度下降算法求解这个测试数据的极值点,算法迭代的终止条件是梯度向量的幅值接近0即可,可以设置个非常小的常数阈值。
import numpy as np
import matplotlib.pyplot as plt
plot_x = np.linspace(-1, 6 , 200)
plot_y = (plot_x - 2.5) ** 2 - 1
#设置个非常小的常数阈值
epsilon = 1e-8
#设置步长
eta = 0.2
# 损失函数
def J(theta):
return (theta-2.5)**2 - 1.
# 求导确认行进方向
def dJ(theta):
return 2*(theta-2.5)
theta = 0.0
theta_history = [theta]
while True:
gradient = dJ(theta)
last_theta = theta
# 向导数的负方向移一步
theta = theta - eta * gradient
theta_history.append(theta)
# 终止条件是梯度向量的幅值接近0,我们设置的是小于epsilon 即可
if(abs(J(theta) - J(last_theta)) < epsilon):
break
plt.plot(plot_x, J(plot_x))
plt.plot(np.array(theta_history), J(np.array(theta_history)), color="r", marker='*')
plt.show()
梯度下降效果如下:
梯度下降效果.png
注意
(1) eta即learning rate,决定的下降步伐,如果太小,则找到函数最小值的速度就很慢,如果太大,则可能会出现overshoot the minimum的现象;简单的说就是你跨步子的大小,跨得太小就会花很长的时间来收敛。
(2) 初始点不同,获得的最小值也不同,因此梯度下降求得的只是局部最小值;
(3) 越接近最小值时,下降速度越慢;
梯度下降的算法调优
(1) 步长选择,选择一个合适的步长需要多次运行后才能得到一个较为优的值。
(2) 参数的初始值选择。 初始值不同,获得的最小值也有可能不同,因此梯度下降求得的只是局部最小值;当然如果损失函数是凸函数则一定是最优解。由于有局部最优解的风险,需要多次用不同初始值运行算法,关键损失函数的最小值,选择损失函数最小化的初值。
(3) 归一化。由于样本不同特征的取值范围不一样,可能导致迭代很慢,为了减少特征取值的影响,可以对特征数据归一化
网友评论