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