指数加权平均:从温度平滑到Adam优化器的核心机制

发布时间:2026/10/19 19:36:51

指数加权平均:从温度平滑到Adam优化器的核心机制 1. 从一个温度曲线说起为什么优化算法需要“加权平均”先说一个我当年刚接触深度学习时的困惑处理时间序列数据比如某地一年的每日温度数据往往带有很大的随机噪声。今天30度明天25度后天突然跳到31度如果直接把原始数据拿来画曲线你会看到一条锯齿状、完全看不出趋势的线。但如果我们把连续几天的温度做个平均呢比如取前后各3天的滑动平均曲线就平滑多了能看出季节变化。这就是最朴素的想法——用历史数据的平均值抵掉单日观测的随机起伏。可是滑动窗口平均有个先天缺陷它要保存最近N天的原始数据窗口越长占的内存就越多。而且窗口内所有天的权重是一样的昨天和10天前的温度对“今天该是多少度”的参考价值显然不同。更麻烦的是窗口滑到边界时数据会突变算出来的平均值会跳动。指数加权平均Exponential Weighted Average, EWA就是来解决这些问题的。它不需要保存整个窗口只需要一个变量每来一天数据就更新一次而且越近的数据权重越大越远的数据按指数速度衰减。这种特性让它成了深度学习优化算法的基础模块——Momentum、RMSProp、Adam底层全都在用这个思想。所以如果你打算认真学深度学习优化器就绕不开EWA。它不是某个特定优化器的附属品而是一套更底层的“平滑工具”理解了它后面看优化器源码会轻松很多。2. 指数加权平均的核心思路公式是怎么来的2.1 一行公式解决三个麻烦EWA的更新公式长这样v_t β * v_{t-1} (1 - β) * θ_t其中θ_t是第t时刻的真实观测值比如第t天的温度v_t是第t时刻的指数加权平均值也是我们维护的那个“变量”β是衰减因子取值范围在0到1之间通常取0.9、0.98、0.999这类接近1的值刚看到这个公式的人第一反应往往是这不就是“新旧数据的加权平均”吗新数据权重(1-β)上一步平均值权重β对吧对但又不完全对。如果只是新旧两个数字做加权平均那这个式子顶多是个平滑滤波器。它的精妙之处在于v_t会一直向下“传递”。你把v_t逐步展开会得到一个累加和v_t (1-β) * (θ_t β * θ_{t-1} β² * θ_{t-2} β³ * θ_{t-3} ...)每一项的系数是β的k次方。β取0.9时第10天前的数据权重已经变成了0.9^10 ≈ 0.349第50天前只剩0.9^50 ≈ 0.005基本可以忽略。看它天然就把“遗忘”这件事写在系数里了。这也顺势解决了三个问题需要存历史数据吗不需要。无论时间线拉多长你手上只有一个v_t变量在跟着迭代走。权重怎么分配越近的数据权重越大而且是指数式递减这符合绝大多数时间序列的直觉——近期信息比远期信息更有参考价值。窗口边界突变怎么办根本不存在窗口概念自然不会因为窗口滑动产生突变。2.2 展开式里的数学直觉来看一个具体例子。假设β0.9某天的v_t 100第二天真实温度θ_{t1}20那v_{t1} 0.9*100 0.1*20 92。你会看到新值20只让平均线挪动了8个点。原因很简单β0.9意味着上一轮积累的信息占了90%的权重单日噪声被大幅压制了。反过来如果β0.5那么v_{t1} 0.5*100 0.5*20 60平均值瞬间掉下来40个点曲线对噪声就非常敏感。所以β本质上就是一个“记忆长度”调节器。β越接近1记忆越长曲线越平滑β越小响应越快但噪声越大。3. β这个超参数到底在控制什么3.1 0.5、0.9、0.999的直观差异常有人在代码里随手填一个β但不知道这个数字背后对应多长的记忆范围。有个近似公式可以帮我们估算“有效记忆长度”大约影响近 1/(1-β) 个时间步的数据这个近似是怎么来的因为β^k衰减到约1/e ≈ 0.367时可认为影响基本消失。如果β0.90.9^k ≤ 0.1需要k≈22而直接算1/(1-0.9)10。其实更标准的是让β^k 1/e得出k ln(1/e) / ln(β) -1 / ln(β)。当β分别取0.9、0.99、0.999时β值有效记忆步数约平滑程度典型用途0.51~2步几乎不平滑极少用过于敏感0.910步左右轻度平滑Momentum默认值0.99100步左右较强平滑RMSProp、Adam默认值0.9991000步左右极强平滑Adam的二阶矩估计3.2 用温度数据比一比假设有30天温度序列第1~10天在30度附近第11~20天在20度附近第21~30天在25度附近中间叠加随机噪声。β0.9的曲线基本贴合真实温度变化滞后大约2~3天噪声被削掉大半。β0.99的曲线非常平滑但变化也慢第11天温度骤降时它要用好几天才能“拐过弯”来滞后明显。β0.5的曲线贴着原始数据抖平滑效果差但几乎没有滞后。这就是EWA的经典“利弊交换”平滑度和响应速度不可兼得。想更平滑就要忍受更大的延迟想快速跟上变化就得接受噪声。这个取舍在优化算法里尤其重要训练初期梯度方向变来变去需要短记忆赶快修正训练后期梯度变小需要长记忆稳定方向。很多进阶优化器之所以效果好正是因为它能在不同阶段动态调整这个“记忆长度”。4. 初学者最常踩的坑偏差修正4.1 为什么一开始的EWA值“偏低”如果你直接照着公式初始化v_0 0然后开始更新会观察到一个尴尬现象前几步的v_t明显偏小和真实值对不上。举例。β0.9真实温度第一天θ_1 30v_1 0.9*0 0.1*30 3第一天算出的平均值是3而真实温度是30差了快10倍。此时如果直接拿3去当“平均温度”用误差极大。原因是初始的v_00是人为设定的虚拟值它把前面所有真实值都“稀释”了。这就像你运动手环第一天戴系统不知道你过去水平用0作为起点算出来的平均值自然被拉低。随着迭代继续v_t会逐渐逼近真实平均水平但“起步阶段偏低”这个偏差确实存在。在训练神经网络时这个偏差会影响早期的梯度更新方向严重时让前几百步的训练变得不够稳定。4.2 修正公式与实操示例标准做法是在计算v_t后进行修正v_t_corrected v_t / (1 - β^t)看上面β0.9, t1的情况v_1_corrected 3 / (1 - 0.9^1) 3 / 0.1 30正好修正回真实温度30。t越大β^t越接近0v_t_corrected就越接近v_t。也就是说偏差修正只在前期起作用后期影响可忽略。实际操作中需要注意修正用t不是用t1很多照抄公式的代码会用错。如果不修正训练初期动量项会有偏向0的错误信号影响收敛速度。PyTorch的SGD源码里momentum版本其实没有刻意分出一套完全独立的修正逻辑但Adam里做了类似处理可见这个细节在不同优化器里处理方式并不完全一样。5. 从EWA到Momentum优化器的第一块拼图5.1 动量法到底改了什么标准梯度下降每次更新参数是w w - learning_rate * gradient问题在于梯度本身是有噪声的。一个batch的梯度可能指向A方向下个batch又偏向B方向更新路径非常抖收敛慢。动量法Momentum引入了一个“速度项”把每步梯度也做一次EWAv_t β * v_{t-1} (1-β) * gradient_t w w - learning_rate * v_t你看这不就是EWA吗v_t在这里扮演的是“梯度的指数加权平均”。因为梯度是向量所以v_t也是向量每个维度独立做EWA。这样改的效果是如果某几个batch的梯度方向大致一致这些梯度的平均向量会朝着一个“相对稳定”的方向前进如果某个batch的梯度方向跑偏了EWA会把它压下去。生活类比你推一个购物车下坡每次有人从侧面轻轻碰一下车购物车不会立刻转向因为之前积累的动量还在推着它向前。动量法就是这个原理——动量越大抗噪声能力越强。5.2 对动量项的直观理解动量法里β通常取0.9相当于最近约10步的梯度在共同决定更新方向。单个batch带来的局部噪声被后面十步的分量平均掉了。每步更新不再听当前gradient的“片面之词”而是看一段时间的“集体意见”。和标准SGD相比Momentum在弯曲的误差面上表现好很多。比如某个维度上梯度方向频繁翻转标准SGD会来回震荡、走得很慢动量法则因为累计速度项不会彻底转向整体向前。实测下来这类优化器在图像分类、目标检测这种标准任务上比普通SGD收敛快损失曲线也更平滑。我最早在某个图像分类模型上试过不加动量loss曲线波动很大加了之后明显稳定。6. RMSProp与AdamEWA的更高级玩法6.1 RMSProp如何用上EWARMSProp解决的问题是“不同参数维度的尺度差异”。有的权重参数梯度大有的梯度常年很小统一用一个学习率就容易顾此失彼。RMSProp的思路是给每个参数单独维护一个梯度平方的EWAs_t β * s_{t-1} (1-β) * (gradient_t)²更新时w w - learning_rate / sqrt(s_t ε) * gradient_t注意这里EWA的对象变成了梯度平方。梯度大的维度s_t就大sqrt(s_t)大除以它之后有效学习率被压低梯度小的维度有效学习率被放大。这就是“自适应学习率”的核心思想。这里面EWA的作用同样是“平滑”。梯度平方值单看一个batch可能非常大但如果它只是偶发大值EWA会把它平摊到历史里不让某一步的异常梯度把学习率短期压得特别低。6.2 Adam双EWA的组合拳Adam把动量法和RMSProp结合同时维护两个EWAm_t梯度的指数加权平均对应动量项默认β10.9v_t梯度平方的指数加权平均对应自适应学习率默认β20.999更新时它对这两项都要做偏差修正m_t_corrected m_t / (1 - β1^t) v_t_corrected v_t / (1 - β2^t) w w - learning_rate * m_t_corrected / (sqrt(v_t_corrected) ε)注意β20.999意味着它要累计近千步的梯度平方信息所以二阶矩的估计非常稳定但也意味着早期v_t严重偏小偏差最明显必须靠偏差修正扳回来。如果你在实现Adam时漏掉这一步前期参数更新会异常大模型容易直接飞掉。所以你看Adam并不是什么神秘算法它就是一个“梯度一阶矩的EWA”加上一个“梯度二阶矩的EWA”再配一个偏差修正机制。理解EWAAdam源码里的大部分逻辑就已经清楚了。7. 手写EWAPython代码实现与调参实验7.1 基础版EWA实现下面这份代码实现了基础EWA并对比了不同β的平滑效果。我平时做演示时会生成一个带噪声的合成时间序列模拟温度漂移。import numpy as np import matplotlib.pyplot as plt def exponential_weighted_average(series, beta0.9): v 0.0 result [] for t, value in enumerate(series, start1): v beta * v (1 - beta) * value # 如果做偏差修正用下面这一行 # v_corrected v / (1 - beta ** t) result.append(v) return np.array(result) # 生成模拟温度数据三段不同均值 噪声 np.random.seed(42) t np.arange(1, 121) true_temp np.where(t 40, 10, np.where(t 80, 30, 20)) noise np.random.normal(0, 2, sizet.shape) data true_temp noise plt.figure(figsize(10, 5)) plt.plot(t, data, alpha0.3, labelraw data) for beta in [0.5, 0.9, 0.99]: ewa exponential_weighted_average(data, betabeta) plt.plot(t, ewa, labelfbeta{beta}) plt.legend() plt.xlabel(day) plt.ylabel(temperature) plt.title(Exponential Weighted Average with different beta) plt.show()这段代码输出三根曲线直接能看出β0.5跟随噪声波动β0.99平滑但明显滞后β0.9是相对均衡的选择。7.2 带偏差修正的版本加了偏差修正的版本变化只在更新的那一行def exponential_weighted_average_corrected(series, beta0.9): v 0.0 result [] for t, value in enumerate(series, start1): v beta * v (1 - beta) * value v_corrected v / (1 - beta ** t) result.append(v_corrected) return np.array(result)用同一份数据跑一遍把修正前后的曲线叠加对比你能看到前10步差异明显——未修正的曲线从0附近爬升修正后的曲线起手就贴合真实均值。训练类模型时建议直接用修正版避免早期更新方向偏掉。7.3 在简单梯度下降里显式使用EWA下面用随机生成的小数据集手写一个仅含一个线性层的模型显式加入EWA动量观察收敛行为。import torch import torch.nn as nn torch.manual_seed(0) X torch.randn(200, 5) y X torch.tensor([1.5, -2.0, 3.0, 0.5, -1.0], dtypetorch.float32) 0.1 model nn.Linear(5, 1, biasFalse) optimizer torch.optim.SGD(model.parameters(), lr0.02, momentum0.9) loss_fn nn.MSELoss() for epoch in range(200): optimizer.zero_grad() loss loss_fn(model(X).squeeze(), y) loss.backward() optimizer.step() if epoch % 20 0: print(fepoch {epoch}, loss {loss.item():.4f})这里的momentum0.9就是EWA的β。你把它改成0或0.99跑一遍对比loss曲线能直观体会到β对收敛速度和平稳性的影响。我个人试下来0.5看不出明显平滑效果0.99起步时loss下降变慢但后期更稳。8. 实操中的建议与常见问题8.1 什么时候需要修β对应的步数实际训练里很少有人只调β一个参数因为β和learning rate是联动的。β增大时EWA记忆更长、速度项更稳定。但速度项的更新幅度也变了需要配合调整学习率。一个不严谨但直观的经验β从0.9提到0.99相当于速度项“惯性”大了约10倍相应学习率一般要适当调小防止更新幅度过大反过来β调小时模型响应变快但要小心loss震荡这种联动关系在Adam上调β2频率不高因为0.999已经是相对稳定的默认值。很多框架里提供的beta参数其实建议先用默认值不要随手改。8.2 网上那些“调参玄学”可靠吗经常看到有人总结“β0.9是动量最优值”“Adam不用调β”之类的话。我个人的体验是这些说法有实践基础但别太迷信。β0.9只是在大量任务中表现稳定不代表它对你的任务最优。如果你的训练数据分布变动很快0.9的步数记忆可能太长可以试0.8甚至0.7验证集上观察两三轮就能看出差异。另外还要注意有些框架对动量实现方式是“乘在梯度上”比如PyTorch的SGD源码里更新公式在实现上与理论公式有细微差别。照抄理论代码去对齐框架实现刚开始会对不上这不奇怪重点看损失曲线是不是稳定下降。8.3 几个常见问题EWA和滑动窗口平均结果接近吗接近但EWA更省内存且能对近期数据倾斜。若要严格的窗口内平均需要存储窗口数据在小批量场景下一般没这个必要。偏差修正只对初始阶段有用对。t越大β^t越接近0修正项接近1。但t1时的差异可能达数十倍不能省。RMSProp里的ε是干什么的加在除根号上防止除以0一般取1e-8。太小早期梯度平方接近0时数值不稳太大会把自适应调节能力削弱。能不能用EWA做数据预处理当然可以。很多时序平滑、滑动统计都可以用EWA替代只需选好β。8.4 别踩的坑最普遍的坑是把EWA值直接当原始信号用。EWA的设计目标是体现“当前趋势”不是每个时刻的精确值。评估模型时如果需要精确值该用原始数据就用原始数据EWA只适合展示趋势不适合做最后的标准答案。还有人在实现Adam时对一阶动量做偏差修正、对二阶动量不做修正。这样早期二阶矩严重偏小有效学习率虚高实践里经常导致第一步参数猛跳。修正要么都做要么都别做偏工减料是最危险的。最后建议你把上面那几段Python代码跑一遍改成自己的时间序列比如股票收盘价、传感器读数直观感受一下β从0.5调到0.999时曲线的形态变化。这里面积累的手感比记住任何公式都重要。
延伸阅读

