ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

系统辨识与建模实战:从M序列设计到参数反演全链路拆解

系统辨识与建模实战:从M序列设计到参数反演全链路拆解

简介:这份系统辨识教案面向自动化专业学生与相关课程学习者,围绕从输入输出数据中建立系统模型这一核心问题,梳理辨识理论、实验设计与编程计算的学习路径。压缩包共1个文件,为doc格式文档,大小约1.42MB,内容以课时讲义形式组织,涵盖参考书目、学习要求、考核办法与概论章节。文档从实体与模型的区分讲起,介绍直觉模型、物理模型与数学模型等分类,并展开Zadeh对系统辨识的定义及数据、模型类、准则三要素,随后结合长网造纸过程的质量控制案例,完整演示明确辨识目的、收集先验知识、设计试验、数据采集与预处理、结构辨识与参数估计、模型检验与转换等一般步骤。已有150人学习,适合希望减少课堂依赖、通过自学掌握辨识方法并独立完成数据分析报告的读者参考。

1. 拿到一份 40 学时的系统辨识教案,先别急着翻公式

如果你手上正躺着一份《系统辨识与建模》的教案,40 学时、五本参考书、考核方式是“给一个数据文件,编程辨识,写报告”,那这份资源的价值不在“读完”,而在“照着它把一条辨识链路跑通”。我带过几届自动化方向的课程设计,最深的体会是:系统辨识这门课,教材讲得再全,学生卡住的地方永远是那几个——M 序列怎么设步宽、采样间隔和扰动周期怎么配、数据预处理做完参数怎么反演回去。这份教案把 Zadeh 的三要素(数据、模型类、准则)、辨识十一大步、M 序列设计公式、标准化反演公式都写进去了,属于少见的“理论够用、步骤能抄”的讲义型资料。它适合两类人:一是要独立完成一次辨识实验并交报告的学生,二是需要快速把辨识流程落到代码里的初级工程师。下面我按“先立理论骨架、再拆实验设计、最后抠预处理和避坑”的顺序,把它拆成能复现的东西。

2. 三要素与十一大步:把辨识流程拆成可执行清单

2.1 为什么先锁死“目的—模型类—准则”这三件事

教案开篇就引 Zadeh 1962 年的定义:辨识是在输入输出数据基础上,从一组给定模型类中确定一个与所观测系统等价的模型。这句话的实操含义是,数据、模型类、准则三者必须同时固定,否则不同方法之间根本没有可比性。我见过太多报告,前面用差分方程拟合,后面又拿传递函数去比误差,结论自然站不住。

选型上有个直接对应关系:目的是验证理论模型,就要求零极点、结构、时延都准,模型类必须和理论模型同构;目的是设计数字控制器,动态响应和时延要准,模型类要便于计算机运算,差分方程比连续传递函数更顺手;目的是监视过程参数做故障诊断,那参数准确比动态特性重要,模型类要能直观体现被监视量。教案里造纸过程的例子把这点讲透了——控制定量和水份,先调查出车速同步困难要恒定、流量到定量约 60 秒延迟而响应只有 2 秒、浓度到定量约 120 秒延迟响应约 80 秒、蒸汽压力到水份约 45 秒延迟响应约 60 秒。这些先验知识直接决定了后面哪些输入加扰动、采样频率取多少。

准则这块,教案给了三种误差定义,我建议新手先吃透方程误差和输出误差的区别:

误差类型准则形式对参数是否线性预测能力适用模型
参数误差J=∑/n是仅算法研究理论验证
方程误差J=∑e(k)²/N,e(k)=y(k)+ay(k-1)-bu(k-1)-cu(k-2)线性只能一步预测AY=B1U1+B2U2
输出误差J=∑e(k)²/N,e(k)=y(k)-ŷ(k)非线性输入已知可多步预测B/A 结构

方程误差是参数的线性函数,最小二乘能直接解,但只能做一步预测;输出误差是参数的非线性函数,得迭代,但能做多步预测。教案还提醒了一个容易被忽略的点:模型阶次越高 J 值越小,会导致过估计,所以不能拿 J 值单独比模型好坏;采样间隔增大一倍,模型阶次大致减半,跨采样步长比较时误差公式要改成 J=∑e(k)ᵀWe(k)·T0²/N。这条在写报告做模型对比时是硬约束。

2.2 十一大步里真正会返工的是哪几步

