介绍
想象一下,您是一名徒步旅行者,您站在山顶,周围环绕着浓雾。您的目标是到达山脚下,但您看不到通往那里的小径。你做什么工作?凭直觉,你开始走下坡路,试图找到通往目的地的路径。
在机器学习的世界里,梯度下降就像那个徒步旅行者,寻找到达成本函数最低点的最佳路径。 成本函数就像一座山,目标是找到模型的参数值,使成本最小化。
梯度下降(通常称为最速下降)是一种用于寻找可微函数 局部最小值的一阶迭代优化算法。思路是在函数当前点的梯度(或近似梯度)的反方向重复走几步,因为这是最速下降的方向。************
它允许我们通过最小化目标变量的预测值和实际值之间的差异来为我们的模型找到最佳参数。
在本文中,我们将探讨如何从头开始实施它。所以,穿上你的登山靴,让我们一起探索机器学习的高山吧!
游戏计划
梯度下降被各种算法使用,从线性回归、逻辑回归到深度神经网络。
今天我们将以线性回归作为示例或主干,只是为了最小的复杂性和最佳的编码直觉,尽管这可以应用于您想要处理的任何算法。
正如我们已经确定的那样,梯度下降的主要目的是最小化成本函数,如果我们使用普通最小二乘 ( OLS ) 方法,这在更高维度上不太可行。
由于 x 和 y 是数据点(ŷ 是预测点),成本函数仅取决于 2 个变量,即斜率 (m) 和截距 (b)。
从上面的等式也很清楚,成本函数取决于这些变量的平方,因此 L(m,b) 将为我们提供3D 空间中的抛物线图。
梯度下降负责找到成本函数最小的 m 和 b 的值,通过上图可以清楚 地看到它位于蓝色区域。
由于该算法无法像我们一样看到最小值,因此它通过 slopes(derivative) 达到最小值。特定点的负斜率或正斜率决定下一步的运动。如果斜率为负,则下一步是向前移动,即增加m 和 b 的值,反之亦然。由于直觉是采取与梯度相反的步骤,因此我们想要得到的是这样的:
bnew = b - (学习率) * 斜率
mnew = m - (学习率) * 斜率
其中斜率正是我们要计算的。为了防止我们的值发生剧烈变化并且从不优化,我们将斜率的值乘以学习率,学习率通常是非常小的值,如 0.001、0.01 等。通过几次迭代,我们将找到最小值。
即使我们正在考虑线性回归,您也可以采用任何算法的成本函数并使用此方法来计算梯度下降,因为您所要做的就是计算导数。这正是深度学习的神经网络所基于的。
代码
当我们考虑线性回归时,我们将生成一个非常小的数据集,然后尝试在其上编写我们的梯度下降。
#Importing libraries
from sklearn.datasets import make_regression
import numpy as np
#Generating a very small dataset with one feature
X,y= make_regression(n_samples= 100 , n_features= 1 , n_informative= 1 , n_targets= 1 , noise= 20 , random_state= 复制代码42)
plt.scatter(X,Y);
这就是我们的数据集的样子
from sklearn.linear_model import LinearRegression
lr= LinearRegression()
#将数据集拟合到我们的模型
lr.fit(X,y)
#计算m(系数)和b(截距)来比较梯度下降
print (lr.coef_)
print (lr 。截距_)
[47.13323967]
2.3302306410539453
我得到了上述值作为输出,让我们尝试将我们的直觉转化为代码并优化我们的梯度下降算法。
class GradientDescent ():
def __init__ ( self, epochs, alpha ):
self.m= 1 #m和b的随机值
self.b= 0
self.epochs= epochs #迭代次数
self.alpha= alpha #学习速率,通常用符号 α
def fit ( self, X, y ) 表示:
对于范围内的 i (self.epochs): loss_slope_b= - 2 * np. sum (y- self.m*X.ravel() - self.b) loss_slope_m= - 2 * np. 和
((y- self.m*X.ravel() - self.b)* X.ravel())
self.b= self.b - (self.alpha*loss_slope_b)
self.m= self.m - (self .alpha*loss_slope_m)
打印(i+ 1 , self.m, self.b)
我们输入 epochs 和 alpha 的值,然后调用我们在数据集上创建的拟合函数。
让我们从 alpha 开始为 0.01 并迭代 50 次
gd= 梯度下降( 50 , 0.01 )
gd.fit(X, y)
结果与我们实际应该得到的值相去甚远 。
让我们降低 学习率并尝试增加 epoch 的数量:
gd= 梯度下降( 100 , 0.001 )
gd.fit(X, y)
我们能够在第 70 个epoch左右获得最佳优化结果,通过将它们与我们之前计算的结果进行比较,我们可以看到我们的算法执行得有多好。****
现在我们已经得到了我们想要的结果,让我们尝试绘制它。我们将使用 matplotlib 并尝试制作动画。
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib import animation #
从非常随机的值开始以可视化优化
b =- 520
m = 600
alpha = 0.001
all_b = []
all_m = []
all_cost = []
epochs = 50
for i in range (epochs):
slope_b = 0
slope_m = 0
cost = 0
for j in range (X.shape[0 ]):
slope_b = slope_b - 2 *(y[j] - (m * X[j]) - b)
slope_m = slope_m - 2 *(y[j] - (m * X[j]) - b) *X[j]
成本 = 成本 + (y[j] - m * X[j] -b) ** 2
b = b - (alpha * slope_b)
m = m - (alpha * slope_m)
all_b.append(b )
all_m.append(m)
all_cost.append(cost)
图, ax = plt.subplots(figsize=( 9 , 5 ))
x_i = np.arange(- 3 , 3 , 0.1 )
y_i = x_i*(- 27 ) - 150
ax.scatter(X, y)
线,= ax.plot(x_i, x_i* 50- 4 , 'r-' , linewidth= 2 )
def update ( i ):
label = 'epoch {0}'。format (i + 1 )
line.set_ydata(x_i*all_m[i] + all_b[i])
ax.set_xlabel(label)
# 返回行,ax
anim = FuncAnimation(fig, update, repeat= True , frames=epochs, interval= 500 )
f = r"animation4.gif"
writergif = animation.PillowWriter(fps= 2 )
anim.save(f, writer=writergif)
梯度下降实战
结论
总之,从头开始构建您自己的梯度下降算法是一种有益的教育体验。通过了解优化的基础知识和梯度下降的工作原理,您可以更深入地 了解机器学习模型的内部工作原理。
虽然有可用的预构建优化库可以使梯度下降的实现变得更加容易,但从头开始构建它可以提供对该算法及其局限性的更全面的理解。梯度下降只是众多优化算法中的一种。随着您继续探索 机器学习和深度学习的世界,您可能会遇到其他优化算法,也许您的好奇心也会解开它们。
最后的想法和结束评论
无论选择哪种算法,关键是要不断学习和试验。随着机器学习领域的不断发展和进步,总会有新的挑战需要应对,新技术需要掌握。
尝试使用其他算法的成本函数编写梯度下降代码,也许尝试 使用神经网络,不要害怕从头开始构建自己的梯度下降算法。您可能会对自己可以完成的事情感到惊讶。