资讯动态

递推最小二乘算法程序与实验报告:从原理到工程避坑完整指南

发布时间:2026/10/16 18:24:12 来源:尧图企业网站定制
简介围绕递推最小二乘RLS算法资料包含Python程序代码、配套说明文档和Word版详细实验报告适合正在学习自适应信号处理、系统辨识或参数估计的本科生与工程师也可作为课程实验与毕业设计的参考资料。压缩包共3个文件包含可直接运行的.py源码、txt程序说明和.doc实验报告整体仅316KB便于快速下载与阅读。代码按初始化、预测、误差计算、遗忘因子更新等步骤编写结构清晰注释简明Word报告则按算法背景、原理介绍、代码实现解析、实验结果与分析展开对递推公式推导和遗忘因子λ的影响均有详细说明。已有468人学习使用内容理论结合实践帮助读者从原理到实现完整掌握RLS在线参数估计方法并迁移到实时系统或工程场景中如在线预测、自适应滤波等。1. 递推最小二乘算法程序代码及word版详细实验报告这套资源到底在解决什么问题“递推最小二乘算法程序代码及word版详细实验报告.rar”——看到这个标题的人基本是同一类情况自动控制或信号处理课程的实验要求里写着“实现递推最小二乘系统辨识”或者毕业设计里需要一个能在线更新参数的估计模块。你下载这份资源不是为了把推导过程背下来而是想拿到一段能跑的代码和一份能照着填的报告。本文就把这两件事讲透递推最小二乘的更新公式到底在干什么、程序怎么写能跑通、Word报告里哪些内容才算“详细”以及调试时最常见的几个翻车点。这份资源通常解压后就是一个工程文件夹加一份Word文档但真正值钱的不是某个人的代码而是代码背后的参数选择和报告里的分析套路。我会先讲清楚算法原理再给完整可复现的Python实现然后拆解实验报告每个章节该写什么最后集中说五个换着花样翻车的典型案例。新手能按步骤抄作业想深究的人也能看到遗忘因子、持续激励、数值稳定性这些边界问题。2. 递推最小二乘的数学模型为什么它是批量最小二乘的在线升级版2.1 从批量最小二乘到递推用一行标量除法替代高维矩阵求逆先看批量最小二乘的经典公式。假设系统满足线性回归关系y(k) φᵀ(k) · θ v(k)收集了N组数据后把所有回归向量堆成矩阵Φ所有观测值堆成向量Y参数估计就是θ̂ (ΦᵀΦ)⁻¹ · Φᵀ · Y这个公式简单、好用但工程上有个致命限制每来一组新数据都要把旧的N1行数据重新拼矩阵然后重新做一个高维矩阵求逆。数据量到几千行之后单次求逆的时间就会让实时辨识变得不现实。递推最小二乘的思路是换一种累积方式保留上一次的估计结果θ̂(k-1)只拿新到的y(k)和φ(k)去修正它。整个递推过程只需要四个方程e(k) y(k) - φᵀ(k) · θ̂(k-1)K(k) P(k-1) · φ(k) / [λ φᵀ(k) · P(k-1) · φ(k)]P(k) [I - K(k) · φᵀ(k)] · P(k-1) / λθ̂(k) θ̂(k-1) K(k) · e(k)这里的P(k)对应批量最小二乘中的(ΦᵀΦ)⁻¹表示当前参数估计的不确定度。K(k)是增益向量决定新数据以多大权重修正旧估计。仔细观察就会发现分母λ φᵀPφ是一个标量更新P矩阵时做的也只是外积和矩阵加减全程没有一个高维矩阵求逆。这就是递推意义所在计算量从O(N³)降到O(dim²)dim是参数个数和累积数据量无关。代码实现时四个方程的先后顺序也很关键。第一步必须先算预测误差e(k)此时用的是旧参数θ̂(k-1)然后算增益K(k)接着更新P(k)最后才更新参数θ̂(k)。如果写成先更新参数再算误差数学上也能自洽但和教材的标准递推公式不对应调试时容易和文档里的符号打架。2.2 遗忘因子λ在线更新的“记忆灰度”和一张取值表递推最小二乘里唯一一个需要你手动调的参数就是遗忘因子λ取值范围是0到1。它的作用从P(k)更新公式里能直接看出来λ出现在分母同时P(k)整体除以λ。λ接近1P矩阵衰减慢历史数据的影响持续很久λ变小P矩阵在每次迭代时被放大更多让后面的新数据获得更大话语权。用等效记忆长度来理解更直观。遗忘因子λ对应的记忆长度近似为1/(1-λ)个采样点。也就是说λ0.99时大约最近100个点对参数估计起主要作用λ0.95时等效记忆长度只剩20步。实际使用中有一个普遍权衡λ越小跟踪时变参数越快但对噪声越敏感稳态时参数波动大λ太大估计稳定但反应迟钝。λ取值等效记忆长度典型适用场景0.99约100步系统参数缓慢漂移、测量噪声很小0.98约50步教材和大多数实验的默认选择0.95约20步参数变化较快但需要接受更大的估计波动0.90约10步快速时变系统噪声大时慎用初次做实验我建议直接从λ0.98起步。跑通之后把λ改成0.95和0.99各跑一次对比参数收敛曲线的波动幅度和跟随时滞这张对比图放进实验报告里比任何文字都说明问题。2.3 初始化三件套θ(0)、P(0)、持续激励三者怎么配递推最小二乘有四个初始化设置任何一个出错都会让程序要么不收敛、要么直接数值爆炸。第一个是参数初值θ̂(0)。一般取零向量。如果你对系统已有先验认识可以填补估计值但实验场景下零向量最稳妥让算法自己花几十步收敛过去。第二个是协方差矩阵初值P(0)。通常取大对角矩阵P(0) αIα从1e2到1e6都可以。P(0)大的含义是“我对初始参数完全没信心”这样头几步的增益K会比较大参数能快速从零拉到真实值附近。但α太大会看到参数初期的明显过冲太小则收敛极慢跑完整个数据序列参数还没到位。实验里常用P(0) 1e4·I和λ0.98、θ(0)0搭配。第三个输入信号必须满足持续激励条件。通俗说输入u(k)要足够“丰富”不能是常数或者单一频率的正弦波。因为递推最小二乘是靠回归向量φ(k)的各个方向来更新参数如果输入只在一个方向上变化P矩阵只有对应方向衰减其他方向的参数永远得不到修正。实验中用均匀白噪声或者伪随机二值序列PRBS最保险。第四个容易被忽略的就是初始段处理。由于θ(0)0和P(0)1e4前20到50步的参数轨迹往往有明显跳变。这不算发散但实验报告里画收敛曲线时最好把热身段和数据采信段分开说明。3. 递推最小二乘程序实现仿真数据、核心函数、收敛对照全套代码3.1 生成测试数据二阶ARX加噪模型与持续激励输入为了验证算法先构造一个已知参数的仿真对象。这里用二阶ARX模型y(k) a1·y(k-1) a2·y(k-2) b1·u(k-1) b2·u(k-2) v(k)真实参数取a11.2a2-0.35b10.6b20.4。输入u用均匀白噪声测量噪声v用零均值高斯分布。代码如下import numpy as np import matplotlib.pyplot as plt # 可复现随机种子改数字观察不同噪声实现的差异 rng np.random.default_rng(42) n 500 u rng.uniform(-1, 1, n) # 均匀白噪声满足持续激励 v rng.normal(0, 0.1, n) # 测量噪声 y np.zeros(n) for k in range(2, n): y[k] (1.2 * y[k-1] - 0.35 * y[k-2] 0.6 * u[k-1] 0.4 * u[k-2] v[k])代码逻辑很简单先初始化输入和输出序列然后从第3个点开始递推生成输出。注意y[0]和y[1]保持为0相当于系统从静止状态启动。均匀白噪声比正弦信号更能满足持续激励条件这是ARX辨识实验的通用做法。噪声方差0.1会让参数收敛曲线带有可观察的波动但不会掩盖收敛趋势如果改成0.01曲线会平滑很多报告里可以两组都跑。3.2 RLS核心递推函数误差、增益、协方差、参数四步更新的顺序核心算法封装成一个函数方便在不同实验中复用。参数向量维度是4对应[a1, a2, b1, b2]def rls(u, y, lam0.98, p01e4): 递推最小二乘4参数版本。 返回参数轨迹矩阵和最终估计参数。 n len(u) theta np.zeros(4) # [a1, a2, b1, b2] P p0 * np.eye(4) # 大对角初值表示完全未知 theta_hist np.zeros((n, 4)) for k in range(2, n): # 回归向量顺序必须与theta一致 phi np.array([y[k-1], y[k-2], u[k-1], u[k-2]]) e y[k] - phi theta # 1. 预测误差 Pphi P phi K Pphi / (lam phi Pphi) # 2. 增益向量分母是标量 P (P - np.outer(K, Pphi)) / lam # 3. 协方差更新 theta theta K * e # 4. 参数更新 theta_hist[k] theta return theta_hist, theta四步更新顺序是标准递推公式的顺序错一步结果对不上教材。增益K的分母是一个标量直接做除法就行不需要调用np.linalg.inv。P矩阵更新里的np.outer(K, Pphi)等价于K乘以Pphi的转置但写法更直观也避免了构造中间矩阵。如果忘记除以λP矩阵会不断膨胀到达一定步数后参数开始剧烈震荡后面避坑章节会专门说这个问题。调用方式很简单theta_hist, theta rls(u, y) # 打印最终估计结果 print(RLS最终估计:, theta)运行这个函数theta_hist每一行对应每一步的参数估计值。前期会有明显波动中后期逐渐平稳这就是收敛过程的可视化素材。3.3 跑通后的验证参数收敛曲线与批量最小二乘对照有仿真对象时批量最小二乘的结果可以作为“标准答案”来对照。批量版本直接套公式# 批量最小二乘结果作为参考标准 Phi np.array([ [y[k-1], y[k-2], u[k-1], u[k-2]] for k in range(2, n) ]) Y y[2:] theta_batch np.linalg.inv(Phi.T Phi) Phi.T Y这里直接把数据矩阵堆出来做一次整体求逆在仿真数据量不大时算得很快也和递推结果形成直接对比。你会看到RLS运行到最后估计值应该和批量最小二乘非常接近差在第三位小数以后这正是算法正确性的有力证据。画收敛曲线的代码true_theta np.array([1.2, -0.35, 0.6, 0.4]) fig, axes plt.subplots(2, 2, figsize(10, 6)) names [a1, a2, b1, b2] for ax, name, est, true in zip(axes.flat, names, [theta_hist[:, j] for j in range(4)], true_theta): ax.plot(est, lw1.8, labelname) ax.axhline(true, colorr, ls--, lw1, label真实值) ax.set_title(name) ax.grid(True) ax.legend() plt.tight_layout() plt.show()这段绘图逻辑把四个参数分别画在2×2的子图里每个子图加一条真实值的红色虚线。曲线在开始阶段会有一个较大的摆尾这是P(0)取大对角阵造成的不是代码错误。要得到更平滑的展示可以跳过前50个点的轨迹不画或者直接把收敛段单独截出来放大。验证时还可以做一个蒙特卡洛实验换不同的随机种子运行50次记录最终估计值的均值和方差。均值应接近真实参数方差反映噪声和遗忘因子共同决定的稳态波动水平。这部分数据放在实验报告里可以明显提升“详细”程度。4. Word实验报告怎么搭六段式结构、图表规范和三张必写的表4.1 报告骨架实验目的到结论的六个章节与每处该写什么Word版详细实验报告通常不是要求你写成长篇论文而是按“实验目的、实验原理、实验设备、实验步骤、结果与分析、结论”六个模块填满。每个模块的篇幅和侧重点完全不同一张表说清楚章节核心内容篇幅建议实验目的用2到3句话说明RLS能干什么半页以内实验原理从批量最小二乘引出递推公式标出每个符号含义1到2页公式占一半实验设备操作系统、Python版本、NumPy版本、运行环境5到8行实验步骤数据生成、RLS递推、绘图验证的执行顺序1页以内结果与分析收敛曲线、残差分析、参数对比表2到3页重点是分析结论算法是否收敛、参数是否准确、局限和可改进点半页以内实验目的不要写成套话。更合适的写法是直接给具体能力“通过本实验理解递推最小二乘的在线更新机制掌握遗忘因子对跟踪性能的影响能够用RLS对含噪声ARX模型进行参数辨识。”这样读起来像一份技术备忘而不是从教材里摘出的定义。实验原理部分要用Word公式编辑器插入递推四式而不是截图。这里需要逐一解释e(k)、K(k)、P(k)、θ̂(k)的物理含义特别强调P(k)对应批量最小二乘里的(ΦᵀΦ)⁻¹。实验设备里不要出现模糊的“某版本Linux”直接写实际运行环境比如Windows 11 Python 3.11 NumPy 1.26。4.2 结果分析的三个固定动作收敛曲线、残差自相关、参数表格结果与分析的写法决定了报告是“详细”还是“流水账”。这三个动作每一个都对应一个具体产出。第一个动作是收敛曲线图。用上一章的2×2子图图题写“图1 RLS参数收敛过程”四个子图分别对应a1、a2、b1、b2。每张子图都要有红色真实值虚线作为参照否则读者只能看到曲线无法判断误差大小。如果λ改过多个值应把λ0.98、0.95、0.99三组收敛曲线放在同一张图里用不同颜色区分说明遗忘因子对收敛速度和波动的影响。第二个动作是残差自相关分析。计算每个采样点的残差e np.zeros(n) for k in range(2, n): phi np.array([y[k-1], y[k-2], u[k-1], u[k-2]]) e[k] y[k] - phi theta然后用matplotlib的acorr函数画残差自相关图或者直接观察残差序列是否像白噪声。残差如果仍有明显周期成分说明模型阶次不够或遗漏了常数项这是提升报告深度的重要切入点。第三个动作是参数对比表这是整个报告中信息密度最高的一张三线表。表格至少五列参数真实值RLS估计批量LS估计相对误差(%)a11.2填入运行结果填入运行结果计算后填入a2-0.35填入运行结果填入运行结果计算后填入b10.6填入运行结果填入运行结果计算后填入b20.4填入运行结果填入运行结果计算后填入相对误差的计算用|估计值-真实值|/|真实值|×100%。RLS和批量LS的结果应当基本一致如果差距明显说明递推还没收敛到稳态需要增加数据点数或检查初始化参数。4.3 代码怎么摆进Word正文只放核心段完整代码放附录报告里最容易出现的问题是贴一大堆代码结果正文被代码块占掉大半。正确的排版方式是正文只放RLS核心函数这段大约15行的代码数据生成和绘图细节放到附录。放正文的代码要满足一个条件——读者不运行任何脚本光看代码就能理解递推四步的顺序。所以核心函数里要保留中文注释变量名和报告公式里用到的符号尽量一致。批量最小二乘公式和蒙特卡洛验证代码放附录结果与分析里通过“详见附录B”引用。Matplotlib画图时还要处理一个很实际的中文乱码问题。默认字体不识别中文时图题和标签全是方框报告观感大打折扣。在绘图脚本开头加三行配置import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] FalseSimHei在大多数Windows环境可用。如果字体设置后仍然乱码检查系统是否有该字体或者换成微软雅黑。图的编号、表的编号要手动维护每一张图必须有图题每一张表必须有表题引用的时候写“图1”而不是“下图”。这些细节凑在一起才是“word版详细实验报告”该有的完成度。5. 递推最小二乘避坑排查五个换着花样翻车的典型案例5.1 P(0)设成0程序跑通了参数却一行不动的“假收敛”现象代码不报错循环正常执行但theta_hist整条曲线是一条水平直线参数始终是初始值。原因增益K(k)的计算公式里分子是P(k-1)·φ(k)P(0)0时分子永远是0K恒为零θ̂(k)永远等于θ̂(k-1)。整个递推过程退化成“空转”。解决P(0)必须用大对角矩阵初始化实验里P(0)1e4·I已经足够。如果你对系统有把握可以把α调小但千万不要设0或者极小值。遇到参数不更新的问题第一反应就检查P矩阵初值这个坑非常经典。5.2 λ取1时变系统面前算法变成一条反应迟钝的鲸鱼现象仿真系统原本参数不变某一步突然把a1从1.2改成0.8RLS估计值需要几百步才缓慢爬向新值期间预测误差显著增大。原因λ1时等效记忆长度无穷大算法把历史所有数据等权看待。系统参数突变了但旧数据还占主导参数自然追不上。解决改为λ0.95到0.99。想要跟随时变参数λ就必须小于1具体数值根据时变速度和噪声水平折中。判断λ是否合适的简单方法是看“参数突变后50步内是否明显接近新值”是则合理否则继续调小λ。5.3 输入信号不满足持续激励部分参数锁死、部分参数乱跳现象输入u(k)用常数或单一频率正弦波最终估计结果中b1、b2看起来正常a1、a2却明显偏离真实值有时还漂移不定。原因递推最小二乘靠回归向量的信息更新P矩阵输入激励不足时P矩阵某些特征方向衰减极慢对应的参数得不到有效修正。本质是持续激励条件不满足信息矩阵接近奇异。解决把输入换成白噪声或PRBS序列保证φ(k)各个方向都有激励。更规范的做法是算一下回归向量的自相关矩阵条件数条件数过大就先处理输入序列再辨识。5.4 P更新漏掉除以λ前100步正常第500步开始数值爆炸现象前期参数收敛得很好到一定步数之后参数曲线开始剧烈震荡甚至出现NaN。回头看代码P更新那行只写了P P - np.outer(K, Pphi)漏掉了除以λ。原因递推公式里P(k) [I - K(k)φᵀ(k)]·P(k-1)/λ漏掉λ后P矩阵只减不增在持续激励不足的方向上会被反复累积数值误差最终导致协方差矩阵失去正定性参数发散。这是我见过频率最高的血泪经验。解决逐行对照公式检查P更新行确认分母上的λ还在。调试时可以打印P矩阵的特征值如果出现负特征值多半就是这行写错。5.5 数据含直流分量但模型没有常数项参数整体偏移看上去还挺合理现象仿真时给u或者y叠加了一个常数偏置但RLS模型仍然是φ [y(k-1), y(k-2), u(k-1), u(k-2)]最后四个参数全部收敛残差也不大但对照真实值整体偏移。原因模型缺少常数项直流分量无法被参数线性组合解释于是被强行分摊到a1、a2、b1、b2上导致参数整体偏置。这种错误看起来“合理”因为残差没有明显异常极易漏检。解决处理办法有两种——对u和y先做去均值预处理或者在回归向量里加一列常数1同时把参数维度扩大到5。第二种更通用毕竟工程数据里直流分量很难完全避免。6. 递推最小二乘的工程进阶自适应遗忘因子和平方根滤波怎么选6.1 普通RLS在工程里的两个软肋固定记忆长度和数值正定性损耗固定遗忘因子意味着无论系统变化快慢记忆长度始终一样。系统长期平稳时较小的λ带来不必要的波动系统突然变化时较大的λ又反应不过来。自适应遗忘因子的思路是用残差能量来判断系统是否在变化从而动态调整λ。数值正定性损耗是普通RLS在长序列或持续激励不足时的隐患。P矩阵理论上是正定对称阵但浮点运算中反复乘除法会逐渐破坏这一性质。对于几千步的课程实验影响几乎看不到但嵌入式设备上跑几万步或者信号本身病态时就可能出问题。6.2 自适应遗忘因子用残差窗口让λ自己动一种工程上常用的做法是维护一个残差滚动窗口窗口内残差的RMS值越大说明当前模型对系统变化的跟踪越差就把λ调小让算法更快地“忘记”旧数据加速追赶。下面这段代码演示了这个思路模型带常数项维度5def rls_adaptive(u, y, p01e4, win30, lam_base0.98): n len(u) dim 5 theta np.zeros(dim) P p0 * np.eye(dim) hist np.zeros((n, dim)) lam lam_base e_win [] for k in range(2, n): phi np.array([y[k-1], y[k-2], u[k-1], u[k-2], 1.0]) e y[k] - phi theta # 滚动残差窗口 e_win.append(e) if len(e_win) win: e_win.pop(0) rms_e np.sqrt(np.mean(np.square(e_win))) # 残差越大λ越小0.1是归一化基准按噪声量级调整 lam max(0.90, lam_base - 0.05 * (rms_e / 0.1)) Pphi P phi K Pphi / (lam phi Pphi) P (P - np.outer(K, Pphi)) / lam theta theta K * e hist[k] theta return hist, theta这段代码里的自适应规则是线性的不是严格推导出来的最优策略但在很多实际场景下够用。关键是归一化基准0.1必须根据真实噪声方差来设定噪声本身RMS就是0.3那这个阈值会让λ一直被压到最低反而丢失了自适应能力。第一步先测量系统稳定时的残差RMS再设定基准值这是调参的第一原则不算玄学。6.3 平方根滤波数值稳定性优先的场景才值得换平方根滤波的原理不复杂不直接递推P矩阵而是递推P的平方根因子每一步保证P正定。实现上比普通RLS多几行矩阵分解运算比如LDL分解或Cholesky因子更新。普通RLS和平方根滤波的取舍可以这样判断对比项普通RLS平方根滤波实现难度低四行公式搞定中高因子更新逻辑复杂数值稳定性长序列下可能丢失正定性稳定适合单精度环境适用场景课程实验、万步以内嵌入式实时系统、超长序列课程实验和论文仿真里普通RLS足够如果做的是嵌入式实时辨识数据量动辄十万步级别或者只能用单精度浮点平方根滤波才值得投入时间改造。我现在的习惯是任何新系统上先跑普通RLS固定λ0.98把整体流程走通确认模型结构和数据质量没问题之后再考虑是否升级成自适应遗忘因子或平方根滤波。直接上复杂算法会引入额外变量出问题时根本分不清是模型问题还是数值问题。这个顺序能省掉大量排查时间希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