更多相关文章

2026/10/19 19:36:51

Popek-Goldberg定理:虚拟化可行性的数学基石

1. 项目概述:为什么“Popek和Goldberg定理”至今仍是虚拟化技术的基石你可能在读某篇关于云平台底层架构的文章时,偶然看到“Popek和Goldberg定理”这个名词,旁边还跟着一句“该定理证明了虚拟机监控器(VMM)的可行性”…

2026/10/19 19:36:51

分词、词性标注与命名实体识别:NLP核心任务工程实践指南

做NLP相关项目也有几年时间了,从最开始用正则表达式硬匹配,到后来用统计模型,再到现在折腾预训练模型,绕了一大圈发现:不管上层玩法怎么变,底层的分词、词性标注、命名实体识别这些核心任务始终是绕不开的基…

2026/10/19 19:36:51

AI工具助力毕业设计:论文撰写与代码复现的8款高效实战指南

又到了毕设冲刺季,我身边前后好几届的同学都在同一条河里扑腾:论文没思路、代码跑不通、实验数据对不上。尤其今年AI工具铺天盖地,但大多数人的用法还停留在“复制粘贴一段文字让AI重写”的水平,根本谈不上“助力”。我自己带过几…

2026/10/19 21:08:22

大模型选型指南:从模型维度到应用维度的完整决策框架

