梯度下降是一种优化算法,用于训练机器学习模型,尤其在神经网络中得到广泛应用。通过训练数据,模型能够随着时间的推移而学习,梯度下降作为一个自动系统,调整参数以获得更好的结果。这些参数在每次迭代后更新,直到函数达到可能的最小误差。
在下面的图表中,红色箭头表示梯度,通过在每次迭代后更新参数,可以减少损失,这是主要目标。
梯度下降,根据Arthur Samuel的说法,是自动处理改变权重以最大化性能的过程。具体来说,将讨论将函数转换为机器学习模型所需的每一步。
用随机值初始化参数。这些初始权重是模型的起点,这样就可以利用损失函数来确定离目标有多远。
需要一个函数,它将实际值和预测值作为输入,计算误差指标。最常见的损失函数是均方误差。
将通过增加或减少一小部分权重来确定什么最有效,以检查损失是上升还是下降。这种方法并不高效,因为找到正确的方向需要时间。这就是梯度发挥作用的地方。梯度帮助确定应该在哪个方向上改变权重以获得更好的结果。通过函数传递初始权重来预测值,并使用它来计算损失。然后取参数的梯度,并从原始参数中减去它。这个过程会重复,直到达到最好的可能分数。
需要决定训练模型需要多少轮迭代(Epochs)。这些迭代将在那之后结束。
代码受到Jeremy Howard深度学习课程的影响,将使用PyTorch构建模型,并使用Pyplot进行可视化。最后,设置手动种子以重现结果。如果使用的是Deepnote环境,可以直接复制粘贴代码以获得等效结果。
import torch
import matplotlib.pyplot as plt
torch.manual_seed(2021);
# 生成值
time = torch.arange(0, 20).float()
speed = torch.rand(20)*5 + 0.8*(time-7.5)**2+1
plt.scatter(time, speed);
# 核心函数
def function(t, params):
a, b, c = params
return a*(t**2) + (b*t) + c
# 均方误差
def mse(preds, targets):
return ((preds-targets)**2).mean()
# 学习率
params = torch.randn(3).requires_grad_()
orig_params = params.clone()
lr = 1e-5
# 可视化函数
def show_preds_actual(preds, ax=None):
if ax is None: ax = plt.subplots()[1]
ax.scatter(time, speed)
ax.scatter(time, preds.detach().numpy(), color='red')
ax.set_ylim(-100, 100)
# 预测输出并绘制
preds = function(time, params)
show_preds_actual(preds)
# 机器学习模型
def apply_step(params, prn=True):
preds = function(time, params)
loss = mse(preds, speed)
loss.backward()
params.data -= lr*params.grad.data
params.grad = None
if prn: print("RMSE:", (loss.item())**0.5)
return preds
# 运行6次迭代并查看结果
_, axs = plt.subplots(1, 6, figsize=(12, 3))
for ax in axs: show_preds_actual(apply_step(params, False), ax)
plt.tight_layout()
# 重置参数并运行10次迭代
params = orig_params.detach().requires_grad_()
for i in range(10): preds = apply_step(params)
曾经认为可以不深入了解机制就能构建机器学习模型,结果发现策略有缺陷,因为局限于现有的模型和库。如果想创建自己的尖端深度学习模型,需要了解神经网络的工作原理。不需要学习数学,但学习最小的构建块将帮助创建一个甚至比现有模型表现更好的模型。