简介:CEEMD(完全集合经验模态分解)源代码压缩包,面向从事非线性、非平稳信号分析的工程与科研人员,用于解决传统EMD存在模式混合、虚假极值等问题。CEEMD作为EMD的改进版本,通过集合平均策略有效抑制模态混叠,提升分解结果的稳定性与可靠性。包内共5个文件,以m脚本为主(4个m,1个mat),涵盖核心算法函数、示例脚本及测试数据,完整呈现噪声添加、迭代sifting、集合平均等关键流程,便于直接运行与二次开发。压缩包仅12KB,小巧实用。已有982人学习下载,适合具备MATLAB基础、希望深入理解CEEMD原理并用于实际信号分解的读者。通过源码可掌握希尔伯特-黄变换的完整链路,并能调整参数适配振动、生物医学等复杂信号场景。无论是算法验证还是工程落地,都能从中获得清晰参考。
1. 你手里的这份 CEEMD 源代码,先想清楚它要替你解决什么问题
你拿到这份 CEEMD 源代码.zip,解压后大概率是一堆 .m 文件外加一两个 demo 脚本。先别急着跑,想清楚你下载它的动机:FFT 对付非线性非平稳信号会频谱泄漏,传统 EMD 又会在某些时段把同一个频率成分切进好几个模态,这就是模态混叠。CEEMD 就是在 EMD 基础上引入噪声辅助的集合分解方案,专治这个问题。振动故障诊断、脑电信号预处理、气象序列趋势提取这几个方向,是它最常被翻牌的场景。适合谁?手上有实测信号、想拆出有物理意义模态的从业者,不是只想要一张频谱图的人。后面按落地顺序讲:先分清源码是 CEEMD 还是 CEEMDAN,再跑通最小 demo,然后调参数、排坑,最后给验证手段。
2. 从 EMD 到 CEEMD:这份源码到底改了哪一步
我见过不少人把 CEEMD 当黑匣子,输入一段信号,输出一堆 IMF,然后直接拿第二个 IMF 当特征。这样用不是不行,但你连它内部改了哪一步都不知道,翻车了根本没地方查。这一章把 EMD 到 CEEMD 的改动链路捋一遍,你才知道参数该往哪个方向调。重点说三件事:EMD 的模态混叠到底怎么发生的,EEMD 用噪声解决了什么又留下了什么,以及你手里的源码究竟是哪一代实现。
2.1 EMD 的模态混叠问题:一个频率成分被拆成两半的现场
先回忆 EMD 的核心动作——sifting。每一次筛选里,算法找出信号的局部极大值和局部极小值,用三次样条分别拟合上包络和下包络,取均值后从原信号里减掉,反复迭代直到剩下的分量满足 IMF 的两个条件:极值点数量与过零点数量相等或至多差 1;上下包络均值趋近于 0。这个迭代过程本身不依赖任何先验频率,所以 EMD 才能处理非线性非平稳信号。
问题出在极值点上。假设信号是 10 Hz 加 50 Hz 两个正弦叠加,前 0.5 秒 50 Hz 分量存在,后 0.5 秒消失。前半个时段极值点密集,后半个时段稀疏,三次样条拟合出来的包络会在切换点附近剧烈起伏,导致 10 Hz 成分的一部分能量漏进 50 Hz 那个 IMF 里。更直观的现象是:你画第一个 IMF 的波形,发现里面有明显的低频包络调制,频率成分在相邻 IMF 之间来回搬家。模态混叠的本质,是局部极值分布被间歇性成分破坏,而不是算法算错了。
这个现象在实际数据里很常见。某次处理齿轮箱振动信号时(模拟项目X),转频 12 Hz 和啮合频率 240 Hz 之间本来隔得很开,但因为负载波动导致啮合频率只在部分时段出现,分解出来的第一个 IMF 里竟能看出 12 Hz 的包络起伏。这就是典型的间歇分量导致的模态混叠,也是 EEMD 和 CEEMD 这类噪声辅助方法要解决的元问题。
2.2 EEMD 补上的噪声,CEEMD 又改了什么
EEMD 的思路很直接:既然间歇性成分会破坏极值分布,那就往信号里加白噪声,让极值分布被高频噪声"打散",然后再多次独立分解、取平均。白噪声在不同的实现里产生不同的极值分布,信号本身的极值点每次都会被保留下来,平均之后噪声贡献互相抵消,信号的真实模态就凸显出来了。实验证明,集合平均次数越多,噪声残留越小,但代价是计算量线性上涨。
EEMD 有个天然缺陷:每次加的是独立噪声,分解结果里每个 IMF 都残留一部分噪声,把 IMF 全部加起来重构原信号时,重构误差并不小。于是后来的 CEEMD 做了两件事改进:其一,把辅助噪声改成正负成对加入,同一信号分别加正噪声和负噪声各分解一次再平均,残留噪声理论上被对称抵消;其二,也是更常见的实现——每分解出一个 IMF 后,在残差信号上重新加自适应噪声,逐级往下分解,而不是每阶都从原信号重新来。第二种做法就是 CEEMDAN。
项目标题写的是 CEEMD 源代码,但实际实现是哪一版,直接决定你的重构误差量级。如果是正负成对的互补噪声版,重构误差通常在 1e-2 量级;如果是自适应噪声版,重构误差能压到 1e-12 量级,几乎完全重构。这两种包我都见过,调用方式相似,但背后的数学假定完全不同,别混着看。
2.3 看源码前先分清:CEEMD 还是 CEEMDAN,两个名字经常被混用
你解压后第一件事是看主函数名。常见情况有三种:主函数叫 ceemdan.m 或 CEEMDAN.m 的,是自适应噪声版;主函数叫 ceemd.m 且内部有正负噪声对操作的,是互补噪声版;主函数直接叫 eemd.m 的,那大概率只是 EEMD 换了层皮。这一步判断比调任何参数都重要,因为三者对输出矩阵的约定都不一样。
差异主要体现在三处:输出维度、噪声参数含义、重构误差。互补版和 EEMD 的输出里,IMF 按列排放,最后一列是残差;自适应版有的把残差单独返回,有的并进 IMF 矩阵。噪声参数方面,互补版的 Nstd 是噪声相对信号标准差的固定比例,自适应版除了 Nstd 还要关注每级残差的标准差变化,同一套参数在两个版本里的实际效果可能差一倍。
用下面这个对照表可以快速定位手里这份源码是哪一代:
| 实现版本 | 主函数常见命名 | 加噪方式 | 重构误差 | 计算开销 | 适合场景 |
|---|---|---|---|---|---|
| EMD | emd.m | 无 | 接近完全重构 | 低 | 信号干净、无明显间歇分量 |
| EEMD | eemd.m | 独立加噪多次平均 | 较大(1e-1 量级) | 高 | 模态混叠不严重、能接受误差 |
| 互补噪声 CEEMD | ceemd.m | 正负成对加噪 | 较小(1e-2 量级) | 中 | 需要较好重构、算力有限 |
| CEEMDAN | ceemdan.m | 每级残差加自适应噪声 | 接近机器精度 | 较高 | 需要精确重构的工程场景 |
判断方法很简单:在 MATLAB 命令行敲 which ceemdan,如果能定位到文件,说明你的包里至少装了自适应版;再看主函数定义行,参数列表里有没有 Nstd、NR、MaxIter 之外的特殊输入。这一步做扎实,后面调参数才有的放矢。
3. 把 CEEMD 源码跑通:文件组织、最小 demo 与输出解读
这一章的目标是让你在自己的机器上跑出第一组可信的 IMF。我不会让你直接拿实测数据开跑,先用合成信号建立"正确结果长什么样"的参照系,再处理真实数据时你才知道哪些波形可疑。先认文件结构,再跑最小示例,最后学会读输出矩阵,三步走完,你手里就有了一套可复现的验证流程。
3.1 源码包里通常会有的四类文件,先对照职责认一遍
CEEMD 类实现无论哪个版本,文件结构都脱不开四类职责。第一类是主函数,命名里一定带 ceemd 字样,负责参数校验、逐级调用分解循环、汇总输出矩阵。第二类是 sift 内核,常见命名是 local_sift.m 或 sift.m,负责单次 EMD 的筛选迭代,也就是那层找极值、拟合包络、减均值的循环。第三类是极值检测,常见命名 extr.m,输入一段信号,输出极值点和对应的上下包络节点。第四类是插值工具,负责把离散极值点拟合成连续包络,绝大多数实现用的是三次样条。
调试建议是:不要把时间花在读主函数上,主函数通常是参数映射和循环控制,逻辑直白;真正决定分解质量的是 sift 内核里的停止条件和极值检测的正确性。如果你改了 Nstd 发现低频段被拆碎,问题大概率出在 sift 内核,而不是主函数。另外包里一般还会有一两个 example 脚本,建议保留它,每次跑你自己的数据之前,先用 example 跑了确认环境和源码没有被改动过。
3.2 最小可运行示例:用已知信号验证分解正确性
我一般会用一段合成信号做冒烟测试:两个正弦分量加白噪声,频率拉开到至少 5 倍,这样分解结果一目了然。下面这段代码是完整的可运行脚本,直接存成 ceemdan_demo.m 放在源码包外层运行。
% ceemdan_demo.m - CEEMD/CEEMDAN 最小验证脚本 fs = 500; % 采样率 500 Hz t = (0:1/fs:1-1/fs)'; % 1 秒时长 rng(7); % 固定随机种子,保证结果可复现 x = 2*sin(2*pi*10*t) + 1.5*sin(2*pi*50*t) + 0.3*randn(size(t)); % 三个核心参数:噪声幅值、集合次数、最大迭代数 Nstd = 0.2; % 噪声标准差相对信号标准差的比值 NR = 100; % 集合平均次数 MaxIter = 500; % 单个 IMF 的最大 sift 迭代次数 imfs = ceemdan(x, Nstd, NR, MaxIter); % 返回的 imfs 每列是一个 IMF size(imfs) % 查看输出维度,确认行列方向这段代码的逻辑说清楚:先构造一个频率成分已知的信号,10 Hz 和 50 Hz 幅度各 2 和 1.5,信噪比大约 20 dB,足够模拟工程数据里的噪声水平。rng(7) 这一步很多人省略,但 CEEMD 内部用 randn 生成噪声序列,不固定种子,两次分解结果会有随机差异,调试时你会分不清差异是参数引起的还是随机性引起的。第 7 行注释写着返回的 imfs 每列是一个 IMF,但请以 size(imfs) 的实际输出为准——有的版本返回的是每行一个 IMF,转置一下就是列方向,这一步错了后面画图全乱。
跑完后的预期是:size 输出为 500×5 或 500×4 之类,通常包含 2 到 3 个真实模态、若干低幅值伪模态和最后一列残差趋势项。如果输出只有一列,说明主函数被改成单次 EMD 了,检查函数名;如果列数超过 10,大概率是停止准则失效,走火入魔式地过分解,第 5 章会专门讲。
3.3 输出矩阵怎么读:IMF 顺序、残差行与重构误差
拿到 imfs 矩阵之后,第一件事是画图,不是算特征。画图时按列逐条画,注意观察每列的频率是否从高到低排列,这是 EMD 家族输出默认的排序约定。第一条 IMF 频率最高,越往后越低,最后一列是最低频的残差趋势。如果发现第 2 列和第 3 列频率接近,说明有模态混叠残留或者过分解,先别急着用特征提取。
画完图之后,必须做一次重构检查。CEEMDAN 的卖点就是重构误差接近机器精度,如果你的源码包重构误差在 1e-2 以上,那它要么是 EEMD,要么是互补噪声版,要么参数没配对。
% 重构误差检查:把全部 IMF 加回来看和原始信号差多少 rec = sum(imfs, 2); % 按列求和,得到重构信号 err = rec - x; rmse_val = sqrt(mean(err.^2)); fprintf('重构 RMS 误差 = %.3e\n', rmse_val); % 画 IMF 波形,方便肉眼检查混叠和端部发散 figure; for k = 1:size(imfs, 2) subplot(size(imfs, 2), 1, k); plot(t, imfs(:, k)); ylabel(['IMF', num2str(k)]); xlim([0 1]); end xlabel('时间 / s');这段代码里 sum(imfs, 2) 是把每行加起来,前提是 imfs 的行方向是时间轴。如果你的包返回的是列方向结果,把 sum 的维度参数换掉。重构误差这个指标有两层判断:RMSE 在 1e-12 量级说明是自适应噪声版且工作正常;在 1e-2 到 1e-1 说明噪声残留明显,你要么换实现,要么接受这个误差后把每个 IMF 再做一次局部去噪。有人把重构误差大的锅甩给"信号本身噪声大",这是误会——CEEMDAN 加的是辅助噪声,不是信号噪声,重构误差大只说明算法实现或者参数配置有问题。
画图时必须看两端。如果第一列或最后一列在首尾处明显翘起,那就是端点效应,后面 5.3 处理。如果中间某列波形出现"拍频"样式的周期起伏,多半是模态混叠残留在相邻两个 IMF 之间,6.2 会给判断方法。
4. 三个必调参数:Nstd、NR、MaxIter,以及它们怎么联动
CEEMD 类算法要调的参数其实不多,主函数里通常就三个:Nstd、NR、MaxIter。参数少不意味着随便设,这三个参数互相联动,乱调一个,另外两个的效果全变。下面按参数逐个讲清楚物理含义、设置区间和判断标准,最后落到它们怎么配合。
4.1 噪声幅值 Nstd:加多了压掉弱分量,加少了等于白加
Nstd 的全名是 noise standard deviation,指的是辅助白噪声的标准差相对原始信号标准差的比值,不是绝对幅度。这个相对定义很重要:同一个 Nstd,对高幅值信号和低幅值信号施加的绝对噪声幅度是不同的。所以跨数据集比较参数没有意义,只需要记住 0.1 到 0.2 是绝大多数工程案例的安全区间。
逻辑是这样的:辅助噪声的幅度太小,不足以改变极值点的分布。如果信号里有一个缓慢变化的弱分量,它的极值稀疏,加进去的噪声幅度低于它的局部起伏,极值分布还是老样子,模态混叠照旧发生。反过来,Nstd 太高,比如超过 0.4,噪声本身会制造出大量假的极值点,分解结果里出现一堆没有物理意义的细碎 IMF,低频弱分量可能直接被淹没。主观上你会看到 IMF 数量变多、低频段被切碎。
习惯做法是先 0.2 起步看输出。如果第一个 IMF 里还能看到低频包络,说明混叠没压住,往上加到 0.25;如果低频段出现碎片,降回 0.15。值得做的实验是:固定 NR 和 MaxIter,把 Nstd 从 0.1 扫到 0.4,记录每个取值下的 IMF 数量和重构误差,画成两条曲线,你会看到它们在一个区间内稳定、在区间外突变,那个稳定区间就是你这个信号的有效工作区。这一步成本不高,值得在真实数据上跑一次。
4.2 集合次数 NR:稳定性和算力的博弈
NR 是 ensemble realization 的数量,也就是为了平均效果,算法要重复分解多少次。EEMD 时代 NR 动辄要几百上千次,因为每次独立加噪,噪声抵消只能靠大数定律。CEEMDAN 因为每级在残差上自适应加噪,收敛速度比 EEMD 快得多,NR 取 100 到 200 通常就能获得稳定结果。如果你跑的是互补噪声版 CEEMD,NR 要适当高一些,建议 200 到 500。
怎么判断 NR 够不够?固定其他参数,换不同的随机种子跑两次,比较前三个 IMF 的波形差异。如果两次结果的 IMF 1 波形几乎重合,NR 够了;如果每次跑出来波形都在变,说明平均不充分,加 NR,或者把 Nstd 调大一点让噪声充分起作用。另一个工程细节是,CEEMDAN 的收敛还取决于每级残差的变化速率,如果信号本身信噪比很低(比如低于 10 dB),NR 要翻倍,否则低频 IMF 的稳定性会很差。
算力方面有一个血泪经验:别盲目把 NR 拉到 1000。曾用某段 10 万点的信号,NR 从 100 加到 300,IMF 波形几乎没变化,运行时间却从 3 分钟涨到 11 分钟。NR 的收益是边际递减的,先 100 起步,用"换种子对比波形"这个手段做判断,比拍脑袋拉高数字有效得多。
4.3 MaxIter 与内层停止准则:过迭代会让窄带信号失真
MaxIter 是单次 sift 迭代的最大次数,限制的是"在一个 IMF 内部循环筛选"这个动作的天花板。sift 的标准做法是反复减包络均值直到满足 IMF 条件,但实际信号里这个收敛过程可能很慢甚至震荡,MaxIter 就是强制截止阀。
如果 MaxIter 设得太小,比如 50,IMF 可能还没收敛就强制输出,包络均值不为零,模态不纯,表现为 IMF 波形里叠着一层高频毛刺。如果设得太大,比如 2000 以上,sift 会不断把信号里的振幅调制也当成需要消除的包络波动,结果把一个本来完好的窄带信号硬掰成两个伪 IMF。这种现象叫过迭代,与高阶滤波器被调到临界点附近是一个性质,结果看起来"分解得很细",但没有物理意义。
除了 MaxIter 这个显式上限,多数实现内部还有一个隐式停止条件:比较相邻两次 sift 结果的标准差之比,低于某个阈值就认为收敛。这个阈值在源码里通常是硬编码的,不同版本取值差异很大,有的用 0.2,有的用 0.001。如果你想对这个做调整,去 sift 内核文件里搜标准差的比值判断那行,通常在 local_sift.m 的下半部分。建议先用默认 MaxIter 跑,如果发现某阶 IMF 的迭代次数恒定等于 MaxIter(有的实现会在控制台打印 sift 次数),说明它在撞上限,需要加大 MaxIter;如果高阶 IMF 出现明显分裂,说明停止条件太松或 MaxIter 过大,两者取其一调。
5. 跑 CEEMD 源码最常见的五个坑与排查思路
这一章是全文里最值得先读的部分。以下五条都是真实数据上反复遇到过的现象,每一条按现象、原因、解决三段展开,你可以直接照着定位自己的问题,不用从头读源码。前两条对应输入数据的问题,第三条是 EMD 家族的通病,第四条是参数过冲,最后一条是性能瓶颈。
5.1 现象:分解结果出现 NaN 或 Inf,一画图全是空白
现象:运行不报错,但 imfs 矩阵里某些位置是 NaN 或 Inf,画图对应位置断成空白,重构误差直接爆表。
原因:这类实现里 NaN 几乎都是输入数据的问题。信号某一段是 NaN、Inf,或者数据有异常大的突跳(比如传感器断线瞬间的毛刺),通过样条插值会把异常值向外传播,导致包络计算发散。另一个隐蔽原因是信号里有连续重复的等值点(比如一段平坦的平台),局部极值检测在平台上找不到合理的极值,三次样条解线性方程组时出现奇异。
解决:喂给主函数之前做数据体检。先用 isnan 和 isinf 把非法值找出来,毛刺用中值滤波或简单阈值剔除,平坦平台加一个非常小的随机扰动(幅度是信号标准差的 0.1%,不影响分解却能让极值点重新出现)。处理完重新跑,绝大多数 NaN 都会消失。如果还有,用排除法:把信号后半段截掉四分之一再跑,如果 NaN 消失,问题定位在被截掉的那一段数据上。
5.2 现象:同一段信号两次分解,IMF 数量和形态对不上
现象:不换任何参数,只是换了一次随机种子或者重启 MATLAB,分解出来的 IMF 数量不同,前几列波形有肉眼可见差异。
原因:集合类算法本质上依赖随机数,如果你不固定随机种子,两次分解有差异是正常的。但如果差异大到 IMF 数量都变了,说明你的参数组合处于临界区——极值分布刚好在被噪声改变和不被改变之间,一点随机扰动就造成完全不同的分解路径。
解决:第一步固定随机种子,用 rng(固定值) 包住调用,保证同参数下结果一致,这是可复现调参的前提。第二步如果固定种子后换种子的两次结果依然差很多,把 Nstd 调大 0.05 再试,让噪声的作用彻底压过临界区的随机性。第三步如果还是不稳定,且你的信号确实很长,降低 NR 反而可能更稳——NR 太高会让平均过程把噪声贡献压得过低,重回临界区。把 Nstd 和 NR 看作一对协同参数,Nstd 稍高时 NR 可以适当降低。
5.3 现象:IMF 两端发散得厉害,中间波形正常
现象:所有 IMF 中间段都漂亮,唯独首尾两端翘起或剧烈震荡,端点效应从第一个 IMF 一路传到最后一个。
原因:三次样条拟合法需要极值点来锚定包络,信号端点附近通常不是极值点,样条在这里没有约束,只能外推,外推结果与真实趋势偏离后,sifting 会把这种偏离当成包络均值减掉,误差逐次累积,表现为两端发散。这不是 CEEMD 的 bug,EMD 家族都有这个毛病。
解决:最常见的做法是镜像延拓,把信号末尾一段翻转后接到开头、开头一段翻转后接到结尾,让包络有足够的极值点锚定,分解完再裁掉延拓部分。在 MATLAB 里先用 flipud 构造延拓信号,延拓长度取信号长度的 5% 到 10%,跑完分解后按原长度截取 IMF。有的源码包内部已经做了延拓,你只需要对比"带延拓跑"和"直接跑"两种输出的两端差异来确认。若包没内置延拓,优先在外部实现,不要为了省事改源码。
5.4 现象:低频段被拆成一堆碎片,趋势项消失
现象:IMF 数量异常多,低频部分不是一条干净的缓变曲线,而是一串波动不均匀的小段,残差趋势项几乎看不到。
原因:Nstd 设得过高,或者信号本身信噪比过低,噪声在低频段制造了伪极值,sift 沿着这些伪极值一路切分,把本来连续的缓变分量切碎。另一个推手是 MaxIter 过大,给了过迭代充分的空间去"雕琢"伪模态。
解决:把 Nstd 降回 0.15 以下,同时把 MaxIter 降回 500 附近,重新跑。如果低频依然碎,检查停止条件阈值是不是被改小了。还有一种情况要排除:信号本身存在真实的间歇性低频事件(比如负载突变的瞬间),这种"碎片"来自物理信号而不是算法故障,判断依据是——把信号切掉突变段重新分解,若低频立即变干净,则碎片来自信号本身,应保留物理解释,而不是强行调参抹掉。
5.5 现象:跑一遍要几十分钟,NR 设得并不大
现象:数据量不大(几千点),NR 也就 100,但运行时间远超预期,风扇狂转。
原因:CEEMDAN 的时间瓶颈不一定在 NR,而在每个 IMF 内部的 sift 迭代次数。如果 MaxIter 设得很大,或者信号里存在难以收敛的模态(比如间歇性强、端点效应严重),单个 IMF 的 sift 循环会跑满上限,总耗时等于 IMF 数量乘 NR 乘 sift 迭代次数,放大效应显著。
解决:先看耗时分布,给主函数的分解循环里临时加一行 tic/toc 打印每阶 IMF 的耗时,找到最慢的那一阶,看它的 sift 迭代次数是不是撞到 MaxIter 上限。如果是,先改善端点效应、再把 MaxIter 从 1000 降到 500,耗时通常能砍掉一半以上;如果你的 MATLAB 有并行工具箱,把 NR 循环用 parfor 重写,集合次数本身就是天然并行任务,这是最直接的提速手段。没有工具箱就只能降 NR 或缩短信号长度,不要硬等。
6. 验证 CEEMD 分解质量的三个手段与一个习惯
6.1 重构误差与正交性指数:给分解打分的两个硬指标
重构误差是最直接的验收线:1e-12 量级说明实现是 CEEMDAN 且参数健康,1e-2 量级要警惕是不是 EEMD 换了皮,超过 1e-1 直接判不合格,按 5.1 和 5.4 的方向排查。正交性指数衡量 IMF 两两之间的混叠程度,理想情况下 IMF 两两正交,指数应远小于 1。工程上低于 0.1 算健康,高于 0.3 说明模态混叠明显,计算代码很短:
% 正交性指数:两两 IMF 点积绝对值之和 / 信号能量 io = 0; for i = 1:size(imfs, 2) for j = i+1:size(imfs, 2) io = io + abs(sum(imfs(:, i) .* imfs(:, j))); end end fprintf('正交性指数 = %.3f\n', io / sum(x .^ 2));这个数字只告诉你有没有问题,不告诉你在哪一阶。
6.2 Hilbert 谱目检:模态混叠在哪一阶,一眼定位
定位靠 Hilbert 谱。对每个 IMF 做 Hilbert 变换得瞬时频率,画成时间-瞬时频率的分布图,健康的分解是几条平行于时间轴的亮带。某条带突然分叉或两条带之间出现渐变过渡,就是混叠残留点,直接对应到那阶 IMF 去调参数。没有信号处理工具箱可以用 FFT 手写:
function z = my_hilbert(x) n = numel(x); X = fft(x); h = zeros(n, 1); h(1) = 1; h(2:floor(n/2)) = 2; % 正频率放大 2 倍,负频率置零 z = ifft(X .* h); end对 IMF 求相位差分就是瞬时频率,画谱的细节可参照你常用的时频图绘制习惯。
6.3 固定随机种子再交付:一个让结果可复现的工程习惯
最后说个踩过坑后养成的习惯:CEEMD 代码里第一行就固定随机种子,写在数据加载之前,因为文件读取和预处理环节也可能引入随机性,种子固定得越早,整条链路越可复现。交付结果时,种子值、Nstd、NR、MaxIter 四个数写进结果说明,别人复现不出来,先检查这四个数对不对。保存大矩阵用 -v7.3 格式,批量跑数据时先把每个样本的 IMF 数和重构误差汇总成表再筛选,别逐个画图。这些习惯不改变算法本身,但能把你的 CEEMD 结果从"跑出来了"升级成"随时可复现、可审计"。希望帮到你。
本文还有配套的精品资源,点击获取