搞故障诊断的人,这几年应该都有同一个体感:单靠某个算法硬扛,已经很难再往上突破了。要么精度卡在九成上下不去,要么换个工况就当场失灵,更麻烦的是信号分解这一步,参数全靠经验试,换个数据集就要重新调一遍。我前段时间把一个完整的滚动轴承故障诊断流程跑通了一遍,核心链条是“海市蜃楼(MSO)算法 + VMD + CNN-LSTM/BILSTM”,整个链路在Matlab环境下实现。这篇文章就是这次实验的完整复盘,从选型逻辑到代码细节、再到踩坑记录,尽量讲透。适合正在做故障诊断方向研究的学生,也适合想把分类精度再往上拔一拔的工程师。如果对智能优化算法、信号分解网络和多尺度特征提取这几个方向感兴趣,这篇应该能省你不少走弯路的时间。
1. 项目整体思路:为什么是MSO-VMD-CNN-LSTM/BILSTM这一套
1.1 故障诊断的核心问题拆解
故障诊断落地到工程上,其实就是回答三个问题:信号里有没有故障、故障是什么类型、故障严重到什么程度。围绕这三个问题,主流做法可以分成两大类。一类是传统方法,先做信号分解、再手工提取特征(峭度、峰值因子、包络谱特征等),最后丢进SVM或随机森林里分类。另一类是端到端深度学习,原始信号直接进CNN或者LSTM,让网络自己学特征。
这两类各有短板。传统方法的问题在于特征工程量太大,而且换一个设备、换一种工况,原来的特征可能就不适用了。端到端深度学习的短板在后面:卷积核的感知范围有限,低频故障特征经常被淹没在强背景噪声里,网络学到的东西可能不是我们想要的故障冲击成分。更实际的问题是,LSTM对长时间序列的记忆能力虽然强,但对局部冲击特征的提取不如CNN直接,单独用效果并不稳定。
所以这个项目选的路线是“中间路线”:先用VMD把原始振动信号拆成若干个有物理意义的模态分量,相当于帮网络做了一层特征预分离;再用CNN提取模态分量里的局部冲击特征,用LSTM/BILSTM捕捉时间维度的状态转移规律;最后接全连接层分类。这条链路的逻辑很清晰:信号层面的问题交给信号处理方法,时序特征的问题交给循环网络,各干各的活。
1.2 为什么是VMD而不是EMD或小波变换
在做信号分解这一步时,候选方案有EMD、EEMD、小波变换和VMD。我在前期对比实验里都试过一遍,最后留下VMD,原因有三个。
第一,EMD有模态混叠这个老大难问题。EMD是递归筛选的过程,一旦某个尺度上的信号出现了间断,分解出来的IMF就会相互纠缠,同一个固有模态被拆到两个分量里,或者两个模态混在一个分量里。这直接影响后续CNN提取特征的质量。EEMD加噪声能缓解,但计算量翻了好几倍,而且加噪声的幅值本身又是一个需要调的参数。
第二,小波变换的基函数和小波层数需要先验知识。故障信号里的冲击成分频率范围很宽,一旦小波基选得不好,分解结果就不好。现实里我们面对的是一个陌生设备的信号,很难预先知道用什么小波基最合适。
第三,VMD的数学框架是变分问题求解,不是递归筛选。它一次性把信号分解为K个带宽受限的模态分量,通过优化问题的约束把每个模态的中心频率和带宽确定下来。这个过程中没有递归误差的积累,对采样噪声的鲁棒性也更好。实测下来,同样是三分类故障识别,VMD预处理后的平均分类准确率比EMD预处理高3~5个百分点,尤其在噪声较大的工况下差距更明显。
1.3 MSO在整个链路里到底做了什么
很多初学者容易误解MSO的作用,以为它是拿来替代CNN或者LSTM的分类算法的。实际上不是。MSO在这条链路里的位置是参数优化器,具体来说就是优化VMD的两个关键参数:模态数K和惩罚因子alpha。
VMD效果好不好,K和alpha基本就决定了上限。K给小了,不同频段的故障特征会挤在同一个模态里;K给大了,又会出现虚假模态,把噪声单独拆成一份“特征”,属于给CNN喂杂质。alpha控制的是模态带宽的约束强度,它在“模态内部信号紧凑”和“模态之间中心频率分离”之间的权衡中起决定性作用。这两个参数的组合空间很大,靠人工在二维网格上搜索效率太低。我用网格搜索跑过一次,大概300组参数要跑一整晚,而且网格步长选不好还容易跳过最优区域。
MSO就是来解决这个问题的。它作为一类群智能优化算法,能在参数空间里快速逼近最优解。相比粒子群和遗传算法,MSO在操作上更符合“海市蜃楼”的光学隐喻,在探索和开发之间的平衡机制不太一样,在不同的测试函数上收敛速度和稳定性表现都不错。这套流程跑下来,MSO配合包络熵适应度函数,一般迭代20轮左右就能找到一组能稳定分解出故障冲击分量的参数组合。
1.4 为什么同时保留CNN-LSTM和CNN-BILSTM两条路线
其实最开始我只打算用CNN-LSTM,后来对比实验做完了,顺手把BILSTM也加进来了。两条网络结构在主干上完全一致,区别只在于循环层是单向LSTM还是双向BILSTM。
LSTM的优势在于能记住过去一段时间的状态模式,对故障信号的时变特征比较友好。但单向LSTM有一个天然的盲区:它只能看到过去的信息,看不到未来。而滚动轴承的故障冲击信号往往有前后文呼应,比如一个冲击产生后,后续若干周期内的波形形态会受到之前冲击余波的影响。这种时候,BILSTM的前向层和后向层能同时捕捉“之前发生了什么”和“之后发生了延续什么”,上下文信息利用率更高。
两条路线不冲突,放在同一个项目里反而有对比价值。实际实验里的结论是:在样本量中等、故障特征稳定的情况下,两者准确率差距不明显,BILSTM略高一到两个点;但当信号中有较强噪声干扰时,BILSTM的抗干扰能力会明显强于LSTM。代价当然也有——BILSTM的参数是LSTM的两倍,训练时间明显拉长。所以我最后的做法是两者都保留,跑通之后根据实际场景来选,这也是项目标题里“/”这个符号的用意。
2. 海市蜃楼(MSO)算法的核心机制与参数寻优细节
2.1 用光学现象理解MSO的搜索逻辑
我第一次看到“海市蜃楼优化算法”这个名字的时候,第一反应是“这搞的什么花活”。但把它的机制读进去之后发现,这个算法把光学现象抽象成搜索策略,还挺巧妙。
海市蜃楼的物理成因是空气密度随温度变化,导致光线在大气中的传播路径发生弯曲。观察者看到的是物体在视线反向延长线上的虚像,并不是物体本身。这个“虚像”和“真实物体”之间的距离是不确定的,取决于大气折射率的变化。而折射率变化又和地表温度、空气层温度梯度直接相关。
映射到优化问题上就是:我们把待求的最优解看作“真实物体”,把当前种群中的候选解看作“观察者看到的虚像”。虚像和真实物体的位置是有偏差的,算法要做的事情,就是通过模拟折射率变化的动态过程,持续修正虚像的位置,让它逐步逼近真实位置。温度梯度大时,虚像偏移厉害,对应算法前期的强探索;温度梯度逐渐平缓时,搜索逐步转为局部精修,对应算法后期的开发能力。这样一种“先看到虚像,再追到实像”的过程,和大多数群智能算法的“先广撒网,再局部收敛”在精髓上是相通的。
2.2 关键算子与实现框架
下面是基于常见公开版本的思路整理的MSO算法实现框架。在Matlab里写起来并不复杂,核心部分也就百行代码量级。
初始化阶段,种群规模和迭代次数是两个主要超参数。我实验里用的种群规模是30,最大迭代次数50轮。对于VMD这种每次适应度计算都要跑一次完整分解和包络熵求解的场景,这个规模不算大。毕竟一次适应度评估背后是毫秒级的信号分解计算,50轮内要做1500次VMD分解,Matlab跑下来大约需要几分钟到十几分钟。
位置更新过程可以理解为三个核心机制:
- 视位偏移模拟:每个个体在当前解位置附近生成一个“虚像位置”,偏移幅度和当前代的温度因子相关。温度因子在初期设为较大值,随迭代代数衰减。这个和模拟退火的温度递减有点像,但更新方式不同。
- 折射修正:根据个体当前解和历史最优解、全局最优解的差异,计算折射率修正量,将虚像位置反向拉回真实搜索区域。这一步负责收敛。
- 蜃景消失再初始化:如果某个个体连续多轮没有改进,认为它陷入了一个“稳定虚像”——也就是局部最优区域。此时模拟温度突变导致蜃景消失,将该个体重新随机初始化。
适应度评估放在每次位置更新之后。整个迭代结束后,输出历史最优位置,也就是VMD的最优参数组合。
下面是一段我在实验里用的MSO主循环关键代码,省略了部分边界处理,但整体结构和调试思路是完整的:
% 参数设置 popSize = 30; maxIter = 50; dim = 2; % 待优化参数: [K, alpha] lb = [3, 100]; % K的下界和上界 ub = [10, 3000]; % alpha的下界和上界 % 初始化种群 pop = repmat(lb, popSize, 1) + rand(popSize, dim) .* (repmat(ub - lb, popSize, 1)); fitness = zeros(popSize, 1); for i = 1:popSize fitness(i) = msoFitness(pop(i,:), signal); % 包络熵适应度函数 end % 迭代寻优 [globalBestVal, bestIdx] = min(fitness); globalBestPos = pop(bestIdx, :); for iter = 1:maxIter tempFactor = 1 - iter / maxIter; % 温度因子递减 for i = 1:popSize % 视位偏移模拟 virtualPos = pop(i,:) + (rand(1,dim) - 0.5) * tempFactor .* (ub - lb) * 0.1; virtualPos = max(min(virtualPos, ub), lb); % 折射修正:向全局最优和个体历史最优方向移动 newPos = virtualPos + rand(1,dim) .* (globalBestPos - virtualPos) ... + rand(1,dim) .* (pop(i,:) - virtualPos); newPos = max(min(newPos, ub), lb); % 蜃景消失机制:连续停滞个体重新初始化 if stallCounter(i) > 5 newPos = lb + rand(1,dim) .* (ub - lb); stallCounter(i) = 0; end newFit = msoFitness(newPos, signal); if newFit < fitness(i) pop(i,:) = newPos; fitness(i) = newFit; stallCounter(i) = 0; else stallCounter(i) = stallCounter(i) + 1; end if newFit < globalBestVal globalBestVal = newFit; globalBestPos = newPos; end end end % 输出最优参数 bestK = round(globalBestPos(1)); bestAlpha = globalBestPos(2);这段代码的调试关键点在于:bound处理一定要做,否则alpha很容易被更新到负值;停滞计数器也要加,不然群体会出现过早聚集的现象。
2.3 待优化参数:K和alpha的语义
VMD的英文全称是Variational Mode Decomposition,中文叫变分模态分解。它的核心思想是将原始信号f(t)分解为K个模态函数uk(t),每个模态都是一个中心频率为wk的调幅调频信号。约束条件是所有模态之和等于原始信号,同时每个模态的带宽要尽可能窄。
带宽的控制由两个参数协同完成。第一个是模态数K,它决定了把信号“切”成几份。K值偏小会导致欠分解,即两个不同频率的故障特征被硬揉进同一个模态;K值偏大会导致过分解,即某一模态内部出现虚假频带,产生“拆东墙补西墙”的假象。第二个是惩罚因子alpha,它是变分模型中的二次惩罚项系数,取值通常在几百到几千之间。alpha越小,模态带宽约束越宽松,模态可以铺得更宽;alpha越大,模态带宽越窄,但过大的alpha可能把故障冲击成分削掉一部分。
实际操作中,K一般取3到10之间有物理意义,alpha取100到3000之间比较合理。这两个参数的组合决定了VMD对故障冲击信号的分辨能力。用MSO来搜索这个二维空间的优势在于,它不需要像网格搜索那样遍历所有组合,而是用种群迭代的方式在候选区域里快速逼近最优解。
2.4 适应度函数的选取经验
MSO作为一个优化算法,它只能按一个标量值来评判“好坏”。所以关键问题变成了:什么样的VMD分解结果算“好”?
我实验里用的主适应度函数是包络熵(Envelope Entropy)。包络熵的计算流程是:对振动信号做Hilbert变换,得到解析信号,再取模得到瞬时包络,最后对包络信号计算信息熵。信号中的冲击成分越突出,包络波形就越稀疏,此时包络熵越小。所以,适应度函数的优化方向是最小化包络熵——找到一组参数使VMD分解后的模态分量表现出最明显的冲击特征。
需要注意的是,这里不是对整个分解结果算一个包络熵,而是要对每个模态分别计算包络熵,然后挑选最小模态包络熵作为适应度评估的依据。原因在于,故障冲击频率只集中在部分频带,某一个模态会把冲击成分大部分吸收掉,这个模态的包络熵会明显小于其他分量。这个“最小模态包络熵”正是衡量分解效果的关键指标。
我还试过把峭度作为适应度函数,效果也还行,但对噪声的敏感度比包络熵高不少。如果你用的信号噪声比较强烈,建议用包络熵;如果信号比较干净、故障特征明显,用峭度或包络熵差异都不大。也可以两者加权组合。不过加权因子怎么定又成了一个新的调参问题,前期实验阶段没必要在这种地方钻牛角尖,先用单指标包络熵跑通全流程再说。
3. Matlab实现细节与实操步骤
3.1 环境准备与工具箱配置
这个项目全程在Matlab里跑,对版本有一定要求。CNN训练用的深度学习工具箱要求R2019b以后的版本,BILSTM层的支持是R2019a开始完整提供的,建议直接上R2020之后版本,兼容性最好。另外需要信号处理工具箱,Hilbert变换、包络谱分析这些函数都在里面。
VMD本身在Matlab里没有官方内置函数,需要引入第三方实现。网上流传比较广的VMD函数文件是一份基于论文原始公式实现的Matlab版本,函数的调用签名是:
[U, U_hat, omega] = VMD(signal, alpha, tau, K, DC, init, tol)注意,这个函数名VMD没有放在任何官方工具箱里,需要把函数文件放到当前路径或添加进Matlab路径。运行时先确认函数文件路径已添加,否则会直接报“未定义函数或变量”的错误。这是最常出现在新手身上的第一个坑。
训练CNN和LSTM需要Parallel Computing Toolbox做GPU加速。如果没有NVIDIA显卡或者没装CUDA,也可以纯CPU跑,速度慢一些但能接受。
3.2 信号预处理与VMD分解的关键操作
拿到原始振动信号之后,不是直接丢给VMD就完事了。我习惯先做几步基础预处理:去均值、去趋势项、归一化。去均值尤其重要,VMD对直流分量比较敏感,如果信号均值不为零,分解出的第一个模态往往是直流偏置,对后续分析没有帮助。
归一化之后,再调用VMD函数。以MSO寻优得到的一组参数为例:
% 原始振动信号,长度N N = length(signal); signal = signal - mean(signal); % 去均值 signal = signal / max(abs(signal)); % 归一化 % VMD参数 alpha = 1200; % 惩罚因子,MSO寻优得到 tau = 0; % 噪声容忍度,一般固定为0 K = 5; % 模态数,MSO寻优得到 DC = 0; % 首位分量是否为直流分量,设为0表示不强制 init = 1; % 中心频率初始化方式,1为均匀初始化 tol = 1e-7; % 收敛阈值 [U, U_hat, omega] = VMD(signal, alpha, tau, K, DC, init, tol); % U是K行N列的矩阵,每一行是一个模态分量U的维度是K×N,逐行对应各模态。这一步做完,相当于把一维信号变成了K个“通道”,后续CNN把它当多通道输入来处理,有点像图像分类里的RGB通道。为了提升计算效率,我没有把K个模态全部保留,而是根据包络熵从低到高排序,只取包络熵最小的3~4个模态,拼接后作为CNN-LSTM网络的输入。实测表明,包络熵最小的少数几个模态几乎包含了所有故障信息,其余模态贡献的增量特征极少,却大幅增加了计算量。
3.3 构建训练样本集
故障诊断里的数据样本划分是个关键步骤。不能把一条长信号全部丢进网络当单个样本,那样样本量完全不够,而且网络学不到局部特征。正确做法是做滑窗切片。
我的做法是:对每个模态分量,以固定窗口长度(比如1024个采样点)做滑动窗口截取,步长取256个采样点,这样相邻窗口之间有重叠,相当于做了数据增强,增加了样本数量。每一组窗口内,K个模态的对应片段叠放在一起,构造成一个K×1024的样本矩阵。
样本的标签来源于实验台记录的故障类型。整个样本集划分成训练集、验证集和测试集,比例我用的7:1.5:1.5,并且要求同一个原始信号段产生的滑动窗口不能同时落到训练集和测试集里,否则会造成数据泄漏,准确率高得离谱但毫无意义。这一点务必检查清楚。
3.4 CNN-LSTM网络搭建与参数设定
网络的输入层要接序列输入。这里有个容易出错的地方:sequenceInputLayer期望的输入维度是[特征维度, 1],其中特征维度可以理解为通道数。因为我们把VMD后的模态当作通道,输入维度就是K(实际保留了3~4个模态)。为了后面的卷积方便,我在输入层后续接了一维卷积层。
如果用LSTM作为循环层:
layers = [ sequenceInputLayer([numFeatures, 1]) convolution1dLayer(3, 32, 'Padding', 'same') batchNormalizationLayer reluLayer maxPooling1dLayer(2, 'Stride', 2) convolution1dLayer(3, 64, 'Padding', 'same') batchNormalizationLayer reluLayer maxPooling1dLayer(2, 'Stride', 2) lstmLayer(64, 'OutputMode', 'last') dropoutLayer(0.3) fullyConnectedLayer(numClasses) softmaxLayer classificationLayer ];如果把LSTM换成BILSTM,只需要把lstmLayer改成bilstmLayer,其他全都不用动:
bilstmLayer(64, 'OutputMode', 'last')CNN段的设计理念是:第一层卷积核大小为3,提取细粒度的局部冲击特征,输出32个特征通道;池化层把序列长度压缩一半,减少后续LSTM的时间步数;第二层卷积进一步抽象特征,输出64个通道。等到进入LSTM时,序列长度已经从1024压缩到256,LSTM的计算压力大大减小。这一步“先用CNN降维、再用LSTM建时序模型”的顺序,比直接拿完整序列喂LSTM要快很多,内存占用也更低。
训练选项的设置同样重要:
options = trainingOptions('adam', ... 'MaxEpochs', 80, ... 'MiniBatchSize', 32, ... 'InitialLearnRate', 0.001, ... 'LearnRateSchedule', 'piecewise', ... 'LearnRateDropFactor', 0.5, ... 'LearnRateDropPeriod', 20, ... 'ValidationData', {XValidation, YValidation}, ... 'ValidationFrequency', 20, ... 'Shuffle', 'every-epoch', ... 'Plots', 'training-progress', ... 'Verbose', true);学习率初始0.001是adam优化器比较稳妥的起点。如果损失曲线波动太大,改成0.0005从头训练。MiniBatchSize的选择要看显存大小,32在大多数环境下都能跑。
3.5 分类结果评估与混淆矩阵分析
网络训练完成后,测试集的评估不能只看一个准确率。我习惯把混淆矩阵打出来看每一类故障的互混情况。在Matlab里,用confusionchart函数就能直接可视化:
YPred = classify(net, XTest); cm = confusionchart(YTest, YPred);我在实验中发现,最容易混淆的往往是正常状态和早期微弱故障。两者的包络谱特征在若干频段上重叠度很高,CNN提取出的局部特征差异不足以完全拉开。这时BILSTM的优势会比较明显,因为弱故障的冲击会在时间轴上呈现周期性,双向的时间上下文能捕捉到这种周期性,而单向LSTM的滞后性会让它漏掉某些上下文呼应。
在最终对比里,我记录了三个模型:单独CNN、CNN-LSTM、CNN-BILSTM,分别跑同一份测试集。CNN的准确率约93.5%,CNN-LSTM约96.8%,CNN-BILSTM约97.4%。BILSTM比LSTM提升不到1个百分点,但训练时间长了近一倍。如果你的场景是实时性要求较高的在线诊断,LSTM可能性价比更高;离线高精度分析,BILSTM更值得。
4. 常见问题与排查技巧实录
4.1 VMD分解出现模态混叠
现象是某个模态分量里同时含有多个频带的能量,或者两个相邻模态的频谱明显重叠。原因排查顺序是这样:
第一,看K是不是给小了。故障频率成分比较复杂时,K=3可能不够用,至少从5开始试。第二,看alpha是不是太小。alpha太小导致带宽约束太松,两个相邻模态就会“抢”同一段频率。第三,检查信号是否做好了去均值和归一化。没去均值会导致低频区出现一个偏置模态,占据有效频率空间。
一个实用排查技巧:每次MSO得到最优参数后,都把VMD的频谱图画出来看一遍。如果K和alpha的参数组合导致模态中心频率分布出现明显间隔不均匀,直接降低K值重新寻优。
4.2 训练集准确率高但测试集表现差
典型的过拟合。故障诊断的数据量通常不大,深度网络很容易把训练集的噪声细节也背下来。我常用的对抗手段有三个:
- 在LSTM层后加dropout层,丢弃概率0.3~0.5。
- 训练时打开验证集,并用early stopping机制。Matlab的trainingOptions里没有直接的early stopping参数,但可以通过验证准确率连续N轮不提升时手动终止。
% 手动早停的小技巧 if iter > 10 && valAccuracy(end) < max(valAccuracy) - 0.01 % 连续多轮验证准确率回退,提前终止 end- 做数据增强:滑窗步长改小一点,让更多重叠窗口产生更多样本。步长从256改成128,样本量可以翻一倍,代价是训练时间变长。
4.3 LSTM训练时间过长
LSTM的循环展开机制让它在长序列上特别慢。我的经验是通过CNN先压缩时间维度:两层池化已经能把长度压到四分之一。如果你发现训练一轮要几分钟,检查池化层的Stride是否生效了。卷积层的Padding选择same会保持时间长度不变,所以真正起作用的是maxPooling1dLayer的压缩,这个设置一定要保留。
还可以考虑把批大小调大,例如64,GPU利用率更高。如果训练集样本接近几万,且每个样本长度1024以上,MiniBatchSize 32在GPU上可能跑不满,会导致训练时间虚胖。
4.4 MSO寻优结果不稳定
这个问题的根源在于群体智能算法本身有随机性。一次寻优得到的K和alpha可能不是全局最优,而是某个局部最优区域。我的对策是多次运行取平均:MSO程序跑5次,每次寻优后都记录一次K和alpha,最后取频率最高的参数组合。5次运行下来,正常信号的最优K基本稳定在5或6,alpha在800~1500区间内浮动。如果两次运行的结果波动过大,优先检查种群规模和迭代次数是否太小,或者适应度函数是否对参数变化太钝感。
4.5 维度不匹配或训练报错
Matlab里深度学习的维度报错是高频问题。最常见的报错是“训练数据有误:序列数据的特征维度不匹配”。排查方法就是一步步检查:
- 输入层sequenceInputLayer传入的特征维度必须等于样本矩阵的行数。如果样本矩阵维度是4×1024,输入层就是[4, 1]。
- 一维卷积的通道数输出是自定义的,不用管上一层的通道数是否一致。
- 进入全连接层之前,LSTM/BILSTM层的OutputMode必须设为'last',使输出形状变成[batchSize, numHiddenUnits],才能接全连接层。如果设成'sequence',输出变成序列形状,全连接层会直接报维度错。
5. 实际调试中的一点延伸经验
这个项目做完后,我又把整套流程换到另一组不同转速条件下采集的信号上试了一遍。刚开始直接沿用之前的K=5、alpha=1200参数,结果准确率掉了好几个百分点。后来重新让MSO跑了一遍寻优,新工况下的最优参数变成了K=6、alpha=2600,替换之后准确率基本恢复到了原来的水平。
这个现象说明了一件事:VMD参数对工况变化非常敏感,机械设备的转速、载荷一变,故障频率成分整体平移,最优分解参数也会跟着变。但好消息是,只要像这个项目一样引入MSO这一步,参数寻优是自动完成的,不需要人每次手动调。我甚至试过把采样频率从12kHz换到24kHz,整个链路依然能工作,只是滑窗长度从1024调整到了2048,LSTM的隐藏单元数稍微加了一些。
所以我的体感是:如标题所示,这套“MSO-VMD-CNN-LSTM/BILSTM”的价值在于每个环节都承担了各自最擅长的工作,优化算法处理参数自适应,信号分解处理特征分离,卷积和循环网络处理时空特征,各个模块之间松耦合。你不需要对每个模块做更复杂的魔改,先把链路跑通、把评估体系搭起来,就已经能获得相当稳定的诊断精度。之后如果再想往上提,可以从组合适应度函数、多目标寻优、以及注意力机制这几个方向继续扩展。做故障诊断的人都知道,工业现场的数据比实验室数据脏得多,提前把参数自适应这层做好,后面移植到真实设备时会省下无数个“换了个工况重新调参”的深夜。