教案把流程画成:明确目的→收集先验知识→设计辨识试验→现场准备→数据采集→数据预处理→选择模型类→结构辨识与参数估计→模型检验→模型转换→应用评价,检验和应用评价不通过要回退。实际做下来,返工最频繁的是第 3 步试验设计和第 6 步预处理,因为这两步的错误在参数估计阶段才暴露,而那时你已经以为快结束了。

设计辨识试验的核心原则教案写得很直白:在安全前提下尽可能激励系统、保持输入输出关系、适当解耦。落到操作上就是先划边界——从边界外连进来的其它信号尽量保持稳定并当作噪声;再定哪些输入叠加扰动、哪些保持稳定;再看过渡过程时间常数是否有明显差异、噪信比多大、噪声是白色还是有色。造纸例子里保持车速和纸浆浓度不变,对流量和蒸汽压力分别施加伪随机序列扰动,幅度以不引起断纸为限,采样频率设为 2,试验 1000 秒,采集定量、水份、纸浆流量和蒸汽压力四路信号。这套参数不是拍脑袋,是前面先验知识推出来的。

现场准备那步教案列了五件事:申请试验时段、准备扰动信号发生器并预发检验、测验现场干扰必要时设计模拟滤波器、准备模数转换设备调好零迁和放大、接线。这几件事在课程设计里常被简化成“直接采数”,但零迁和放大没调好,采回来的数据要么削顶要么分辨率不够,后面预处理再努力也救不回来。

3. M 序列与采样设计:扰动信号参数怎么算才不翻车

3.1 M 序列的周期、游程和自相关性质

教案花了不小篇幅讲 M 序列,因为它是辨识实验里最常用的扰动信号。n 阶 M 序列周期 N=2ⁿ-1,是一个周期内移位寄存器能表示的最多状态数;一个周期里 1 的个数比 0 多 1;游程长度从 1 到 n,长度为 1 的游程有 2ⁿ⁻² 个,长度每加一数量减半,长度为 n 的游程只有 1 个。把 0 换成 -1 后,自相关函数在 τ=iN 时为 1,在 τ=iN+k(k=1…N-1)时为 -1/N。N 充分大时这个 -1/N 趋近 0,近似 δ 函数,所以以 M 序列为输入的线性系统,互相关函数序列就等于脉冲响应序列——这是用相关分析法辨识的数学基础。

多输入单输出系统有个实用技巧:同一 M 序列的不同移位序列(M(k)、M(k+J)、M(k+2J))分别作为各输入扰动,只要输出对各输入的过渡过程小于 J,就可认为输入之间正交。这解决了多路扰动互相污染的问题,但前提是 J 选得够大,J 太小正交性就破了,这是后面避坑章要展开的点。

逆重复 M 序列是 M 序列乘方波得到的,周期 2N,一个周期里 1 和 -1 个数相等,自相关在 τ=i·2N 时为 1、τ=i·2N+1 时为 -1、其余为 0。它保留了白噪声的优点而幅值可控,直流分量问题比普通 M 序列更干净。

3.2 步宽 Ts 和级数 n 的两套算法

教案给了两套 M 序列设计方法,我建议新手用第一套,逻辑链清楚:

# M 序列参数设计:第一套算法 # 输入:系统过渡过程时间 T(秒),系数 k(fmax = k/T,常取 3~15) T = 60.0 # 系统过渡过程时间,由阶跃预实验估计 k = 5 # 最高工作频率系数,fmax = k/T fmax = k / T # 系统最高工作频率 # 步骤1:由 1/Ts > 3*fmax 得 Ts 上限 Ts_max = 1.0 / (3 * fmax) Ts = Ts_max * 0.8 # 留余量,实际取略小于上限 # 步骤2:由 1.5*T < (2^n - 1)*Ts 反解 n import math n = math.ceil(math.log2(1.5 * T / Ts + 1)) N = 2**n - 1 print(f"Ts={Ts:.3f}s, n={n}, N={N}, 周期长度={N*Ts:.1f}s")

这段代码的逻辑是:先由过渡过程时间 T 估出最高工作频率 fmax=(3~15)/T,再由 1/Ts>3·fmax 定出步宽上限,最后用 1.5·T<(2ⁿ-1)·Ts 保证一个周期覆盖至少 1.5 倍过渡过程,反解出最小阶次 n。参数说明:k 取 3 偏保守、取 15 偏激进,课程设计里取 5 左右比较稳;Ts 乘 0.8 是给实际采样留余量,因为现场信号发生器的时间精度未必理想。第二套算法是反过来先定 n 再算 Ts=(0.1~0.8)T/n,适合已经知道要用几阶移位寄存器的场合。多输入时还要加一条约束:(2ⁿ-1-1)·Ts>1.5·∑(输出对各输入的过渡过程时间),否则移位序列之间的正交性不成立。

