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