1. 大模型赛道的分野逻辑与选型困局 过去两年我一直在做企业侧的模型选型咨询,经手过的项目从智能客服、代码辅助到多模态内容审核,覆盖了十来个行业。每次开新项目,团队问得最多的永远是同一个问题:市面上这么多模型,…

2026/10/19 21:08:22

搞懂MySQL存储引擎:InnoDB与MyISAM选型调优指南

1. 从一个线上事故说起,为什么必须先搞懂存储引擎 你有没有遇到过这种情况:线上的某个统计表数据量涨到几百万行之后,select 查询突然慢得离谱,insert 也开始排队,整个页面卡死。我最早踩这个坑是在给某模拟项目X做一套…

2026/10/19 21:08:22

基于Python的UDP可靠传输实现:从停等协议到GBN滑动窗口

简介:这是一份基于Python实现的可靠数据传输协议课程设计资源包,以UDP为底层通道,完整演示了停等协议、GBN滑动窗口协议及SR协议的设计与实现过程。面向计算机网络课程学生、需要完成类似实验或对传输层协议感兴趣的学习者,可借此…

2026/10/19 21:08:22

表格合并全攻略:从Excel自带功能到代码方案一网打尽

表格合并这事儿,看起来简单,真做起来恶心过多少人,我太有数了。尤其是月底、年底那几天,群里一片哀嚎:销售数据分了十二个月、各门店表头还不一样、刘姐交上来的表编码是文本格式,张哥那边编码却是数字&…

