1.4.1 梯度下降的代码
下面将给出梯度下降的Python实现代码。
下列代码可以从本书GitHub存储库(https://tinyurl.com/mcvp-packt)Chapter01文件夹中的Gradient_descent.ipynb获得。
1.定义前馈网络并计算均方误差损失值,正如我们在1.3.5节中所做的那样:
2.将每个权重和偏置项增加一个非常小的量(0.0001),并对每个权重和偏置项更新一次,计算总体误差损失的平方值。
❍ 在下面的代码中,创建了一个名为update_weights的函数,它通过执行梯度下降过程来更新权重。函数的输入是网络的输入变量inputs、期望的outputs、weights(在模型训练开始时进行随机初始化),以及模型的学习率lr(有关学习率的更多内容见后面的章节):
❍ 确保对权重列表进行了deepcopy操作。由于权重将在后面的步骤中被操纵,deepcopy确保了我们可以在不干扰实际权重的情况下使用多个权重副本。创建作为函数输入传递的原始权重集的三个副本——original_weights、temp_weights和updated_weights:
❍ 通过feed_forward函数传递inputs、outputs和original_weights,使用原始的权重集计算损失值(original_loss):
❍ 循环遍历网络的所有层:
❍ 在神经网络中总共有四个参数列表:两个连接输入层和隐藏层的权重与偏置参数列表,另外两个连接隐藏层和输出层的权重与偏置参数列表。现在,我们循环遍历所有单独的参数,因为每个列表有不同的形状,利用np.ndenumerate循环遍历给定列表中的每个参数:
❍ 现在将原始权重集存储在temp_weights中。选择其在第i层存在的指标权重,并将其增加一个较小的量。最后,用神经网络的新权重集计算新的损失:
在上述代码的第一行中,将temp_weights重置为原始的权重集,正如在每次迭代中那样更新不同的参数,由此计算出在给定轮内对参数进行少量更新时得到的新的损失。
❍ 计算由于权重变化而产生的梯度(损失值的变化):
通过非常小的增量更新一个参数,然后计算相应的梯度,这个过程相当于一个微分过程。
❍ 最后,更新updated_weights对应层和index中的参数。更新后的权重值将按梯度值的比例减小。此外,我们还引入了一种机制,通过使用学习率lr(关于学习率的更多信息,见1.6节)来缓慢地建立信任,而不是将其完全减小为梯度值:
❍ 一旦更新了所有层的参数值和层内的索引,我们就返回更新后的权重值updated_weights:
神经网络的另一个参数是在计算损失值时需要考虑的批大小(batch size)。
前面使用所有数据点来计算损失(均方误差)值。然而在实践中,当有成千上万(或者在某些情况下数百万)的数据点时,使用较多数据点计算损失值,其增量贡献将遵循收益递减规律,因此我们将使用比数据点总数要小得多的批大小进行模型训练。在一轮的训练中,每次使用一个批次数据点进行梯度下降(在前向传播之后),直到用尽所有的数据点。
训练模型时典型的批大小是32和1024之间的任意数。
在本节中,我们了解了当权重值发生少量变化时,如何基于损失值的变化更新权重值。在下一节中,将学习如何在不计算梯度的情况下更新权重。