深度学习之PyTorch实战计算机视觉
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.4 损失和优化

深度神经网络中的损失用来度量我们的模型得到的预测值和数据真实值之间的差距,也是一个用来衡量我们训练出来的模型泛化能力好坏的重要指标。模型预测值和真实值的差距越大,损失值就会越高,这时我们就需要通过不断地对模型中的参数进行优化来减少损失;同理,预测值和真实值的差距越小,则说明我们训练的模型预测越准确,具有更好的泛化能力。

对模型进行优化的最终目的是尽可能地在不过拟合的情况下降低损失值。在拥有一部分数据的真实值后,就可通过模型获得这部分数据的预测值,然后计算预测值与真实值之间的损失值,通过不断地优化模型参数来使这个损失值变得尽可能小。可见,优化在模型的整个过程中有举足轻重的作用。

下面看看损失和优化的具体应用过程。以之前讲到的二分类问题为例,在该二分类问题中我们的目的是让搭建的模型能够对一堆苹果和梨混合在一起的水果进行准确分类。首先,建立一个二分类模型,对这堆水果进行第1轮预测,得到预测值ypred,同时把这堆水果中每个水果的真实类别记作真实值ytrue,将ytrueypred之间的差值作为第1轮的损失值。第1轮计算得到的损失值极有可能会较大,这时我们就需要对模型中的参数进行优化,在优化过程中对参数做相应的更新,然后进行第2轮的预测和误差值计算,如此循环往复,最后得到理想模型,该模型的预测值和真实值的差异足够小。

在上面的二分类问题的解决过程中计算模型的真实值和预测值之间损失值的方法有很多,而进行损失值计算的函数叫作损失函数;同样,对模型参数进行优化的函数也有很多,这些函数叫作优化函数。下面对几种较为常用的损失函数和优化函数进行介绍。

3.4.1 损失函数

这里将会列举三种在深度学习实践中经常用到的损失函数,分别是均方误差函数、均方根误差函数和平方绝对误差函数。

1.均方误差函数

均方误差(Mean Square Error,简称MSE)函数计算的是预测值与真实值之差的平方的期望值,可用于评价数据的变化程度,其得到的值越小,则说明模型的预测值具有越好的精确度。均方误差函数的计算如下:

其中,ypred表示模型的预测值,ytrue表示真实值,它们的上标i用于指明是哪个真实值和预测值在进行损失计算,下同。

2.均方根误差函数

均方根误差(Root Mean Square Error,简称RMSE)在均方误差函数的基础上进行了改良,计算的是均方误差的算术平方根值,其得到的值越小,则说明模型的预测值具有越好的精确度。均方根误差函数的计算如下:

3.平均绝对误差函数

平均绝对误差(Mean Absolute Error, MAE)计算的是绝对误差的平均值,绝对误差即模型预测值和真实值之间的差的绝对值,能更好地反映预测值误差的实际情况,其得到的值越小,则说明模型的预测值具有越好的精确度。平均绝对误差函数如下:

3.4.2 优化函数

在计算出模型的损失值之后,接下来需要利用损失值进行模型参数的优化。之前提到的后向传播只是模型参数优化中的一部分,在实际的优化过程中,我们还面临在优化过程中相关参数的初始化、参数以何种形式进行微调、如何选取合适的学习速率等问题。我们可以把优化函数看作上述问题的解决方案的集合。

在实践操作中最常用到的是一阶优化函数,典型的一阶优化函数包括GD、SGD、Momentum、Adagrad、Adam,等等。一阶优化函数在优化过程中求解的是参数的一阶导数,这些一阶导数的值就是模型中参数的微调值。

这里引入了一个新的概念:梯度。梯度其实就是将多元函数的各个参数求得的偏导数以向量的形式展现出来,也叫作多元函数的梯度。举例来说,有一个二元函数f(x,y),分别对二元函数中的xy求偏导数,然后把参数xy求得的偏导数写成向量的形式,即,这就是二元函数f(x,y)的梯度,我们也可以将其记作gradf(x,y)。同理,三元函数f(x,y,z)的梯度为,以此类推。

不难发现,梯度中的内容其实就是在后向传播中对每个参数求得的偏导数,所以我们在模型优化的过程中使用的参数微调值其实就是函数计算得到的梯度,这个过程又叫作参数的梯度更新。对于只有单个参数的函数,我们选择使用计算得到的导数来完成参数的更新,如果在一个函数中需要处理的是多个参数的问题,就选择使用计算得到的梯度来完成参数的更新。

