![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=1739284388-Yvg4Zz74gaFV292DROf84UEJDIWLultR-0-bd8a9bc46c7d9c47b6df1f74a9d23905)
2.将每个权重和偏置项增加一个非常小的量(0.0001),并对每个权重和偏置项更新一次,计算总体误差损失的平方值。
❍ 在下面的代码中,创建了一个名为update_weights的函数,它通过执行梯度下降过程来更新权重。函数的输入是网络的输入变量inputs、期望的outputs、weights(在模型训练开始时进行随机初始化),以及模型的学习率lr(有关学习率的更多内容见后面的章节):
![](https://epubservercos.yuewen.com/37D997/29686491107405206/epubprivate/OEBPS/Images/33_01.jpg?sign=1739284388-9uOFZdIS2RodwngMKgfXNK5qtCQPVDQc-0-d9eaf682021b47db0e2b134605d46ad2)
❍ 确保对权重列表进行了deepcopy操作。由于权重将在后面的步骤中被操纵,deepcopy确保了我们可以在不干扰实际权重的情况下使用多个权重副本。创建作为函数输入传递的原始权重集的三个副本——original_weights、temp_weights和updated_weights:
![](https://epubservercos.yuewen.com/37D997/29686491107405206/epubprivate/OEBPS/Images/33_02.jpg?sign=1739284388-1AhQP4pLGeqXqXxxHFtxGQvUdswV20My-0-d22e47e5d92228d9de49da488b0f04ce)
❍ 通过feed_forward函数传递inputs、outputs和original_weights,使用原始的权重集计算损失值(original_loss):
![](https://epubservercos.yuewen.com/37D997/29686491107405206/epubprivate/OEBPS/Images/33_03.jpg?sign=1739284388-Z42ZG8S1A4j8vHTKPZ5obe4aMfP6MFoL-0-7ab38493bd4d18c465210ed40be9d817)
❍ 循环遍历网络的所有层:
![](https://epubservercos.yuewen.com/37D997/29686491107405206/epubprivate/OEBPS/Images/33_04.jpg?sign=1739284388-YCD6kDXolEC2OuoNqlxqzc4HRiUy5Thl-0-4fcb1af2944f9c7026de91f32a3ad4f5)
❍ 在神经网络中总共有四个参数列表:两个连接输入层和隐藏层的权重与偏置参数列表,另外两个连接隐藏层和输出层的权重与偏置参数列表。现在,我们循环遍历所有单独的参数,因为每个列表有不同的形状,利用np.ndenumerate循环遍历给定列表中的每个参数:
![](https://epubservercos.yuewen.com/37D997/29686491107405206/epubprivate/OEBPS/Images/33_05.jpg?sign=1739284388-R5iYvFpc0qRIqDjkztCB1TgKgCJUMbm4-0-8da22b2be34f3f4f3675ce9665f06dc4)
❍ 现在将原始权重集存储在temp_weights中。选择其在第i层存在的指标权重,并将其增加一个较小的量。最后,用神经网络的新权重集计算新的损失:
![](https://epubservercos.yuewen.com/37D997/29686491107405206/epubprivate/OEBPS/Images/33_06.jpg?sign=1739284388-ie72hGDDesuWJ0CLUktbQslN4ZAYS87X-0-570dba8166690329acb146f0a87903b5)
在上述代码的第一行中,将temp_weights重置为原始的权重集,正如在每次迭代中那样更新不同的参数,由此计算出在给定轮内对参数进行少量更新时得到的新的损失。
❍ 计算由于权重变化而产生的梯度(损失值的变化):
![](https://epubservercos.yuewen.com/37D997/29686491107405206/epubprivate/OEBPS/Images/33_07.jpg?sign=1739284388-ws8BvayeyNSYEBdb5k0JKjhpNq0iWOjF-0-a06a8e278aaee6a3ffa5a8e53dedc231)
通过非常小的增量更新一个参数,然后计算相应的梯度,这个过程相当于一个微分过程。
❍ 最后,更新updated_weights对应层和index中的参数。更新后的权重值将按梯度值的比例减小。此外,我们还引入了一种机制,通过使用学习率lr(关于学习率的更多信息,见1.6节)来缓慢地建立信任,而不是将其完全减小为梯度值:
![](https://epubservercos.yuewen.com/37D997/29686491107405206/epubprivate/OEBPS/Images/34_01.jpg?sign=1739284388-98r3MDpsdPLNjbakpCEtNW7rrxTb63ri-0-3107823fb7f56c4d57960c2b62f50e5f)
❍ 一旦更新了所有层的参数值和层内的索引,我们就返回更新后的权重值updated_weights:
![](https://epubservercos.yuewen.com/37D997/29686491107405206/epubprivate/OEBPS/Images/34_02.jpg?sign=1739284388-hX5pBKKhqUnOIMCQNbFiMDKRItMsUEWT-0-c5d34e662533dd82e392142bc576f5d2)
神经网络的另一个参数是在计算损失值时需要考虑的批大小(batch size)。
前面使用所有数据点来计算损失(均方误差)值。然而在实践中,当有成千上万(或者在某些情况下数百万)的数据点时,使用较多数据点计算损失值,其增量贡献将遵循收益递减规律,因此我们将使用比数据点总数要小得多的批大小进行模型训练。在一轮的训练中,每次使用一个批次数据点进行梯度下降(在前向传播之后),直到用尽所有的数据点。
训练模型时典型的批大小是32和1024之间的任意数。
在本节中,我们了解了当权重值发生少量变化时,如何基于损失值的变化更新权重值。在下一节中,将学习如何在不计算梯度的情况下更新权重。