ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用AdaGrad、RMSProp、Adam优化LMS算法:MATLAB实现与对比

用AdaGrad、RMSProp、Adam优化LMS算法:MATLAB实现与对比 简介这是一套基于MATLAB实现的LMS算法源码并整合了AdaGrad、RMSProp、Adam三种自适应学习率优化策略面向毕业设计、课程设计以及项目开发场景适合需要研究自适应滤波、梯度下降优化或算法对比的MATLAB使用者。资源包共13个文件其中6个.m脚本分别实现标准LMS训练、测试以及三种优化器训练版本3个.fig和3个.jpg用于保存和展示对比结果1个.md说明文档介绍代码结构与实验思路整个压缩包仅496KB轻量易用便于快速下载与二次修改。目前已有101人学习下载。代码刻意将标准LMS与三种优化版本分开存放主程序统一调用可直观对比不同学习率策略下的收敛曲线和稳态误差同时支持修改步长、迭代次数等参数进行扩展实验既适合本科毕设和课程设计中的算法演示也适合工程人员在此基础上做进一步开发。1. 用自适应学习率改造LMS从固定步长到逐分量缩放跑过LMS自适应滤波的人多半有过这种体验步长μ调大一点误差曲线刚冲下去就开始震荡调小一点权值像蜗牛爬等收敛了参考信号早已变了。固定步长是LMS的核心设计也是它最别扭的地方——收敛速度与稳态失调是一对天然矛盾。把AdaGrad、RMSProp、Adam这三种在深度学习中常用的自适应学习率优化器套到LMS的权值更新上正是为了用逐分量、逐时刻的缩放来解决这个矛盾。这个题目是毕业设计、课程设计里的常见选题但常见的写法止步于“跑通三种优化器并画出对比图”。本文会把LMS的递推骨架先拆开再分别给出三种优化器的MATLAB实现、参数含义和调节边界最后落到系统辨识场景下怎么对比收敛曲线、怎么查发散原因。信号处理方向的学生、需要做自适应滤波仿真的工程师以及想用MATLAB把“经典算法现代优化器”做成完整项目的读者都能按文中的代码直接起步不需要额外工具箱有MATLAB基础环境就够。2. LMS算法的递推骨架与固定学习率的边界2.1 从维纳滤波到LMS递推公式拆开看维纳滤波要求已知输入信号的自相关矩阵R与输入-期望互相关向量p再解维纳-霍夫方程。现实中的信号统计特性随时间变化矩阵求逆既昂贵又不实时。LMS的做法是用瞬时梯度替代统计梯度定义误差e(n)d(n)wᵀx(n)其中x(n)是由最近order个输入样本组成的向量w是权值向量。取损失函数J(w)0.5e²(n)则瞬时梯度为∇Je(n)x(n)顺着负梯度方向走一步得到最核心的权值递推式w(n1)w(n)μ·e(n)·x(n)这个式子就是整篇文章的地基。μ是固定学习率它同时控制收敛速度与稳态失调。收敛的必要条件是0μ2/λ_maxλ_max是输入自相关矩阵的最大特征值。输入功率越大μ必须越小否则权值更新会在最优解附近来回跳动甚至发散。2.1.1 为什么“最小均方”却无法同时要速度和精度把权值更新看成随机逼近过程μ大等效于在噪声梯度方向上放大步伐收敛快但稳态时权值在维纳解周围的波动也大μ小波动小但瞬态时间常数与1/(μλ)同量级收敛慢。实际工程中若输入信号的功率波动范围超过一个数量级固定μ几乎不可能选得合适。这就是引入自适应学习率的最大理由让每个权值分量拥有独立的等效学习率。2.2 最小可运行MATLAB里写一个LMS函数为了后续对比公平先实现一个不带任何优化的固定步长LMS输入为x、期望信号d、滤波器阶数order和步长mu输出为权值序列与误差序列。function [w, e] lms_fixed(x, d, order, mu) % LMS固定步长实现 % x: 输入信号列向量 % d: 期望信号列向量 % order: 滤波器抽头数 % mu: 固定学习率 N length(x); w zeros(order, 1); % 权值初始化为0 e zeros(N, 1); % 记录每个时刻的误差 for n order:N xn x(n:-1:n-order1); % 构造输入向量注意时间倒序 yn w. * xn; % 滤波器输出 en d(n) - yn; % 先算误差 w w mu * en * xn; % 再更新权值 e(n) en; end end代码逻辑分三步构造输入向量、计算误差、执行权值更新。这里必须强调x(n:-1:n-order1)的倒序切片它让抽头延迟线与卷积的定义对齐顺序反了会导致权值与输入错位实验结果直接发散。mu的取值与输入信号幅度强相关文件开头可以加一行归一化x (x - mean(x)) / std(x);把输入标准化后再跑mu0.01、0.03这类数值才有可移植性。2.2.1 用误差平方的滑动平均看收敛直接画误差序列会看到剧烈抖动肉眼很难判断收敛趋势。常见做法是对误差平方做指数滑动平均MATLAB里一句即可mse_avg filter(0.01, [1, -0.99], e.^2);这里0.99是遗忘因子等效时间窗口约为100个样本。比plot(e)更可靠后续所有对比曲线的绘图都建议用这种处理后的曲线。2.3 学习率μ的稳定性上界与发散迹象固定步长LMS的调参本质上是在两个指标之间找平衡下表列出μ在不同取值区间下的典型表现可作为调试时的判断依据。μ取值区间收敛速度稳态失调误差曲线形态远小于上界很慢很小单调平缓下降接近上界的一半快适中快速下降后进入平稳带接近或超过上界快但危险显著增大先降后震荡甚至上翘明显超过上界不收敛无法定义持续增长出现NaN工程上常用μ1/trace(R)作为粗略上界若不想估计自相关矩阵也可以直接用1/mean(x.^2)估计。发散的两个典型标志误差平方的滑动平均连续若干点不降反升或者权值向量w出现数量级跳变。遇到NaN或Inf时先不要怀疑算法优先检查输入是否包含NaN、d与x是否长度一致、xn切片是否越界。3. AdaGrad、RMSProp、Adam优化LMS三种策略的MATLAB实现3.1 为什么深度学习里的优化器能搬到LMS上深度学习优化器解决的问题是梯度在不同维度上尺度不一致希望每个参数都有独立的有效学习率。LMS的瞬时梯度−e(n)x(n)同样存在这个问题当输入信号是有色噪声或语音时各抽头位置的输入功率差异明显单一μ会让大功率抽头震荡、小功率抽头收敛迟缓。把AdaGrad、RMSProp、Adam中的累积梯度统计量引入LMS权值更新本质上是把标量μ替换成一个逐分量调节的自适应系数。三者共享同一个框架维护额外的梯度统计量用统计量对瞬时梯度做归一化。区别只在于统计量的计算方式不同。3.1.1 统一视角三个优化器都是“梯度除以尺度”AdaGrad用全历史梯度的平方和做分母RMSProp用指数滑动平均的梯度平方做分母Adam在RMSProp基础上增加一阶矩估计并做偏差校正。理解了这一层LMS部分不需要任何改动只需改动权值更新那一行这也是这个课题最适合做进阶实验的原因LMS的滤波器结构是固定的变量全在更新策略上实验结果容易归类解释。3.2 AdaGrad-LMS累积平方梯度做逐分量缩放AdaGrad为每个权值分量维护一个累积量G(n)每一步把瞬时梯度的平方累加进去更新时用sqrt(G)ε去除学习率。算法特征很明显梯度平方持续累积分母单调增大等效学习率随时间严格衰减越到后期更新越保守。function [w, e] lms_adagrad(x, d, order, eta, eps) % AdaGrad优化的LMS % eta: 基础学习率区别于固定步长mu % eps: 防止除零的小常数通常取1e-8 N length(x); w zeros(order, 1); G zeros(order, 1); e zeros(N, 1); for n order:N xn x(n:-1:n-order1); en d(n) - w. * xn; grad -en * xn; % LMS瞬时梯度 G G grad.^2; % 累积平方梯度逐元素平方 w w - eta * grad ./ (sqrt(G) eps); e(n) en; end endgrad.^2是对每个分量单独做平方G的维度与w保持一致./表示逐元素相除。AdaGrad-LMS中eta的典型取值在0.01到0.1之间比固定步长的mu可以大一些因为分母项会不断压制学习率。它适合输入信号较稀疏、梯度方差大的场合但不适合非平稳输入——一旦G累计得过大后期无论误差多大都没有能力继续更新这也是它后来被RMSProp取代的主要原因。3.3 RMSProp-LMS滑动窗口解决累积衰减问题RMSProp把AdaGrad的“全历史累积”改成“指数滑动平均”引入衰减系数rho。每一步更新为G(n)rho·G(n−1)(1−rho)·grad.²这样近期的梯度信息权重更大远古梯度的影响按指数衰减等效于只统计最近约1/(1−rho)个样本的梯度能量。在MATLAB里只需要把上一节函数里的累积行替换掉。function [w, e] lms_rmsprop(x, d, order, eta, rho, eps) % RMSProp优化的LMS % rho: 滑动平均衰减系数常用0.9或0.99 N length(x); w zeros(order, 1); G zeros(order, 1); e zeros(N, 1); for n order:N xn x(n:-1:n-order1); en d(n) - w. * xn; grad -en * xn; G rho * G (1 - rho) * grad.^2; % 指数滑动平均 w w - eta * grad ./ (sqrt(G) eps); e(n) en; end endrho取0.9时有效窗口约10个样本取0.99时约100个样本。窗口越短对输入功率突变的响应越快但稳态时梯度估计抖动也越大。做LMS实验时我一般先用rho0.99因为滤波器的收敛过程相对平缓过短的窗口会把噪声引入等效学习率中产生不必要的权值抖动。eta与AdaGrad同量级仍为0.01左右。3.4 Adam-LMS一阶矩与二阶矩联合修正Adam在RMSProp基础上多维护一个一阶矩估计m配合beta1、beta2两个衰减系数并对初始时刻的矩估计做偏差校正。更新公式可以写为m beta1·m (1−beta1)·grad v beta2·v (1−beta2)·grad.² m_hat m / (1−beta1^t) v_hat v / (1−beta2^t) w w − lr·m_hat ./ (sqrt(v_hat)eps)偏差校正这一步不能省m和v初始为0早期几步若不做校正估计值严重偏小等效学习率会异常放大导致前几个样本就把权值推飞。function [w, e] lms_adam(x, d, order, lr, beta1, beta2, eps) % Adam优化的LMS % lr: 基础学习率典型0.001~0.01 % beta1: 一阶矩衰减系数默认0.9 % beta2: 二阶矩衰减系数默认0.999LMS场景可调小为0.99 N length(x); w zeros(order, 1); m zeros(order, 1); v zeros(order, 1); e zeros(N, 1); for n order:N xn x(n:-1:n-order1); en d(n) - w. * xn; grad -en * xn; m beta1 * m (1 - beta1) * grad; % 一阶矩 v beta2 * v (1 - beta2) * grad.^2;% 二阶矩 t n - order 1; % 当前迭代次数 m_hat m / (1 - beta1^t); % 偏差校正 v_hat v / (1 - beta2^t); w w - lr * m_hat ./ (sqrt(v_hat) eps); e(n) en; end end深度学习中的默认参数beta10.9、beta20.999在LMS场景下不是最优的。原因是深度学习的训练样本数以万计而LMS实验数据长度通常只有几千点beta2取0.999时v的估计严重滞后于梯度变化前几百步的分母估计失真。LMS场景下把beta2降到0.99或0.995收敛更平稳。lr的调节范围比前两者更小通常0.001到0.005不要一开始就取0.1。4. 系统辨识实测三种优化LMS在MATLAB里的对比与参数调节4.1 实验场景未知FIR系统的在线辨识把LMS用于未知FIR系统辨识是最经典的验证场景输入信号x通过一个未知的权值向量w_true生成输出再叠加少量噪声作为期望信号dLMS在线估计w_hat观察w_hat与w_true的差。这个场景的好处是“真值已知”可以精确计算权值误差比单纯看误差收敛更直观。MATLAB里生成实验数据只需几句话注意固定随机种子以保证实验可复现rng(42); % 固定随机种子 N 5000; % 样本数 order 8; % 滤波器阶数 w_true [1, -0.5, 0.25, -0.1, 0.05, -0.02, 0.01, -0.005]; x randn(N, 1); % 白噪声激励 d filter(w_true, 1, x) 0.01 * randn(N, 1); % 期望信号filter(w_true, 1, x)把w_true当作FIR系数直接滤波生成的d与x之间存在真实的线性关系。0.01倍的randn是观测噪声幅度控制为信号能量的1%左右让稳态失调有一个可比的下限。4.2 对比脚本把四种LMS跑在同一个数据集上写一个统一入口脚本调用第2、3章中的四个函数分别计算权值误差的归一化范数。% 对比四种LMS的收敛行为 mu 0.02; % 固定步长LMS参数 eta 0.01; % AdaGrad与RMSProp基础学习率 rho 0.99; lr 0.003; % Adam学习率 [~, e_fixed] lms_fixed(x, d, order, mu); [~, e_adag] lms_adagrad(x, d, order, eta, 1e-8); [~, e_rms] lms_rmsprop(x, d, order, eta, rho, 1e-8); [~, e_adam] lms_adam(x, d, order, lr, 0.9, 0.99, 1e-8); % 误差平方的滑动平均 alpha 0.01; mse_fixed filter(alpha, [1, alpha-1], e_fixed.^2); mse_adag filter(alpha, [1, alpha-1], e_adag.^2); mse_rms filter(alpha, [1, alpha-1], e_rms.^2); mse_adam filter(alpha, [1, alpha-1], e_adam.^2); % 用半对数坐标观察早期收敛速度 semilogy(mse_fixed); hold on; semilogy(mse_adag); semilogy(mse_rms); semilogy(mse_adam); legend(LMS, LMS-AdaGrad, LMS-RMSProp, LMS-Adam); xlabel(迭代次数); ylabel(误差平方滑动平均);filter的第二个参数写成[1, alpha-1]等价于y(n)0.01·e²(n)0.99·y(n−1)。为什么用semilogy而不是plot因为LMS收敛早期误差可能跨越两三个数量级线性坐标会把后期细节压扁在横轴附近半对数坐标能同时看清早期速度和稳态高度。4.2.1 脚本运行后先看什么第一次运行不要急着调参先看四条曲线是否分开、是否有发散。固定步长LMS若选择得当会在前500步快速下降然后进入平稳区AdaGrad-LMS的下降速度在初期与固定步长接近但后半段会出现明显“变慢”的拐点这是累积平方梯度持续增大的正常表现RMSProp-LMS与Adam-LMS的曲线整体更平滑其中Adam因为一阶矩的作用早期峰值比RMSProp更小。4.3 参数表与选择建议不同优化器在LMS场景下的参数调节范围与适用场景总结如下表中数值基于平稳白噪声输入、阶数在8到32之间的常见实验设置。优化器核心参数常见取值区间适用场景固定步长LMSmu0.005~0.05输入平稳、功率已知AdaGrad-LMSeta, epseta0.01~0.1, eps1e-8稀疏激励、短实验RMSProp-LMSeta, rho, epseta0.005~0.02, rho0.9~0.99输入功率波动、非平稳Adam-LMSlr, beta1, beta2lr0.001~0.005, beta10.9, beta20.99不想精细调mu、要稳定收敛需要注意这些数值不是从某份官方文档里抄来的而是这套代码在白噪声激励下的通用经验值。把输入换成语音、心电信号或通信信号时幅度差异可能高达几十倍最稳妥的做法是先对输入做零均值单位方差归一化再套用表中区间。AdaGrad与RMSProp的基础学习率eta可以比固定步长mu大一倍因为分母项会持续压制步长Adam的lr反而要小因为它有动量累积过大的lr容易在早期冲出稳定区域。4.4 收敛曲线的四个检查点与调参方向曲线画出来后按下面四个顺序逐一检查能少走很多弯路前50步是否出现尖峰脉冲。出现说明基础学习率偏大或eps偏小先检查eps是不是取成了0再把lr/eta缩小3倍重跑。AdaGrad曲线是否过早进入平台。若后半段几乎水平且误差值差于固定步长LMS说明eta过大导致累积平方梯度快速膨胀把eta减半再试。RMSProp与Adam的稳态抖动是否过大。把rho从0.99改成0.999或把beta2从0.99改成0.995通常可以压制稳态波动代价是收敛速度略慢。固定步长LMS的mu是否真的“调到合理”。常见误区是拿一个明显偏小的mu去做对比然后声称自适应学习率“全面碾压”。合理做法是先粗略搜索mu找到临界发散为止再取临界值的四分之一到二分之一作为对比基准这样得到的结论才有说服力。5. 收敛异常排查与毕业设计代码组织的三个技巧5.1 发散不一定是学习率问题先查这四件事实验发散时先别急着调参数先检查数据通路。第一输入向量x(n:-1:n-order1)与期望d(n)对齐没有若期望信号在时间上超前或滞后一拍相关关系被破坏任何优化器都会发散。第二输入是否包含异常值或NaN训练数据里混入Inf会让G和v瞬间爆炸即使Adam也救不回来用any(isnan(x))先做检查。第三数据长度是否足够固定步长LMS的时间常数约为1/(μλ)若N只有500点而μ取0.001曲线根本来不及下降容易被误判为“算法不行”。第四对比时是否用了相同的输入顺序四种算法必须在同一份x、d上跑否则任何对比都没有意义。5.2 用继承体系组织源码更适合答辩展示的MATLAB结构把四种算法各写成独立函数虽然能跑但横向对比时重复代码多、参数传递啰嗦。课程设计和毕业设计答辩中面试老师更希望看到清晰的扩展结构。常见做法是定义一个抽象基类统一的构造方法接收x、d、order子类各自实现更新策略classdef LMSFilter handle properties w e end methods (Abstract) update(obj, xn, en) end methods function run(obj, x, d, order) N length(x); obj.w zeros(order, 1); obj.e zeros(N, 1); for n order:N xn x(n:-1:n-order1); en d(n) - obj.w. * xn; obj.update(xn, en); obj.e(n) en; end end end end继承类只需实现update方法。比如Adam子类把m、v、beta1、beta2作为属性update里按第3.4节公式更新。这样做的好处是新增一种优化器不用重写run方法答辩时也可以现场演示“增加一个继承类就能跑新算法”。MATLAB继承语法在R2014b之后都是通用的老版本也能运行。5.3 用rng、参数表与半对数坐标保住实验可复现性自适应滤波实验的随机性来自输入信号与噪声不做种子控制的实验几乎不可能复现。每个脚本开头固定rng(42)是最低要求更进一步把每次实验的mu、eta、rho、beta1、beta2与最终稳态MSE写入表格params {LMS, mu, mu; Adam, lr, lr; ...}; T cell2table(params, VariableNames, {Algo, ParamName, Value}); writetable(T, exp_records.csv);这能让评审老师看到“参数可追溯结果可复核”。绘图时统一用semilogy展示误差曲线最后20%样本的平均误差作为对比指标而不是挑一个幸运时刻的误差值。5.4 用稳态MSE随学习率变化的U形曲线做参数验证一个很实用的验证技巧固定其他参数只改变一个优化器的学习率记录每个学习率下的稳态MSE取后20%样本的均值然后以学习率为横轴、稳态MSE为纵轴画图。固定步长LMS会得到一条先降后升的U形曲线U形底部的宽度就是该优化器的稳定区间AdaGrad因累积机制曲线右侧的上升段更陡Adam因方差校正底部相对更宽更平。这张图比单次收敛曲线更有信息量既能说明“固定步长对μ敏感”又能说明“自适应学习率拓宽了稳定区间”是毕业设计论文里最值得放的一类实验图。把稳态MSE的计算封装成一个函数四种算法共用同一个评估逻辑后续换数据、换阶数时只需改一行。本文还有配套的精品资源点击获取
返回列表