
简介CEEMDAN是EMD与EEMD基础上的进一步改进算法通过引入与信号相位相关的自适应噪声可有效抑制模态混叠提升非线性、非平稳信号分解的准确性与稳定性面向信号处理研究者与机械故障诊断、生物医学、金融分析等领域的工程技术人员。压缩包共5个文件包含4个MATLAB脚本和1个MAT数据文件脚本覆盖CEEMDAN、EEMD、EMD三种方法的完整实现MAT文件提供心电信号等实测数据便于直接运行示例运行时可直接观察各阶IMF的波形与频率成分有助于理解不同分解策略的差异。脚本中已集成从加载数据、执行分解到输出IMF的完整流程读者可快速复现结果并对比三种算法在频谱分离效果和收敛速度上的差异。已有5933人学习下载压缩包整体仅32KB结构紧凑、核心代码集中适合需要快速上手并验证改进算法效果的研究者。1. CEEMDAN算法不是EMD系列的玄学改进把模态混叠压到可控的那一步搞信号处理、机械故障诊断的同行对CEEMDAN算法应该不陌生。它是EMD、EEMD之后的第三代改进把“加白噪声取平均”思路做成了自适应版本结果就是各阶IMF既正交又完备重构误差可以压到机器精度级别。相比EEMDCEEMDAN的集总次数通常能少一半以上模态混叠也压得更干净。这篇笔记适合两类人一类是刚接触EEMD但觉得拆得不干净、想换CEEMDAN入门的初学者另一类是已经在用CEEMDAN但被参数调优、结果复现、IMF筛选搞得头疼的从业者。下面直接从原理差异讲起把参数、案例和坑一次说清。2. 从EMD到CEEMDAN三次改进分别补上了哪个短板2.1 EMD的筛分过程与两种典型失效场景EMD经验模态分解做的事情一句话说清把一维信号按时间尺度从高频到低频逐层剥离每层得到一个本征模态函数IMF。筛分的经典循环是先找信号全部局部极大值点和极小值点用三次样条分别拟合出上包络和下包络取两条包络的中值作为均值曲线再用原信号减去均值重复这个过程直到当前序列满足两个条件——零点和极值点个数相等或至多差一个、上下包络关于时间轴局部对称。此时得到一个IMF然后从原信号中扣掉它对剩余残差继续重复直到残差单调或能量低于设定阈值。工程实测信号里用EMD会碰到两个绕不开的问题。第一个是模态混叠信号中如果存在一个幅值小但频率高的间歇成分或者有一个噪声尖峰筛分时极值点位置会被扰动导致不同频率的成分被收进同一个IMF里。表现出来就是某阶IMF里同时含两段频率相差很大的振荡下游做时频分析、特征提取都会走样。第二个是端点效应信号首尾不一定刚好有极值点三次样条在端点附近会大幅摆动导致两端几十个采样点的IMF明显失真而且这个失真还会向内部传播。从选型角度看并非所有场景都需要换算法。数据干净、成分单一、采样稳定的仿真信号直接用EMD没问题但持续采集的振动信号、含有间歇冲击的声音信号几乎必然触发模态混叠和端点漂移。这时EEMD或CEEMDAN才是可用的工具。2.2 EEMD靠白噪声平均能治标但不完备EEMD集合经验模态分解的解决思路很直观既然原始信号极值分布不均匀那就人为加上覆盖全频段的白噪声再对加噪信号做EMD。白噪声在时域里密布着极值点会改变原信号极值分布把散落的间断成分“聚拢”到对应的尺度上使其更容易被单独筛出来。一次加噪分解不够就重复几十上百次再把各次分解得到的对应IMF按位做算术平均。白噪声是随机的平均次数足够多时会相互抵消真实信号分量则保留下来。这个方案有效但不完备。关键问题在于每次分解都是独立加噪的噪声在有限次平均后并不能完全抵消干净。实测经验是NR取100时重建信号与原始信号的误差在10^-1量级附近取到500次也大致在10^-2到10^-1量级离机器精度差得很远。也就是说最后重构回去的信号里始终残留一份噪声相当于“拆出来的成分并不完全等于原始信号”。另外各阶段独立加噪还会让IMF之间不满足严格正交性分解结果随随机种子漂移两次运行得到的IMF形状基本一致但细节不同。2.3 CEEMDAN的自适应噪声把残差噪声挡在门外CEEMDAN自适应噪声完全集合经验模态分解看起来和EEMD差不多差在噪声的生成方式上。它不再对整段信号反复加同一组白噪声而是在每一阶IMF分解时先把白噪声做一次EMD得到对应的噪声IMF再把这段噪声IMF叠加到当前残差上继续筛分。第一阶IMF算完后从信号里扣除得到新的残差下一轮继续向当前残差叠加自适应的噪声IMF而不是回到原始信号重新加噪。这样每一轮加噪都与当前残差绑定噪声不会在后续分解中“漏”到下一层也不会残留在最终结果里。带来的收益是三个可量化的改善第一各阶IMF正交性明显变好重构误差能压到10^-10量级第二所需集总平均次数大幅下降普遍50到150次就够而EEMD通常要几百次第三对模态混叠的压制更加稳定尤其在间歇性冲击强烈的轴承信号上CEEMDAN拆出的冲击IMF更干净。这也是它被称为EMD系列进一步改进算法的原因——把“加噪声辅助分解”从一个经验做法变成了严格自适应的流程。方法对比一句话版本EMD是无辅助、单次分解理论重构无误差但模态混叠厉害EEMD是固定白噪声辅助、多次平均能压混叠但重构有残留CEEMDAN是自适应噪声辅助、按残差逐层推进混叠压得干净且重构误差接近机器精度。3. CEEMDAN参数设置Nstd、NR、MaxIter怎么调才不翻车3.1 三个核心参数的作用区间与默认值拿到任何一份CEEMDAN实现首先要面对的三个参数是Nstd、NR和MaxIter。它们分别控制噪声强度、平均次数和内部筛分迭代上限。下表是常用区间和调参方向参数常见取值作用偏大后果偏小后果Nstd0.050.4常用0.2辅助噪声标准差与信号标准差之比噪声残留增加可能产生非物理IMF对模态混叠压制不足NR50500常用100200集总平均次数计算时间成倍增加统计不充分结果逐次漂移MaxIter100010000常用5000单次EMD筛分最大迭代次数过筛分导致IMF过度平滑提前截断IMF不满足停止条件Nstd是最敏感的旋钮。取0.2的意思是辅助噪声的标准差为原始信号标准差的20%。这个值兼顾了极值点扰动和信噪比太小了压不住间歇分量太大了会把噪声引入到低频IMF中。NR和Nstd存在配合关系NR越大统计平均越充分Nstd可以适当调低如果NR只有50次Nstd最好不要超过0.25否则平均不充分残留噪声明显。3.2 输出结果怎么读IMF、Residue与重构误差CEEMDAN返回的内容一般是两部分IMFs矩阵和残差residual。IMFs矩阵每一行对应一阶IMF从上到下频率从高到低残差是最后的单调趋势项。有的实现会把残差直接附在矩阵最后一行读取前先看函数说明。要验证分解是否成功最直接的办法是算重构误差x_reconstruct sum(imfs, 1) residual; err max(abs(x - x_reconstruct));这里x是原始信号imfs是IMF矩阵residual是残差。取最大值的原因是把整个序列上的最大误差暴露出来避免平均误差掩盖端点附近的失真。err在1e-8以下说明分解是完备的如果err跑到1e-2量级大概率是NR太小或者这个实现并不是严格按CEEMDAN流程写的而是EEMD换了个名字。还需要建立一条认知IMF不是物理实体而是数据自适应的基函数。同一段信号换一组参数、换一个随机种子IMF形状会变但频率结构和分量组合是稳定的。所以不要执着于“某阶IMF必须等于某个物理分量”要关注的是IMF集合能否清晰地把目标频带分离出来。3.3 一个最小可运行的MATLAB示例下面这段代码是最小可运行的CEEMDAN调用流程信号是60Hz与150Hz正弦叠加高斯白噪声% CEEMDAN最小示例 fs 1000; % 采样率 1kHz t (0:999) / fs; % 时间向量1秒 x 2*sin(2*pi*60*t) 1.5*sin(2*pi*150*t); x x 0.2*randn(size(x)); % 叠加白噪声 rng(42); % 固定随机种子保证可复现 Nstd 0.2; % 辅助噪声标准差比例 NR 100; % 集总平均次数 MaxIter 2000; % 内部筛分迭代上限 [imfs, residual] ceemdan(x, Nstd, NR, MaxIter);这段代码里rng(42)不是可选项而是必选项。CEEMDAN内部每次运行会重新生成白噪声不锁种子的话同一条数据跑两次结果略有不同锁住后完全一致。Nstd取0.2是通用默认值NR取100在CEEMDAN里够用MaxIter取2000是为了这个长度的序列能正常收敛。如果换成长度超过几万点的信号MaxIter建议提高到5000。接着看一下分解结果是否合理figure; subplot(2,1,1); plot(t, imfs(1,:)); title(IMF1 - 150Hz分量); subplot(2,1,2); plot(t, imfs(2,:)); title(IMF2 - 60Hz分量);第一阶IMF理论上对应最高频分量所以是150Hz正弦第二阶对应60Hz。如果第一阶里同时出现两种频率的交替振荡就说明模态混叠没压住优先调大Nstd或NR重跑。4. 用CEEMDAN处理轴承振动信号从IMF筛选到包络谱4.1 故障特征频率计算先知道要找什么处理轴承信号前必须先算出目标特征频率否则分解完也不知道该看哪条谱线。滚动轴承的四个特征频率如下内圈故障频率BPFI (Z/2) × (1 (d/D)cosα) × fr外圈故障频率BPFO (Z/2) × (1 - (d/D)cosα) × fr滚动体故障频率BSF (D/(2d)) × (1 - ((d/D)cosα)²) × fr保持架故障频率FTF (1/2) × (1 - (d/D)cosα) × fr其中Z是滚动体个数d是滚动体直径D是节圆直径α是接触角fr是转轴转频。这些参数在轴承型号手册里都能查到不用自己估。写成一个计算脚本Z 12; d 8; D 40; alpha 0; % 某型号轴承参数 fr 29.5; % 转频约1770rpm BPFI Z/2 * (1 d/D * cos(alpha)) * fr; BPFO Z/2 * (1 - d/D * cos(alpha)) * fr; BSF D/(2*d) * (1 - (d/D*cos(alpha))^2) * fr;代入这组数得到BPFI约212Hz、BPFO约142Hz、BSF约71Hz。注意实际故障频率会有1%3%的滑移偏差分析时不要死盯着理论值不放要在理论值±3Hz范围内找峰值。4.2 分解、筛选IMF与重构降噪拿到轴承振动数据后先用CEEMDAN分解再用峭度筛选IMF做重构降噪。峭度对冲击型故障非常敏感轴承点蚀、剥落产生的冲击会在时域造成高尖峰其IMF峭度远高于平稳分量。以下是完整流程rng(0); % 固定种子 [imfs, residual] ceemdan(x, 0.15, 150, 3000); nImf size(imfs, 1); % 计算各阶IMF峭度 kurt zeros(nImf, 1); for i 1:nImf kurt(i) kurtosis(imfs(i, :)); end % 以峭度均值的1.5倍为阈值筛选冲击特征明显的IMF kurtRef mean(kurt); selIdx find(kurt 1.5 * kurtRef); xRec sum(imfs(selIdx, :), 1); % 重构降噪信号这里把Nstd从0.2降到0.15是因为实测数据本身就含噪声辅助噪声太强会把原始扰动放大。阈值kurt 1.5*kurtRef是经验值噪声大时调到2倍以上噪声小时1.2倍也能用。选择IMF时不看能量大小原因在于能量最大的往往是转频及其谐波分量不代表故障冲击峭度更能抓出冲击特征。如果算出来的selIdx为空说明信号里没有明显冲击成分可能是数据本身正常也可能是传感器安装位置离故障点太远、冲击被路径衰减吞掉了。4.3 包络谱分析与故障判定边界对重构信号做希尔伯特包络解调把高频冲击串转换成低频特征频率再做频谱分析env abs(hilbert(xRec)); % 包络解调 N length(env); f (0:N-1) * fs / N; % 构造频率轴 amp abs(fft(env)); plot(f(1:N/2), amp(1:N/2)); % 单边谱 xlim([0 300]);判定规则总结如下若BPFI附近出现明显峰值且伴随二倍频、三倍频判定为内圈故障若BPFO附近出现峰值判定外圈故障若只在转频fr处有峰大概率是不平衡或不对中不是轴承问题若任何特征频率处都没有峰先检查特征频率计算是否用错了轴承参数再检查采样长度是否过短导致频率分辨率不足。这里有个工程细节包络谱的频谱分辨率等于fs/N。采样长度只有0.5秒时分辨率是2Hz而滚动体故障频率BSF和保持架FTF往往只差几十Hz频谱分辨率不够会把相邻特征混在一起。建议至少采几十个转频周期让分辨率低于0.5Hz。5. CEEMDAN避坑指南五个高发翻车现场与排查办法5.1 两次运行结果不一致随机种子与NR没锁住现象同一段数据、同一组参数跑两次CEEMDAN得到的IMF形状略有差异重构误差也不一样。现象放在批处理脚本里每条数据结果都对不上下游特征矩阵没法保持稳定。原因CEEMDAN内部生成白噪声是随机的。没有固定种子的情况下每次运行噪声序列不同最终IMF自然不同。NR越小差异越明显。解决在调用前加rng(固定值)批处理时每条样本用同一套种子。如果发现同一种子下IMFs仍然剧烈抖动把NR从100加到200以上再试。固定种子是对科学复现的基本要求项目里的所有离线分析都应该留一个随机种子参数。5.2 分解速度突然变慢MaxIter与Nstd互相拉扯现象同一个程序昨天跑一段10万点数据只要几十秒今天换了一段同等长度的信号后跑到超时还没结束。原因这段新信号的高频成分丰富极值点密度大配合Nstd取0.2时噪声又制造了大量额外极值点单次筛分的迭代次数远超过默认的MaxIter上限。内部循环一直撞到上限才停下来整个分解耗时翻几倍。解决先把Nstd降到0.1或0.15看是否还有模态混叠同时把MaxIter从5000改成3000避免单阶做无意义的过度筛分。另外换一段只有原长度一半的数据测试用二分法确认是长度问题还是参数问题。CEEMDAN的复杂度是N乘以NR再乘以IMF个数任何一个乘数过大都会卡死。5.3 端点出现飞翼极值延拓方式选错了现象分解出的IMF在信号首尾几十个点出现大幅摆动幅度明显超过内部重构后的包络谱在低频段出现假峰。原因三次样条插值在首尾端点处缺少约束包络线会朝着没有极值的方向翘起来。这就是EMD系列都带有的端点效应CEEMDAN只是把它摊薄到各阶IMF并没有根除。解决分解前先做端点延拓常见做法是镜像延拓或基于自回归预测的延拓。镜像延拓是把端点附近的极值按对称方式延长简单且稳定。另一个实用操作是分解后丢弃首尾各一段数据比如单侧丢1%的采样点。如果项目允许也可以给信号加一段窗让两端渐变到零但要注意这样会改变IMF的幅值在做定量分析时不推荐。5.4 各段数据IMF数量不统一停止条件不一样现象一批20条样本信号分别做CEEMDAN有的返回7个IMF有的返回8个有的返回9个。下游特征矩阵的列数对不齐。原因CEEMDAN的停止条件是残差极值点少于两个或能量低于阈值。不同样本的噪声水平和极值分布不同天然会在不同阶段提前停住IMF数量自然不同。解决不要在停止条件上追求统一而是在分解后做长度对齐。常见做法是统一保留前N阶IMF一般是6到8阶多余的截断不足的补零或者把缺失的IMF视为零向量。更严格的做法是把最后一个残差也固定为某个公共长度所有样本都取同样的IMF数加一个残差。对齐后再做特征提取否则机器学习模型会直接报维度错误。5.5 把噪声IMF当真信号筛选阈值没做现象拿全部IMF直接求和作为降噪信号结果包络谱里多了好几个没有物理意义的峰值信噪比反而下降了。原因CEEMDAN分解出的前几阶里有一部分IMF本质上是辅助噪声的残余。它们虽然能量不大但包含了宽频噪声全部累加等于把噪声又加回来了。解决做筛选而不是全选。最少要做两个过滤峭度筛选去掉接近高斯分布的低峭度IMF相关系数筛选计算每个IMF与原始信号的皮尔逊相关系数低于0.3的直接剔除。两条件都满足的再进入重构。还有一个补充指标是能量占比能量占比低于1%的IMF对整个重构贡献很小留下只会引入噪声。6. 再进一步用重构误差和正交性指标给分解结果打分CEEMDAN用多了会发现光看IMF图像很难判断这次分解到底靠不靠谱。我习惯在每段数据分解完后强制算两个量化指标再进入下游流程。第一个是重构误差前文提过直接反映分解完备性err max(abs(x - (sum(imfs, 1) residual)));第二个是正交性指数IO衡量IMF之间互相独立的程度。EEMD的IO通常在0.1到0.3之间CEEMDAN应该明显小于0.1n size(imfs, 1); normsq sum(x.^2); IO 0; for i 1:n for j i1:n IO IO abs(sum(imfs(i,:) .* imfs(j,:))); end end IO IO / normsq;两者可以配合参数寻优写一个两重循环让Nstd在0.05、0.1、0.2、0.3四档NR在50、100、200三档各自跑一遍记录err和IO选两者都最小的组合。这比凭感觉调参可靠得多整个网格在新数据上跑也就十几分钟换来的是后续特征稳定。有一回我偷懒跳过了这两个指标直接拿分解结果去做样本熵特征结果特征值漂移得离谱。排查了两天才发现是那批数据Nstd取太大IO超过0.3IMF之间掺混严重。以后我每次分解完都强制走一遍err和IO两个指标再往下做。希望帮到你。本文还有配套的精品资源点击获取