采样间隔单独设计:满足香农定理 1/T0>2·fmax;有扰动信号时 T0<Ts,且 Ts 必须是 T0 的整数倍。实验时间取 3~5 个扰动信号周期,预实验 1~2 个周期。这几条是硬约束,T0 和 Ts 不整除,后面重抽样和对齐就会出小数索引,血泪经验。

3.3 白噪声、有色噪声和成形滤波器

教案指出白噪声谱密度为常数、频谱宽度无限、不同时刻互不相关,用途包括激发系统所有模态、防止数据病态、以输出估计误差是否具有白色性判断辨识方法优劣。物理上白噪声不存在,常见的是有色噪声,而有色噪声表示定理说:任何谱密度为实函数的平稳噪声,都可由白噪声经过一个渐近稳定的线性环节(成形滤波器)得到。这条定理的实操意义是,如果你的残差不是白的,说明模型没把噪声的成形环节吸收进去,要么加阶次要么换模型结构,而不是简单说“噪声太大”。

4. 数据预处理:标准化、滤波、重抽样和参数反演

4.1 标准化为什么必须做,反演公式怎么推

教案把预处理拆成四件事:传感器非线性校正、滤波、重抽样、标准化。前三件偏工程,标准化是数学上最容易做错又最影响结果的。目的写得很清楚:降低舍入误差、防止病态方程、提高计算精度。方法是对输入输出各自零均值、单位方差化,辨识完再把参数反演回原尺度。

以二阶差分方程为例,原始模型是 y(k)+a·y(k-1)=b·u(k-1)+c·u(k-2)+d。先减均值消掉常数项 d,得到 Y(k)+a·Y(k-1)=b·U(k-1)+c·U(k-2);再除以标准差,得到 Yσ(k)+a·Yσ(k-1)=B·Uσ(k-1)+C·Uσ(k-2),其中 B=b·σu/σy、C=c·σu/σy。辨识得到 B、C 后反演:b=B·σy/σu,c=C·σy/σu。a 不变,因为它作用在同尺度的 Y 上。

import numpy as np def normalize_io(u, y): """输入输出零均值单位方差化,返回标准化数据与反演系数""" u_mean, y_mean = u.mean(), y.mean() U = u - u_mean Y = y - y_mean sigma_u, sigma_y = U.std(), Y.std() U_sigma = U / sigma_u Y_sigma = Y / sigma_y return U_sigma, Y_sigma, sigma_u, sigma_y, u_mean, y_mean def denormalize_params(B, C, sigma_u, sigma_y): """把标准化域辨识出的 B、C 反演回原尺度 b、c""" b = B * sigma_y / sigma_u c = C * sigma_y / sigma_u return b, c

逻辑说明:先减均值是为了消掉模型里的常数项 d,否则 d 会和参数耦合导致有偏;再除标准差是为了让方程系数落在同一量级,避免最小二乘的法方程条件数爆炸。参数说明:σu、σy 用样本标准差(ddof=0 还是 1 影响不大,但全流程要统一);反演时 b、c 都乘 σy/σu,因为输入被缩小了 σu 倍、输出被缩小了 σy 倍,系数要补回这个比例。注意 a 不需要反演,它对应的是 Y(k) 和 Y(k-1),同尺度相消。

4.2 滤波、重抽样和非线性校正的先后顺序

教案说滤波时对输入输出加相同的滤波器,输入输出关系不变——这句话的前提是同一个滤波器、同样的相位响应,否则输入输出之间的时移对不上,辨识出的时延就是错的。重抽样针对过渡过程较长的子系统,重新选采样间隔以降低模型阶次,配合前面“采样间隔翻倍、阶次减半”的结论用。传感器非线性校正要按厂家给的静态非线性曲线编程序校正,这一步在课程设计里常被跳过,但如果你的传感器在量程两端明显非线性,不校正的话辨识出的模型会把非线性折进参数里,换个工作点就失效。

顺序上我一般按:非线性校正→滤波→重抽样→标准化。理由是非线性校正是逐点映射,必须先做;滤波和重抽样都改变数据长度或频带,放在标准化之前,保证标准化统计量是基于最终数据算的。

5. 避坑与排查:五个让辨识报告返工的具体问题

5.1 现象:辨识出的时延总是差一两个采样点