2026/10/19 21:03:21

Python+大模型+微博舆情分析:从数据采集到可视化全链路实战指南

每年到毕业设计季,“微博舆情分析”这个方向都会被大量同学翻牌,尤其是加上Python和大模型之后,听起来既有技术含量又紧跟热点。但真正动手之后很多人会发现:微博数据怎么拿、情感分析怎么做准、大模型怎么接、预测结果怎么才能不…

2026/10/19 18:06:35

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/19 0:04:56

悟空开源无代码平台实战:从实体建模到应用设计避坑指南

简介:基于悟空开源无代码平台的多种应用设计源码,面向希望在不编写代码的情况下快速搭建CRM、HRM、财务系统、ERP、SRM等业务应用的企业与技术人员,通过拖放式界面和内置模板即可完成应用定制与部署。压缩包共697个文件,约10.74MB…

2026/10/19 0:04:56

基于.NET9的多租户权限系统:数据权限与动态API落地实践

简介:这份资源是一套面向 .NET 与 Vue 全栈开发者的中台权限管理系统,后端基于 .Net9,前端采用 Vue3 Element Plus,并配套 uniapp uviewui 移动端方案,实现前后端分离。系统覆盖多租户隔离、数据权限、动态 Api、任务…

2026/10/19 0:04:56

场地预约小程序毕设实战:SSM+微信小程序+MySQL数据库设计到避坑

简介:面向毕业设计场景的场地预约小程序完整项目,基于微信小程序SSMMySql技术栈开发,适合计算机相关专业学生作为选题参考、功能扩展或二次开发起点。系统实现场地类型管理、场地管理、预约管理、取消申请与押金退回等功能,分为管…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