优化和深度学习
在本节中,我们讲讨论优化与深度学习之间的关系以及在深度学习中使用优化的挑战。对于深度学习问题,我们通常会先定义损失函数。一旦我们有了损失函数,我们就可以使用优化算法来尝试最小化损失。在优化中,损失函数通常被称为优化问题的目标函数。按照传统和惯则,大多数优化算法都关注的是最小化。若我们需要最大化目标,那么只需要要在目标函数前加符号即可
1 - 优化的目标
尽管优化提供了一种最大限度地减少深度学习损失函数的方法,但实质上,优化和深度学习的目标是根本不同的。前者主要关注的是最小化目标,后者则关注在给定的有限数据的情况下寻找合适的模型。
两个目标之间的区别,例如,训练误差和泛化误差通常不同;由于优化算法的目标函数通常是基于训练数据集的损失函数,因此优化的目标是减少训练误差。但是,深度学习的目标是减少泛化误差,为了实现后者,除了使用优化算法来减少训练误差之外,我们还需要注意过拟合
%matplotlib inline
import numpy as np
import torch
from mpl_toolkits import mplot3d
from d2l import torch as d2l
为了说明上述不同的目标,让我们考虑经验风险和风险
- 经验风险:训练数据集的平均损失
- 风险:整个数据群的预期损失
下面我们定义了两个函数;风险函数f和经验风险函数g,假设我们只有有限量的训练数据。因此,这里的g不如f平滑
def f(x):
return x * torch.cos(np.pi * x)
def g(x):
return f(x) + 0.2 * torch.cos(5 * np.pi * x)
下图说明,训练数据集的最低经验误差可能与最低风险(泛化误差)不同
def annotate(text,xy,xytext):
d2l.plt.gca().annotate(text,xy=xy,xytext=xytext,arrowprops=dict(arrowstyle='->'))
x = torch.arange(0.5,1.5,0.01)
d2l.set_figsize((4.5,2.5))
d2l.plot(x,[f(x),g(x)],'x','risk')
annotate('min of \n empirical risk',(1.0,-1.2),(0.5,-1.1))
annotate('min of risk',(1.1,-1.05),(0.95,-0.5))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fMoWGoU6-1663161929456)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209142122258.svg)]
2 - 深度学习中的优化挑战
在本章中,我们讲特别关注优化算法在最小化目标函数方面的性能,而不是模型的泛化误差。
在3.1中我区分了优化问题中的解析解和数值解。在深度学习中,大多数目标函数都很复杂,没有解析解。相反,我们必须用数值优化算法,本章的优化算法都属于数值优化算法
深度学习优化存在许多挑战。其中一些最令人烦恼的是局部最小值、鞍点和梯度消失
局部最小值
x = torch.arange(-1.0,2.0,0.01)
d2l.plot(x,[f(x),],'x','f(x)')
annotate('local minimum', (-0.3, -0.25), (-0.77, -1.0))
annotate('global minimum', (1.1, -0.95), (0.6, 0.8))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijXJ8ilc-1663161929458)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209142122259.svg)]
深度学习模型的目标函数通常由许多局部最优解。当优化问题的数值解接近局部最优值时,随着目标函数解的梯度接近或变为零,通过最终迭代获得的数值解可能仅使目标函数局部最优,而不是全局最优。只有一定程度的噪声可能会使参数超出局部最小值。
事实上,这是小批量随机梯度下降的有利特性之一,在这种情况下,小批量上梯度的自然变化能够将参数从局部极小值中移出
鞍点
除了局部最⼩值之外,鞍点也是梯度消失的另⼀个原因。鞍点(saddle point)是指函数的所有梯度都消失但既不是全局最⼩值也不是局部最⼩值的任何位置。考虑这个函数f(x) = x^3。它的⼀阶和⼆阶导数在x = 0时消失。这时优化可能会停⽌,尽管它不是最⼩值
x = torch.arange(-2.0,2.0,0.01)
d2l.plot(x,[x**3],'x','f(x)')
annotate('saddle point',(0,-0.2),(-0.52,-5.0))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HNmyKcf8-1663161929458)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209142122260.svg)]
如下例所示,较高维度的鞍点甚至更加隐蔽,考虑整个函数 f ( x , y ) = x 2 − y 2 f(x,y)=x^2-y^2 f(x,y)=x2−y2。它鞍点为(0,0)。这是关于y的最大值,也是关于x的最小值。此外,它看起来像马鞍,这就是这个数学属性的名字由来
x,y = torch.meshgrid(
torch.linspace(-1.0,1.0,101),torch.linspace(-1.0,1.0,101))
z = x**2 - y**2
ax = d2l.plt.figure().add_subplot(111,projection='3d')
ax.plot_wireframe(x,y,z,**{'rstride':10,'cstride':10})
ax.plot([0],[0],[0],'rx')
ticks = [-1,0,1]
d2l.plt.xticks(ticks)
d2l.plt.yticks(ticks)
ax.set_zticks(ticks)
d2l.plt.xlabel('x')
d2l.plt.ylabel('y')
C:\Users\20919\anaconda3\envs\d2l\lib\site-packages\torch\functional.py:478: UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at C:\actions-runner\_work\pytorch\pytorch\builder\windows\pytorch\aten\src\ATen\native\TensorShape.cpp:2895.)
return _VF.meshgrid(tensors, **kwargs) # type: ignore[attr-defined]
Text(0.5, 0.5, 'y')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TmrCLMCz-1663161929458)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209142122261.svg)]
我们假设函数的输入是k维向量,其输出是标量,因此其Hessian(黑塞)矩阵将有k特征值。函数的解决方案可以是局部最小值、局部最大值或函数梯度为零的位置处的鞍点:
- 当函数在零梯度位置处的Hessian矩阵的特征值全部为正值时,我们有该函数的局部最⼩值
- 当函数在零梯度位置处的Hessian矩阵的特征值全部为负值时,我们有该函数的局部最⼤值
- 当函数在零梯度位置处的Hessian矩阵的特征值为负值和正值时,我们对函数有⼀个鞍点
对于高纬度问题,至少部分特征值为负的可能性相当高。这使得鞍点比局部最小值更有可能。我们将在下一节介绍凸性时讨论这种情况的一些例外情况
凸函数时Hessian函数的特征值永远不是负值的函数。不幸的是,大多数深度学习问题并不属于这个类别,尽管如此,它还是研究优化算法的一个很好工具
梯度消失
x = torch.arange(-2.0,5.0,0.01)
d2l.plot(x,[torch.tanh(x)],'x','f(x)')
annotate('vanishing gradient',(4,1),(2,0.0))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TfHWeVU4-1663161929459)(https://yingziimage.oss-cn-beijing.aliyuncs.com/img/202209142122262.svg)]
正如我们所看到的那样,深度学习的优化充满挑战。幸运的是,有一系列强大的算法表现良好,即使对于初学者也很容易使用。此外,没有必要找到最佳的解决方案,局部最优解或其近似解仍然非常有用
3 - 小结
- 最小化训练误差并不能保证我们找到最佳的参数集来最小化泛化误差
- 优化问题可能有许多局部最小值
- 问题可能有更多的鞍点,因为通常问题不是凸的
- 梯度消失可能会导致优化停滞,重参数化通常会有所帮助,对参数进行良好的初始化也可能是有益的