
简介基于最小二乘递推算法的MATLAB参数估计源码面向需要掌握RLS在线参数估计的科研人员、工程师及高年级本科生适用于信号处理、系统辨识与实时数据分析等场景。递推方式可依据新数据实时更新模型参数无需存储全部历史数据适合时间序列与在线应用。资源核心为一个MATLAB脚本完整串联数据生成、模型定义、初始化、预测、误差计算与参数更新等关键步骤并附带基本注释便于对照理论理解运算流程有MATLAB使用基础的读者可直接运行观察参数随迭代收敛的过程。压缩包内仅包含1个 .m 脚本文件大小约1KB结构极简、无冗余文件适合直接阅读、修改与二次开发。已有210人学习下载适合作为快速搭建参数估计仿真环境的起点也为进一步研究加权递推最小二乘、扩展卡尔曼滤波或粒子滤波算法打下基础。1. 最小二乘递推算法在参数估计里解决什么问题做系统辨识的人基本都遇到过这个场景手里有一堆输入输出数据想拟合一个传递函数或者差分方程模型。最直接的想法是拿全部数据做一次最小二乘一次解出所有参数。但问题在于工业现场的数据是边采边来的继电器动作、电压波动、负载切换每一个新样本都可能带着系统当前状态的信息。等数据存够了再一次离线解方程要么错过参数漂移的窗口要么被迫重复求解越来越大的矩阵算力和存储都吃不住。递推最小二乘Recursive Least SquaresRLS的思路就是每来一个样本用上一步的参数估计值加上一个修正项得到新的估计值不需要保留整段历史数据。它不改变最小二乘的估计准则只是把批量计算变成了在线迭代使参数估计能够跟着系统的实际输出走。这套方法在MATLAB里做仿真尤其顺手可以先用一个已知参数的差分方程生成仿真数据再用RLS反向估计对比估计值和真实值的偏差检验算法的收敛性和跟踪能力。写这份源码时会涉及几个核心部件系统的回归向量构造、递推增益矩阵、协方差矩阵更新以及遗忘因子的引入。这个过程也依赖仿真对象的模型结构假设比如ARX模型、阶数选择、采样周期是否合理。本文就按“递推公式→搭建仿真→加遗忘因子→自检结果”这条路径把参数估计的一份可运行的MATLAB仿真源码讲清楚不绕弯子。2. 递推最小二乘的迭代结构与公式落地2.1 从批处理最小二乘到递推形式改了什么先看一眼批量最小二乘的基本写法。对线性回归模型y(k) φT(k)θ e(k)其中 y(k) 是系统输出φ(k) 是回归向量由过去输入输出构成θ 是待估计参数向量e(k) 是噪声项。如果有 N 组数据把回归向量堆成矩阵 Φ输出堆成向量 Y最小二乘解是θ̂ (ΦTΦ)^(-1)ΦTY。这里的矩阵求逆在数据量增大时开销会快速上升而且每来一个点ΦTY 和 ΦTΦ 都得重算一遍现场设备通常扛不住。递推最小二乘的出发点是把 (ΦTΦ)^(-1) 记作协方差矩阵 P(k)暂不考虑遗忘因子利用矩阵求逆引理将第 k 步的结果表达成第 k-1 步的结果加修正量。每次更新不碰整个历史矩阵只处理当前样本的回归向量 φ(k) 和输出 y(k)复杂度从随数据量增长变为固定。代价是需要给 P 和 θ 设置初值这个初值会影响早期几步的收敛速度后文会专门给一组推荐值。递推公式的标准写法如下θ̂(k) θ̂(k-1) K(k)[y(k) - φT(k)θ̂(k-1)] K(k) P(k-1)φ(k) / [λ φT(k)P(k-1)φ(k)] P(k) 1/λ [I - K(k)φT(k)] P(k-1)表达式里 λ 是遗忘因子工程上取 0.95 到 1 之间λ1 就是标准RLS。中括号里那一项 y(k) - φT(k)θ̂(k-1) 是新息物理含义是“上一轮参数对当前样本的预测误差”。增益矩阵 K(k) 决定这个误差里有多少比例用来修正参数看起来很像卡尔曼滤波的增益计算事实上两者在数学结构上确实同源。2.2 回归向量怎么构造这是很多人第一步就错的地方做参数估计仿真时回归向量 φ(k) 的构造直接决定模型结构。以最常见的 ARX 模型为例y(k) a1 y(k-1) ... ana y(k-na) b1 u(k-1) ... bnb u(k-nb) e(k)这种结构下回归向量取φ(k) [-y(k-1), ..., -y(k-na), u(k-1), ..., u(k-nb)]T待估参数向量是θ [a1, ..., ana, b1, ..., bnb]T。这里有一个容易掉进去的坑MATLAB的索引从1开始而采样序列从0或1开始计时构造 φ(k) 时如果直接用 k-1 作为下标会在 k1 时指向0触发越界。写源码时习惯上从 k max(na, nb) 1 开始迭代或者提前预填一段零向量。另一个常见错误是把 y(k) 自己放进回归向量这会形成回归元与噪声相关估计结果有偏仿真时看起来很漂亮但和真实模型对不上。输入 u 要选持续激励信号白噪声、PRBS伪随机二进制序列都可以正弦叠加也凑合但不能是常数或斜率不变的斜坡。2.3 初值和噪声方差的影响仿真里怎么看递推初值的选法可以按规则来不必猜。一般取θ(0) 0P(0) aIa 是一个较大的正数比如 10^4 或 10^6。P(0) 取得大相当于一开始认为参数估计的不确定性很大第一步修正量也会比较大这样前几十步能快速从零点逼近真实值。如果 a 取得太小比如 1收敛会慢甚至看起来像卡住了。但 a 也不是越大越好过大会导致前几步修正幅度过大在含噪数据下早期估计曲线出现明显过冲。噪声方差的作用体现在估计结果的稳态波动幅度上。仿真里如果给 e(k) 设定为方差 0.01 的白噪声估计曲线会在真实值附近小幅波动把噪声方差提高到 0.5参数曲线会明显抖动这时需要靠遗忘因子或滤波来平衡。下面是标准RLS在一个二阶ARX模型上的结构示意注释里标出了每一步的职责。% 标准RLS核心迭代单步 % P: 协方差矩阵, 维度由theta长度决定 % theta:当前参数估计列向量 % phi: 当前回归向量列向量 % y: 当前系统输出标量 % lam: 遗忘因子, 取1为无遗忘 % 计算增益 K按标准RLS公式 K P * phi / (lam phi * P * phi); % 先用当前theta预测输出并算出新息 innovation y - phi * theta; % 更新参数估计 theta theta K * innovation; % 更新协方差矩阵I 为单位矩阵 P (eye(length(theta)) - K * phi) * P / lam;这段代码是递推的“心脏”放在for循环里对每个采样点执行一次。增益计算时做一个标量除法如果 lam phi * P * phi 接近0说明输入激励不足或者P数值异常仿真里会出现参数突变甚至发散。协方差更新用了自左乘的方式把 P 顺序放在右边避免矩阵维度被广播错误。每次循环结束后可以把 theta 存进预先分配的大矩阵里仿真结束后画图看收敛轨迹。循环外面还要准备两个东西一是数据生成用的真实模型系数二是与真实模型同结构的输入输出序列。这样估计出来的 theta 才有对照物判断算法实现是否正确就有了依据。3. 用MATLAB写一个最小二乘递推参数估计仿真3.1 仿真数据怎么生成用真实模型当标尺在MATLAB里做参数估计仿真的第一步不是先写递推函数而是先用“已知答案的模型”生成输入输出数据。常见做法是定义一个离散传递函数或差分方程加白噪声扰动把仿真步数定在几百到几千之间。生成的数据放在工作区后面RLS算法用到的 y(k) 和 u(k) 都是从这里取。% 参数估计仿真 - 数据生成部分 % 真实系统: y(k)0.8y(k-1)0.2y(k-2)0.4u(k-1)0.3u(k-2)e(k) % 目标是让RLS把 [0.8,0.2,0.4,0.3] 估出来 rng(42); % 固定随机种子保证可复现 N 2000; % 仿真步数取长一点便于观察收敛 u idinput(N, prbs, [0, 0.2], [-1, 1]); % 伪随机二进制序列幅值可调 e 0.05 * randn(N, 1); % 白噪声扰动方差0.05^2 y zeros(N, 1); for k 3:N y(k) -0.8*y(k-1) - 0.2*y(k-2) 0.4*u(k-1) 0.3*u(k-2) e(k); endPRBS这类激励信号的作用是让系统所有模态都被激活这样回归向量里的各项信息量是充分且持久的RLS才能收敛到唯一解。噪声方差设成 0.0025信噪比大约在20dB上下比较接近现场仪表数据的粗糙程度。如果你用常值输入输出会趋向稳态回归向量里相邻样本高度相关递推出来的参数会出现震荡且不随步数增加而收敛。3.2 主循环与在线估计完整源码拿到数据后进入参数估计的核心部分。写源码时建议把RLS单独做成一个函数或脚本块不要和画图逻辑混在一起方便切换不同的遗忘因子进行对比实验。这里给出可以直接在MATLAB中运行的主循环版本。% RLS参数估计主循环 % 对ARX模型: y(k)a1 y(k-1)a2 y(k-2)b1 u(k-1)b2 u(k-2) na 2; % 输出阶次 nb 2; % 输入阶次 n na nb; % 待估参数个数 theta zeros(n, 1); % 参数初值为0 % 协方差矩阵初值大数乘以单位阵 P 1e6 * eye(n); % 遗忘因子先用1观察基本收敛行为后续可改0.97 lambda 1; theta_hist zeros(n, N); % 保存每一步的参数估计轨迹 for k 3:N % 构造当前回归向量 % 注意顺序输出项【注意符号】在前输入项在后 phi [-y(k-1); -y(k-2); u(k-1); u(k-2)]; % 单步递推 K P * phi / (lambda phi * P * phi); innovation y(k) - phi * theta; theta theta K * innovation; P (eye(n) - K * phi) * P / lambda; % 保存历史 theta_hist(:, k) theta; end % 画图比较真实参数与估计参数 figure; plot(1:N, theta_hist); hold on; plot(1:N, [0.8 0.2 0.4 0.3] * ones(1, N), k--, LineWidth, 1.5); xlabel(迭代步数); ylabel(参数值); legend(a1估计, a2估计, b1估计, b2估计, 真实值); grid on;上面代码里的回归向量 a1 和 a2 对应模型中的正系数输出项但差分方程标准形式里 y(k-1) 前面是负号所以回归向量里取 -y(k-1)。而图里面画真实值时写 0.8 和 0.2不是 1.8、1.2属于MATLAB图注的语义约定不要搞混。如果画出来的曲线最终停在 0.8、0.2、0.4、0.3 附近说明RLS的递推结构没错P初值引入的修正已经收敛完毕。曲线在前30步内出现陡峭上升或下降不是算法发散而是 P(0) 很大的正常表现。P矩阵在这个循环里会越来越小最后趋于一个较小常数矩阵。这是因为随着数据增加信息量积累参数估计的协方差在减小。但如果你引入遗忘因子 P 到达一个平衡值后不会持续缩小而是维持在一个固定量级这表示算法“记住”的是最近一段时间的数据而不是全部历史。这个区别在参数缓变系统里特别重要。3.3 阶次不匹配时的表现怎么判断模型结构用错先给一个结论如果真实系统阶次是2而你估的时候na和nb取成1参数估计曲线不会平滑收敛残差序列也明显表现出相关性因为模型欠拟合。再比如真实系统含有时滞而你构造的回归向量里没有对应的 u(k-d)那么估计出的 b 系数会分散到多个相邻项上参数值稳定了但传递函数和真实系统不完全等价。对照实验的做法是改变 phi 的维度观察残差序列是否接近白噪声。残差按res(k) y(k) - phi * theta计算把残差的自相关画出来如果相关性明显就该增加阶次。另外也可以用MATLAB自带的 armax 或 tfest 函数做一次离线辨识把离线结果当作RLS的参照系。两者一致说明RLS递推实现在数值上没有问题只是模型结构选择层面的独立判断。下面是几个常用参数的参考表在调RLS仿真时可以直接对照调整参数或变量推荐取值影响P(0)1e41e6 乘以单位阵越大收敛越快但早期过冲越大θ(0)零向量或由离线OLS估计零向量省事离线初值能让收敛更快更稳遗忘因子 λ0.951.0越小跟踪越快稳态波动越大输入信号PRBS、周期方波、白噪声必须持续激励否则P矩阵病态噪声方差0.0010.1影响稳态估计方差不影响渐近收敛性采样步数5005000短了看不到收敛长了浪费算力运行仿真代码后如果遇到“仿真发散”现象通常先看 P 矩阵是否出现非正定再看输入激励是否充足最后检查 phi 里是否不小心混入了噪声相关的量。4. 遗忘因子的作用跟踪时变参数4.1 从无遗忘到遗忘因子收敛行为怎么变标准RLS把全部历史数据等同对待这在参数不随时间变化时是最优的。实际现场里的设备参数会漂移阀门的磨损让增益缓慢变化环境温度让电阻值偏移负载切换让电机模型的结构改变。此时需要让算法“忘记”太老的数据给新数据更高的权重。遗忘因子 λ 就是干这个的。λ1时所有样本等权λ0.98时算法相当于只有约 1/(1-λ)50 个样本的记忆窗口λ越小记忆越短跟踪能力越强但参数估计的稳态方差也会变大因为用来平均的样本少了。使用时变参数做仿真就能直观看到 λ 取值的效果。比如系统参数在第1000步时从 0.8 跳变到 0.5λ1 的RLS要经过一两百步才能慢慢追过去而且由于P已经很小修正增益低追赶速度非常慢。改成 λ0.97 后P会在一个相对较大的平衡值附近波动参数曲线能在几十步内跟上变化。下面是带遗忘因子RLS的仿真变体只改动了核心循环的P更新行。% 带遗忘因子的RLS - 时变参数跟踪仿真 % 真实参数在第1000步从旧值切换为新值观察跟踪效果 lambda 0.97; % 遗忘因子记忆越短跟踪越快 theta_hist zeros(n, N); theta zeros(n, 1); P 1e4 * eye(n); % 有遗忘时P初值不用取太大 % 在数据生成部分加入参数跳变 for k 3:N if k 1000 y(k) -0.8*y(k-1) - 0.2*y(k-2) 0.4*u(k-1) 0.3*u(k-2) e(k); else y(k) -0.5*y(k-1) - 0.2*y(k-2) 0.4*u(k-1) 0.3*u(k-2) e(k); end end for k 3:N phi [-y(k-1); -y(k-2); u(k-1); u(k-2)]; K P * phi / (lambda phi * P * phi); innovation y(k) - phi * theta; theta theta K * innovation; P (eye(n) - K * phi) * P / lambda; theta_hist(:, k) theta; end运行后对比两条参数轨迹能看清一个关键区别λ1 时P持续缩小参数一旦收敛就很难再动λ1 时P趋近一个稳态矩阵参数曲线像“跟着目标跑”收敛后仍有小幅波动。波动的幅度由噪声方差和λ共同决定仿真中如果想削弱波动可以把噪声方差调低或者在递推之前对输入输出做一次低通滤波。注意低通滤波器本身会引入相位滞后可能让数据失真仿真验证时可以先不加。4.2 遗忘因子和P初值的耦合坑在哪带遗忘因子的RLS有一个容易被忽略的问题λ 越小P的稳态值越大初始阶段过冲越明显。原因在于P更新式里每次都除一个小于1的λ即使新息为0P也会因除法而缓慢增大直到信息量和遗忘速率达到平衡。如果P(0) 也已经很大前几步的K会异常大参数一步就冲到很远的位置随后才慢慢拉回来。建议做法是P(0) 与遗忘因子匹配当 λ 在0.95到0.99之间时P(0) 取 1e2 到 1e4 即可没必要再上1e6。如果你在做仿真时看到参数前几十步剧烈弹跳先怀疑P初值再怀疑输入信号。还有一个更隐蔽的问题λ 恒定不变会导致参数收敛后的方差偏大恒定值意味着“永远用最近50步的数据”信号噪声没有被长时间平均压下去。于是有人用渐消记忆的变体让λ在启动阶段接近1稳定后逐步降低到目标值。这种变体实现简单把λ写成关于k的函数或按误差大小调度即可仿真时可以加进对比维度观察信噪比的影响。4.3 参数时变速度不同遗忘因子怎么选遗忘因子不是一个随便填的数字它应当和参数变化的时间尺度挂钩。参数每小时才缓慢漂移λ取0.99以上即可记忆窗口200步以上稳态波动小参数随负载切换在几十秒内就会改变λ就需要降到0.95左右。以下是仿真时常用的选择逻辑表参数变化特征遗忘因子λ记忆窗口≈1/(1-λ)注意事项参数定常噪声较大1 或 0.9991000以上估计最稳但跟踪突变能力差缓慢漂移幅度小0.990.995100200折中方案优先推荐偶发跳变间隔较长0.970.9930100能跟上跳变但稳态波动稍大快速时变噪声小0.950.971530跟踪快对噪声高度敏感在没有先验信息时通常先跑两个极端λ值1和0.95对比收敛后估计值的均方误差。如果两者相差不大说明参数其实不常变λ取0.99左右是最稳妥的。时变参数仿真里判定λ合不合适的标准不只是跟踪快不快还要看参数跳变恢复后的稳态误差能不能回到与λ1时同一量级。5. 辨识结果自检与可视化验证方法5.1 残差自相关检验判断模型是否可信参数估计仿真做完后不要看着曲线贴近真实值就收工。RLS输出的只是一组θ值这组值是否可信需要从残差序列上验证。残差定义为ε(k) y(k) - φT(k)θ̂如果模型结构正确且参数收敛残差应当近似为白噪声均值为0自相关函数在滞后非零处接近0。把残差算出来并画自相关图如果明显超出置信带且呈周期性说明模型没有完全捕获系统的动态特性比如漏了某个输入项、阶次偏低、或者存在未建模的时滞。% 残差计算与自相关检验 % theta_final 为收敛后的参数估计 phi_all [-y(3:end-1), -y(2:end-2), u(3:end-1), u(2:end-2)]; % 注意上面的写法仅为示意实际需保证维度一致 res y(3:end) - phi_all * theta_final; figure; subplot(2,1,1); stem(res(1:200), filled, MarkerSize, 3); title(残差序列前200点); xlabel(样本序号); ylabel(残差); subplot(2,1,2); [r, lags] xcorr(res, 20, coeff); stem(lags, r, filled, MarkerSize, 3); yline(1.96/sqrt(length(res)), r--); yline(-1.96/sqrt(length(res)), r--); title(残差自相关函数); xlabel(滞后); ylabel(自相关系数);注意这里红色虚线给出95%置信边界。若自相关在滞后1到几阶处明显越界并且残差序列看起来有波形而不是杂乱跳动先回去检查回归向量构造和阶次设置。噪声方差会影响残差的绝对值大小但不影响白噪声特性的判断即使噪声很大自相关图也应该在零附近波动。5.2 参数轨迹的稳态区间怎么读看参数估计曲线时不能只看最后落在哪个值还要看收敛后的稳态波动区间。稳态波动范围大约在真实值正负两倍标准差以内。仿真中可以通过折半分段的方式快速估算把收敛后的估计历史数据分成两段分别求均值和方差。两段均值之差如果超过3倍第一段标准差说明参数还在漂移或算法还没收敛此时画的最终估计值没有参考价值。另外可以同时画P矩阵对角线元素的变化曲线它对应用各个参数的估计方差如果对角线一直下降但没有稳定说明递推还没进入稳态。用这些标准去筛参数轨迹比肉眼判断“看起来挺稳”要可靠得多。最后再提一个不起眼但容易被忽略的点MATLAB里做数据生成和递推估计时尽量避免把大矩阵比如theta_hist反复拼接预先分配会快出一个量级代码也更接近实际能移植到嵌入式环境的形式。本文还有配套的精品资源点击获取