一个技巧让你的模型不再波动:指数移动平均!

您所在的位置:网站首页 u8使用技巧 一个技巧让你的模型不再波动:指数移动平均!

一个技巧让你的模型不再波动:指数移动平均!

2023-04-04 17:38| 来源: 网络整理| 查看: 265

译者 | 严钟响

单位 | 东北大学自然语言处理实验室

前言

指数移动平均是一种神经网络训练技巧,有时可以提高模型的准确性。具体来说,不是使用来自最终训练迭代的优化参数作为模型的最终参数,而是使用在所有训练迭代过程中参数的指数移动平均值。在这篇博文中,我想快速讨论一下指数移动平均以及它如何改进深度学习模型的泛化。

原文链接:https://leimao.github.io/blog/Exponential-Moving-Average/

移动平均

移动平均是一种平滑技术,通常用于减少时间序列数据的噪声和波动。例如,如果我们想建立一个使用历史数据预测酒店房价的模型,对历史数据应用移动平均通常可以帮助模型更好地预测。移动平均最简单的形式是简单移动平均(simple moving average ,SMA),它采用前k 个数据点的等权重平均。具体而言,给定 k 个数据点 p_1,p_2,...,p_t,.. ,在 t 时刻的 SMA_t 计算公式如下。

\mathrm{SMA}_{t}=\frac{1}{k} \sum_\limits{i=t-k+1}^{t} p_{i}

我们也可以用 SMA_{t-1} 进行迭代计算,这个技巧在计算在线流数据的SMA非常有用。

\mathrm{SMA}_{t}=\mathrm{SMA}_{t-1}+\frac{1}{k}\left(p_{t}-p_{t-k}\right)

实际上还有其他移动平均变体,包括累积平均和指数移动平均。在数学上,移动平均是一种卷积运算,是对一定数量的先前数据点的一种加权平均。

指数移动平均

指数移动平均(exponential moving average,EMA) 计算所有先前数据点的加权平均值,并且权重呈指数衰减。具体来说,给定一系列数据点 p_1,p_2,...,p_t,.. ,在 t 时刻的 SMA_t 计算公式如下。