原因:输入输出加了不同滤波器,或者滤波器的群延迟没对齐,导致互相关峰值偏移。教案明确要求输入输出加相同滤波器,但实操里常有人给输出加低通、给输入不加,理由是“输入干净”。

解决:输入输出走同一个滤波器对象、同一组系数;如果必须分别处理,先算滤波器的群延迟并在数据上做补偿,再用互相关找时延。

5.2 现象:最小二乘解出的参数发散或大得离谱

原因:没做标准化,输入输出量级差几个数量级,法方程条件数过大;或者模型里保留了常数项 d 又做了零均值化,造成共线。

解决:先零均值单位方差化再辨识,常数项单独估计或直接消掉;检查数据里有没有削顶、跳变、缺失,异常点对最小二乘的杠杆效应极大。

5.3 现象:多输入实验里各路扰动互相干扰,辨识结果对不上单输入实验

原因:移位序列的移位量 J 取得太小,不满足“输出对各输入的过渡过程小于 J”,正交性假设破了。

解决:按 (2ⁿ-1-1)·Ts>1.5·∑(各输入过渡过程时间) 重新核算 n 和 Ts;J 至少取最大过渡过程对应的采样点数,宁大勿小。

5.4 现象:模型检验残差不是白的,但加大阶次后 J 值还在降

原因:把“J 值下降”当成“模型变好”,忽略了教案说的阶次越高 J 越小会导致过估计;残差非白可能是噪声成形环节没建模,不是阶次不够。

解决:用残差白性检验(自相关是否落在置信带内)而不是只看 J 值;跨采样步长比较时用 J·T0²/N 归一化;必要时给噪声加成形滤波器结构。

5.5 现象:报告里模型转换后应用效果和辨识阶段对不上

原因:参考模型转应用模型时,离散化方法或采样率变了,但参数没跟着重算;或者标准化反演漏了某一路系数。

解决:模型转换后重新在验证数据上跑一遍预测,对比转换前后的输出误差;反演公式逐项核对,b、c 乘 σy/σu,a 不动,常数项按 (1+a)·ȳ-(b+c)·ū 回填。

6. 用一份数据文件把整条链路验一遍:我的收尾习惯

教案的考核方式是给一个数据文件、编程辨识、写报告,这其实是最好的自检方式。我一般会拿一份已知结构的仿真数据先跑通全链路,再换真实数据。具体做法是:用二阶差分方程加有色噪声生成 2000 点数据,按第 3 章算 M 序列参数、按第 4 章做预处理、用最小二乘估参数、反演回原尺度,最后对比真值。

import numpy as np # 生成已知结构的仿真数据:y(k)+a*y(k-1)=b*u(k-1)+c*u(k-2)+e(k) np.random.seed(0) N = 2000 a_true, b_true, c_true = -0.7, 0.5, 0.3 u = np.random.randn(N) e = np.random.randn(N) * 0.05 y = np.zeros(N) for k in range(2, N): y[k] = -a_true*y[k-1] + b_true*u[k-1] + c_true*u[k-2] + e[k] # 构造回归矩阵并最小二乘 Phi = np.column_stack([-y[1:-1], u[1:-1], u[:-2]]) Y = y[2:] theta, *_ = np.linalg.lstsq(Phi, Y, rcond=None) print("估计参数:", theta, "真值:", [a_true, b_true, c_true]) # 残差白性粗检:滞后1~5阶自相关应落在 ±2/sqrt(N) 内 res = Y - Phi @ theta for lag in range(1, 6): r = np.corrcoef(res[:-lag], res[lag:])[0, 1] print(f"lag{lag} 自相关={r:.3f}, 阈值={2/np.sqrt(len(res)):.3f}")

这段代码的价值不在估参数本身,而在给你一个“真值已知”的对照系:参数估偏了能立刻定位是预处理、回归矩阵构造还是噪声水平的问题;残差自相关逐阶打印,超过 2/√N 就说明还有结构没吸收。参数说明:噪声标准差 0.05 是故意设小,先验证算法正确性,再逐步加大到噪信比接近真实工况;回归矩阵第一列取 -y[k-1] 是为了让 θ 直接对应 a 的正负号,和教案公式一致。

从那以后我每次交辨识报告前,都强制先用仿真数据把“参数估计—反演—残差检验”走一遍,确认链路无误再碰实测数据,这个习惯帮我省掉了至少三次整篇返工。希望这份拆解能帮到你,把教案里的公式真正变成能跑出结果的代码。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进