下面来看几种常用的优化函数。

1.梯度下降

梯度下降(Gradient Descent,简称GD)是参数优化的基础方法。虽然梯度下降已被广泛应用,但是其自身纯在许多不足,所以在其基础上改进的优化函数也非常多。

全局梯度下降的参数更新公式如下:

其中,训练样本总数为n,j=0…n。可以将这里的等号看作编程中的赋值运算,θ是我们优化的参数对象,η是学习速率,J(θ)是损失函数,是根据损失函数来计算θ的梯度。学习速率用于控制梯度更新的快慢,如果学习速率过快,参数的更新跨步就会变大,极易出现局部最优和抖动;如果学习速率过慢,梯度更新的迭代次数就会增加,参数更新、优化的时间也会变长,所以选择一个合理的学习速率是非常关键的。

全局的梯度下降在每次计算损失值时都是针对整个参与训练的数据集而言的,所以会出现一个令人困扰的问题:因为模型的训练依赖于整个数据集,所以增加了计算损失值的时间成本和模型训练过程中的复杂度,而参与训练的数据量越大,这两个问题越明显。

2.批量梯度下降

为了避免全局梯度下降问题带来的弊端,人们对全局梯度下降进行了改进,创造了批量梯度下降(Batch Gradient Descent,简称BGD)的优化算法。批量梯度下降就是将整个参与训练的数据集划分为若干个大小差不多的训练数据集,我们将其中的一个训练数据集叫作一个批量,每次用一个批量的数据来对模型进行训练,并以这个批量计算得到的损失值为基准来对模型中的全部参数进行梯度更新,默认这个批量只使用一次,然后使用下一个批量的数据来完成相同的工作,直到所有批量的数据全部使用完毕。

假设划分出来的批量个数为m,其中的一个批量包含batch个数据样本,那么一个批量的梯度下降的参数更新公式如下:

训练样本总数为batch,j=0…batch。从以上公式中我们可以知道,其批量梯度下降算法大体上和全局的梯度下降算法没有多大的区别,唯一的不同就是损失值的计算方式使用的是Jbatch(θj),即这个损失值是基于我们的一个批量的数据来进行计算的。如果我们将批量划分得足够好,则计算损失函数的时间成本和模型训练的复杂度将会大大降低,不过仍然存在一些小问题,就是选择批量梯度下降很容易导致优化函数的最终结果是局部最优解。

3.随机梯度下降

还有一种方法能够很好地处理全局梯度下降中的问题,就是随机梯度下降(Stochastic Gradient Descent,简称SGD)。随机梯度下降是通过随机的方式从整个参与训练的数据集中选取一部分来参与模型的训练,所以只要我们随机选取的数据集大小合适,就不用担心计算损失函数的时间成本和模型训练的复杂度,而且与整个参与训练的数据集的大小没有关系。

假设我们随机选取的一部分数据集包含stochastic个数据样本,那么随机梯度下降的参数更新公式如下:

训练样本的总数为stochastic,j=0…stochastic。从该公式中可以看出,随机梯度下降和批量梯度下降的计算过程非常相似,只不过计算随机梯度下降损失值时使用的是Jstochastic(θj),即这个损失值基于我们随机抽取的stochastic个训练数据集。随机梯度下降虽然很好地提升了训练速度,但是会在模型的参数优化过程中出现抖动的情况,原因就是我们选取的参与训练的数据集是随机的,所以模型会受到随机训练数据集中噪声数据的影响,又因为有随机的因素,所以也容易导致模型最终得到局部最优解。

4.Adam

最后来看一个比较“智能”的优化函数方法——自适应时刻估计方法(Adaptive Moment Estimation,简称Adam)。Adam在模型训练优化的过程中通过让每个参数获得自适应的学习率,来达到优化质量和速度的双重提升。举个简单的实例,假设我们在一开始进行模型参数的训练时损失值比较大,则这时需要使用较大的学习速率让模型参数进行较大的梯度更新,但是到了后期我们的损失值已经趋近于最小了,这时就需要使用较小的学习速率让模型参数进行较小的梯度更新,以防止在优化过程中出现局部最优解。

在实际应用中当然不止Adam这种类型的自适应优化函数,不过应用该方法在最后取得的效果都比较理想,这和Adam收敛速度快、学习效果好的优点脱不了干系,而且对于在优化过程中出现的学习速率消失、收敛过慢、高方差的参数更新等导致损失值波动等问题,Adam都有很好的解决方案。