\mathrm{EMA}_{t}=\left\{\begin{array}{ll} p_{1} & \text { if } t=1 \\ \alpha p_{t}+(1-\alpha) \mathrm{EMA}_{t-1} & \text { else } \end{array}\right.

其中 \alpha\epsilon(0,1] 。

从上面的等式中,还没办法直观感受到“指数平均”,但是,如果我们把公式展开得到

\begin{aligned} \mathrm{EMA}_{t} & =\alpha\left[p_{1}+(1-\alpha) p_{2}+(1-\alpha)^{2} p_{3}+\cdots\right] \\ & =\alpha \sum_{i=1}^{t}(1-\alpha)^{i-1} p_{i} \end{aligned}

我们发现每个数据点的系数呈指数衰减,并且上述等式可以进一步重新排列成加权移动平均形式。

\begin{aligned} \text { EMA }_{t} & =\alpha \sum_{i=1}^{t}(1-\alpha)^{i-1} p_{i} \\ & =\frac{1}{\frac{1}{\alpha}} \sum_{i=1}^{t}(1-\alpha)^{i-1} p_{i} \end{aligned}

可以证明,当 t\rightarrow\infty , \frac 1\alpha 是所有数据点前面的数据和。

\begin{aligned} \sum_{i=1}^{t}(1-\alpha)^{i-1} & =\frac{1\left(1-(1-\alpha)^{t}\right)}{(1-(1-\alpha))} \\ & =\frac{1-(1-\alpha)^{t}}{\alpha} \\ & \stackrel{t \rightarrow \infty}{=} \frac{1}{\alpha} \end{aligned}

很明显,现在 EMA 只是一个加权移动平均,其权重呈指数衰减。

指数移动平均如何改进模型泛化

理想情况下,给定一个包含N个带标注样本的训练集D,神经网络中的参数 \theta 将通过最小化某种训练损失函数 L(D;\theta) 来优化。如果神经网络没有在训练数据集上过拟合,并且验证数据集和训练数据集是同分布的,则在训练集上达到最小损失的参数也能在校验集上达到最小损失。在这种情况下,我们用 \theta^* 来表示优化后的参数,这是一个局部最优值。

在实践中,N通常非常大,因此使用整个训练数据集进行参数优化的代价变得非常昂贵,尤其是使用梯度下降等常见的神经网络优化技术。因此,不是使用整个训练数据集,而是随机抽取来自训练数据集的小样本(称为 mini-batch)进行训练。这实际上给训练引入了噪音,而这种训练噪音既有优点也有缺点。在梯度下降中,使用整个训练数据集进行参数更新的梯度是从使用小批量的梯度中估计出来的,因此梯度计算速度更快但精度也更低。然而,不太准确的梯度或噪声的梯度有时可以帮助优化,从而产生比使用完整数据集训练得到的局部最优参数更优,这就是mini-batch引入的训练噪声的优势。

在梯度下降中,当参数优化快要收敛时,整个训练数据集的梯度会越来越小。随着学习率也变小,优化后的参数将是真正的局部最优。然而,由于使用 mini-batch 的梯度有噪声且不太准确,当参数优化即将收敛时,优化后的参数有可能不是局部最小值,而是围绕局部最小值波动。这是由mini-batch 引入训练噪声的缺点。

平滑技术,尤其是 EMA,可用于降低优化后的参数波动噪声,并且使得参数更有可能接近局部最小值。具体来说,每个更新步骤后的优化参数是 \theta_1,\theta_2,...,\theta_t,...\theta_n 。这就像一系列带有噪声的时间序列数据。因此,EMA可以提高模型的泛化能力。为了去除噪声,优化参数的 EMA 计算如下

\mathrm{EMA}_{t}=\left\{\begin{array}{ll} \theta_{1} & \text { if } t=1 \\ \alpha \theta_{t}+(1-\alpha) \mathrm{EMA}_{t-1} & \text { else } \end{array}\right.

代码实现

原博客对指数移动平均做了理论上的分析,但是缺乏代码总感觉少了点干货,因此笔者参阅了pytorch的实现,在此分享一下自己的理解。pytorch在optim/swa_utils.py实现了一个AveragedModel类,我们根据下面代码进行逐步讲解。

从第1,2行可以看出这个类继承于Module类,这说明AveragedModel同样会有自己的模型权重,之后接受四个参数model,device,avg_fn,use_buffers,我们依次分析一下。从第四行可以看出,AveragedModel实际上会对原来的model做一个深度拷贝,这个在tf中被称为影子权重,拷贝出来的权重更新并不依赖反向传播,而是根据自己定义的规则。avg_fn就是参数平均的方法,如果不指定的话,那么9-12行这里会定义一个默认的SMA方法,可以看到这里的实现是和上文的公式对应的(分母部分n_averaged初始化为0,故需要加一)。use_buffers是用来计算模型参数和缓冲区的平均值,通常情况下我们都不需要用到这个参数,但是如果模型包含了Batch Normalization这样的操作,我们还需要更新它的均值和方差,这个时候需要把它设置为True。

上图所示代码是影子权重更新的规则。20-27行是利用itertools将模型参数展开成一个可迭代列表方便操作,我们往后面看34行调用了avg_fn函数,也就是自定义的参数平均规则,用就地操作copy_()复制了更新后的模型权重。每次更新完后n_averaged需要自增1。

pytorch官方也提供了一个使用模型指数平均的简单示例。

AveragedModel使用起来时非常简便的,只需要把原来的模型包装一下即可,需要注意的是在warmup阶段是不需要使用模型参数平均的。

阅读更多内容请查看“机器翻译学堂”

关于机器翻译学堂

机器翻译学堂是一个以机器翻译为核心的学习平台。面向所有的自然语言处理、机器学习等领域的学习者,分享论文解读、学习资料、优质博客、会议信息、行业动态、开源数据集等资源。

欢迎大家多多关注机器翻译学堂,一起学习,共同进步!

网站:https://school.niutrans.com

微信公众号:jiqifanyixuetang



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3