MATLAB实现LSTM与SVM设备故障诊断:从特征工程到源码详解

发布时间:2026/8/31 5:25:07
MATLAB实现LSTM与SVM设备故障诊断:从特征工程到源码详解 简介本资源是一套基于MATLAB实现设备故障诊断的完整算法实践方案面向工业智能运维领域的研究人员、自动化专业学生及机器学习初学者聚焦时间序列建模与小样本分类两大核心问题。压缩包共62个文件含53个.mat数据文件存储西储大学轴承故障数据集预处理后的特征与标签、3个主程序脚本run_1.m等实现LSTM训练与SVM分类流程、2个说明文档含数据集介绍与特征向量构建逻辑、1个.xlsx特征表、1个.class增强信号处理工具及配套ASV备份与DOCX说明整体大小为52.77MB。已有59人学习下载资源结构清晰分层data目录组织原始与归一化数据tezhengxiangliang存放手工/ESMD提取的时频域特征tu.m等脚本提供模型性能可视化混淆矩阵、F1曲线、准确率对比图并支持LSTM早期预警与SVM多类故障精分的协同诊断流程。 搞设备故障诊断有一段时间了用的最多的工具组合就是MATLAB加上机器学习那套东西。今天我把用LSTM和SVM做设备故障诊断的完整思路、源码细节、踩坑记录一次性整理出来。这篇内容适合已经在读研或者刚进厂做设备健康管理的朋友也适合那些想从传统信号处理转向数据驱动诊断的工程师按着步骤走不需要深厚的机器学习基础也能跑通整个流程。先说清楚这活儿到底是干嘛的。所谓设备故障诊断本质上是利用传感器采集到的振动、温度、电流等信号判断设备当前处于什么状态。比如滚动轴承常见故障就是内圈磨损、外圈点蚀、滚动体损伤这几类。传统做法是靠老师傅听声音、看频谱有经验但不可复制。用LSTM和SVM这类模型就是让算法从历史数据里自己学出故障特征然后对新采集的数据自动分类实现故障类型的智能识别。我这里把两个模型都做了一个偏传统机器学习一个偏深度学习各有各的适用场景。1. 整体设计思路为什么同时用LSTM和SVM1.1 两个模型的本质差异在设备故障诊断这个场景里LSTM和SVM是完全两种路子。SVM属于经典机器学习方法它做的事情是在特征空间里找一个最优超平面把不同类别的样本分开。它的核心优势在于样本量不大的时候泛化能力很强而且对高维特征的处理非常稳定。LSTM则是循环神经网络的一个变种专门处理时间序列数据它通过门控机制记住长期依赖关系所以在信号本身具有时序特征的情况下表现更好。我之所以两个都做而不是只选一个是因为在实际项目里你根本提前不知道数据长什么样。有的设备信号周期性很强故障特征主要体现在时间序列的形态变化上那LSTM就有优势有的设备信号噪声大需要你人工提取统计特征后再分类SVM配合好的特征工程照样能打。两个模型都落地可以在面对不同数据时灵活选择基线方案。1.2 方案选型为什么选MATLAB而不是Python很多朋友会问搞深度学习不是Python更主流吗这话没错但MATLAB在设备故障诊断这个特定领域有它不可替代的地方。第一MATLAB的信号处理工具箱太成熟了滤波、FFT、小波变换、经验模态分解全是内置函数比Python里到处找库再调参省事太多。第二Simulink可以做硬件在环仿真后面如果要往嵌入式平台部署整个链路是通的。第三MATLAB的Classification Learner和Deep Network Designer这两个App让你可以先拖拽式地验证方案可行性再转成脚本做批处理这个工作流效率很高。我自己的习惯是先用MATLAB把特征工程和算法原型验证完如果后面需要大规模部署上线再考虑把模型移植到其他平台。做学术研究或者打比赛MATLAB的代码可读性也更好审稿人看起来也直观。1.3 诊断流程的整体架构整个诊断系统可以拆成四个环节。第一步是数据采集通过加速度传感器获取设备振动信号采样率一般在12kHz到48kHz这个要看你诊断的故障频率范围。第二步是数据预处理包括去趋势、滤波去噪、归一化。第三步是特征提取和模型构建这里分两条线一条线走人工特征加SVM另一条线走原始序列直接喂给LSTM。第四步是模型评估与对比用混淆矩阵、准确率、召回率这些指标来判断模型的实用性。后面我所有的代码和讨论都是围绕这个架构展开的。下面一个个环节细讲。2. 数据准备与预处理故障诊断的地基2.1 数据集来源说明这个项目里我用的标准数据集是凯斯西储大学CWRU的滚动轴承数据中心数据这是故障诊断领域用得最多的公开数据集。数据里有正常状态、内圈故障、外圈故障、滚动体故障四类每类故障还分了不同的损伤直径采样频率有12kHz和48kHz两种档位。MATLAB读取CWRU数据的代码很简单官方的mat文件直接load就能读每个mat文件里包含了DE驱动端加速度、FE风扇端加速度、BA基座加速度几个通道你根据自己需要取一个通道就行。实际操作中我一般取DE通道因为故障特征在驱动端表现最明显。如果你没有公开数据集自己用实验台采集也完全可以。关键是保证每个状态类别下采集的样本数量均衡别出现一类样本200组、另一类只有20组的情况否则后面训练出来的模型基本就废了。2.2 数据分帧与样本构造拿到连续的振动信号后不能直接把整段信号丢给模型。原因很简单一整段信号可能长达几十秒包含了很多个旋转周期信息过于冗余而且计算量太大。标准做法是把长信号切成固定长度的小片段每个片段作为一个独立样本。切片长度怎么选我做过对比实验在12kHz采样率下切片长度选1024个采样点约0.085秒或者2048个采样点约0.17秒效果比较好。太短了单个样本包含的故障冲击信息不够模型学不到东西太长了样本数变少而且一个样本里可能混入多种状态的过渡反而干扰分类。构造样本的时候还有个细节相邻片段之间可以设置重叠率。比如切片长度2048步长512那相邻两个片段就有75%的重叠。这样做的好处是变相做了数据增强样本量能翻好几倍对LSTM这种数据饥饿型模型尤其重要。% 信号分帧示例 function samples signal2frames(signal, winLen, stepLen) n length(signal); idx 1:stepLen:(n - winLen 1); numSamples length(idx); samples zeros(numSamples, winLen); for i 1:numSamples samples(i, :) signal(idx(i):idx(i) winLen - 1); end end2.3 特征提取SVM的输入是特征不是原始信号SVM没法直接吃原始振动信号。把2048个采样点直接作为2048维特征喂给SVM理论上可以但效果很差因为原始信号里包含了大量与故障无关的噪声和冗余信息而且维度太高还容易引发维度灾难。所以SVM这条路必须做特征工程。我常用的特征分两组。时域特征包括均值、方差、峰值、均方根值、峭度、波形因子、峰值因子、脉冲因子、裕度因子、偏度、标准差一共11个。频域特征包括频谱峰值对应的频率、频谱重心、均方频率、频率方差、频域幅值均值等。把这些特征拼在一起每个样本变成一个15到20维的特征向量再喂给SVM。这里我强烈建议你画一下特征可视化图就是PCA降维之后把不同类别的样本用不同颜色画在二维平面上。如果不同类别在特征空间里已经有明显的分簇现象那后续SVM的分类效果大概率不会差。如果特征混在一起完全分不开说明你提取的特征没有抓住故障的本质换再好的分类器也没用。function featVec extractFeatures(x) % 时域特征 meanVal mean(x); varVal var(x); peakVal max(abs(x)); rmsVal rms(x); kurtVal kurtosis(x); % 频域特征 L length(x); Y fft(x); P2 abs(Y/L); P1 P2(1:floor(L/2)1); P1(2:end-1) 2*P1(2:end-1); f 12000 * (0:floor(L/2))/L; % 假设采样率12kHz [~, maxIdx] max(P1); peakFreq f(maxIdx); % 组合 featVec [meanVal, varVal, peakVal, rmsVal, kurtVal, peakFreq]; end2.4 归一化处理不管你用SVM还是LSTM归一化这步都逃不掉。SVM对特征的尺度非常敏感如果某个特征的数值范围是0到1000另一个是0到1那距离计算几乎完全被前者主导后者形同虚设。LSTM内部用sigmoid和tanh激活函数输入数值如果太大梯度很容易饱和训练直接卡死。归一化最简单有效的方法就是z-score标准化让每个特征变成均值为0、方差为1的分布。MATLAB里一行代码就能搞定% 训练数据标准化 [featTrainNorm, mu, sigma] zscore(featTrain); % 测试数据必须用训练集的mu和sigma featTestNorm (featTest - mu) ./ sigma;这里有个特别容易踩的坑测试集的标准化必须用训练集算出来的均值和标准差不能自己单独算。因为模型在训练时学习的特征分布是训练集定义的你如果让测试集独立标准化相当于改变了特征的相对尺度测试结果就不准了。很多新手在这个地方栽跟头还找不到原因最后模型精度上不去就怪算法不好其实是数据预处理的问题。3. SVM诊断模型MATLAB源码实现3.1 多分类SVM的核心思路SVM原始版本是二分类器只能回答是或者不是。设备故障诊断通常是多分类问题比如判断轴承是正常、内圈故障、外圈故障还是滚动体故障四选一。怎么让SVM处理多分类业界有两种主流策略一对一One-vs-One简称OvO和一对多One-vs-All简称OvA。MATLAB的fitcecoc函数用的是纠错输出编码ECOC框架它默认支持这两种策略。CWRU四分类问题下fitcecoc内部会对K个类别两两训练一组二分类器一共训练出K*(K-1)/2个子分类器然后通过投票决定最终类别。这种做法的好处是每个子分类器只需要区分两个类别决策边界简单训练效率高。3.2 完整的SVM训练与预测代码下面这段代码我实测可以直接跑通里面有完整的注释。注意其中OptimizeHyperparameters参数可以自动做超参数调优但会显著增加训练时间数据量小的时候可以用数据量大了建议关掉手动调参。% 加载特征数据假设已经构造好 % featTrain: 训练特征矩阵每行一个样本 % labelTrain: 训练标签1正常, 2内圈, 3外圈, 4滚动体 % 使用fitcecoc训练多分类SVM svmModel fitcecoc(featTrain, labelTrain, ... Learners, templateSVM(KernelFunction, rbf, ... BoxConstraint, 1, ... KernelScale, auto), ... Coding, onevsone, ... Verbose, 1); % 测试集预测 labelPred predict(svmModel, featTestNorm); % 计算准确率 accuracy sum(labelPred labelTest) / length(labelTest); fprintf(SVM Test Accuracy: %.2f%%\n, accuracy * 100);这段代码里容易被人忽略的是templateSVM这个函数。在MATLAB较新版本中SVM的超参数要通过templateSVM来定义BoxConstraint和KernelScale是两个决定性参数。3.3 超参数寻优BoxConstraint和KernelScale怎么调BoxConstraint记作C是SVM的正则化参数它控制误分类惩罚和决策边界复杂度之间的权衡。C值大模型越倾向于把所有训练样本都分对边界变得复杂容易过拟合C值小模型允许一些样本被分错边界更平滑泛化能力可能更好。KernelScale记作gamma控制RBF核的宽度gamma越大每个支持向量的影响范围越小边界越复杂gamma越小影响范围越大边界越平滑。这两个参数怎么选最科学的做法是网格搜索配合交叉验证。我在这个项目里用5折交叉验证把C从0.1到100按对数间隔取10个值gamma从0.01到10按对数间隔取10个值组合起来一共100个候选参数对每组做一次5折交叉验证选出平均准确率最高的那组参数。% 超参数网格搜索示例 CList logspace(-1, 2, 10); % 0.1 到 100 gammaList logspace(-2, 1, 10); % 0.01 到 10 bestAcc 0; bestParams []; for c CList for g gammaList % 5折交叉验证 cvModel fitcecoc(featTrain, labelTrain, ... Learners, templateSVM(KernelFunction, rbf, ... BoxConstraint, c, ... KernelScale, g), ... Coding, onevsone, ... CrossVal, on, KFold, 5); acc 1 - kfoldLoss(cvModel); if acc bestAcc bestAcc acc; bestParams [c, g]; end end end实测下来CWRU数据集做过特征工程之后C在1到10之间、gamma在0.1到1之间的区域效果最好测试准确率能做到97%以上。但你要记住这是这个特定数据集的结果换到自己的设备数据上一定要重新寻优不能直接套用别人的参数。4. LSTM诊断模型MATLAB源码实现4.1 为什么用LSTM而不用普通BP神经网络如果只是拿特征向量做分类BP神经网络或者SVM就够了。但这里有个问题我前面构造的每一个样本本质上是2048个采样点的时序信号。这2048个点不是孤立的而是有前后依赖关系的。内圈故障时振动信号里会出现周期性的冲击脉冲这个冲击的特征不仅体现在每个点的幅值上更体现在一段时间内的变化规律上。普通BP神经网络把输入当成一个平坦的向量完全忽略了时间维度的信息。LSTM天生就是处理这种序列数据的它在每个时间步上通过输入门、遗忘门、输出门来控制信息的流动让网络自己学习哪些时间点上的信息重要哪些应该遗忘。4.2 序列数据构造与数据格式转换LSTM在MATLAB里需要的输入格式是若干个序列的cell数组每个cell里是一个numFeatures x numTimeSteps的矩阵。如果你训练数据是N个样本每个样本是1通道、2048个时间步那么cell数组的维度是Nx1每个cell内部是一个1x2048的矩阵。% 假设rawTrain是Nx2048的矩阵每行一个样本 XTrainLSTM cell(N, 1); for i 1:N XTrainLSTM{i} rawTrain(i, :); % 1x2048 end % 标签是分类变量 YTrainLSTM categorical(labelTrain);如果你有多个传感器通道比如同时采集了加速度和温度信号那numFeatures就是2每个cell内部变成2x2048的矩阵LSTM会自动融合多通道信息不需要额外拼接。4.3 网络结构与训练选项设置LSTM网络结构我推荐这样一个基线设计在实际项目里能少走弯路序列输入层 - LSTM层隐藏单元数64- dropout层丢弃率0.2- 全连接层输出节点等于类别数- softmax层 - 分类层。隐藏单元数怎么选64是个不错的起点数据量大可以加到128或256但要注意过拟合。我把隐藏单元数和dropout放一起看如果训练集准确率很高但测试集上不去说明过拟合了要么加大dropout要么减小隐藏单元数。numHiddenUnits 64; numClasses 4; layers [ sequenceInputLayer(1, Normalization, zscore) lstmLayer(numHiddenUnits, OutputMode, last) dropoutLayer(0.2) fullyConnectedLayer(numClasses) softmaxLayer classificationLayer]; options trainingOptions(adam, ... MaxEpochs, 50, ... MiniBatchSize, 64, ... InitialLearnRate, 0.01, ... LearnRateSchedule, piecewise, ... LearnRateDropFactor, 0.5, ... LearnRateDropPeriod, 10, ... GradientThreshold, 1, ... Shuffle, every-epoch, ... Verbose, 1, ... Plots, training-progress); net trainNetwork(XTrainLSTM, YTrainLSTM, layers, options);训练选项里的几个参数我逐个说下。GradientThreshold设为1是为了防止梯度爆炸LSTM虽然比普通RNN稳定但序列长的时候梯度爆炸还是可能发生的。LearnRateDropFactor和LearnRateDropPeriod配合每10轮训练学习率减半这样可以先用大学习率快速下降后期用小学习率精细收敛。Shuffle设为every-epoch让每轮的mini-batch顺序都不同增强随机性。4.4 训练过程监控与过拟合判断上面代码里的Plots, training-progress会在训练时弹出实时曲线图包括准确率和损失值。训练过程中你得眼睛盯着两张曲线训练准确率和训练损失。如果训练损失在下降但下降得很慢可能是学习率太小如果损失先降后涨很可能是学习率太大在最优解附近震荡了。关键判断点出现在训练集准确率接近100%之后。如果测试集准确率远远低于训练集恭喜你过拟合了。解决办法有三个方向加dropout、加大数据量用重叠采样扩充样本、减小隐藏单元数。这三个方向优先顺序我建议先减模型复杂度再加dropout最后才想着找数据因为找数据成本最高。5. 模型对比与鲁棒性分析5.1 量化对比指标的选取两个模型都跑完之后不能光看一个总准确率就说谁好谁坏。设备故障诊断场景里我更关心的是每个类别的召回率尤其关注故障样本被误判成正常这种情况。如果一个外圈故障样本被模型判成正常现场维护人员就可能漏掉一次检修机会这是最危险的情况。所以我除了看总体准确率一定会画混淆矩阵confusion matrix。MATLAB的confusionchart函数几行代码就能画出来从混淆矩阵里可以直观看出模型在哪两个类别之间容易混淆。CWRU数据上SVM和LSTM最容易混淆的往往是内圈故障和滚动体故障因为这两种故障产生的振动信号在某些频率段上确实有重叠。5.2 不同工况与噪声条件下的表现实验室数据和现场数据的差距往往比模型选型带来的差距还要大。我在做鲁棒性测试时会人为在测试信号里叠加不同信噪比的高斯白噪声看模型准确率随噪声水平的变化曲线。实测数据显示SVM在特征提取阶段做了平滑处理对中低水平噪声有天然的抑制作用所以噪声加到一定程度之前SVM的准确率下降得比LSTM慢。但噪声再大一些特征被污染SVM的准确率会急剧下降。LSTM因为直接吃原始数据对噪声的容忍度更高因为它可以在训练过程中自己学会抑制噪声干扰。这个结论给我的启示是如果现场环境很嘈杂优先选LSTM如果现场信号相对干净SVM更轻量高效。5.3 训练时间与部署成本的现实考量还有一个不可忽视的维度是计算资源。我的实验环境是普通台式机i7处理器16GB内存没有独显纯CPU跑。训练一个SVM模型特征提取加交叉验证总共不到2分钟训练一个LSTM50轮跑下来大概8到10分钟看数据量和隐藏单元数。如果数据量再翻几倍或者隐藏单元加到256LSTM的训练时间会飙升到半小时以上。部署阶段差距更大。SVM模型本质上就是一组支持向量和权重系数保存下来几个KB预测一个样本只需要计算一次核函数速度是毫秒级的适合部署到PLC或嵌入式设备上。LSTM模型结构更复杂参数数量多几个量级虽然在CPU上也能跑但在嵌入式环境里就比较吃力了。所以如果是做在线实时诊断SVM往往是更务实的选择。6. 常见问题与调试实录6.1 读取mat文件时数据维度不符CWRU数据集中不同mat文件里的数据结构有点差别有些文件是结构体有些直接就是数组。如果在load之后发现size跟你预期不一致别慌先用whos命令查看工作区变量再用fieldnames查看结构体字段确认到底哪个字段是你要的信号数据。我曾经在一个文件上栽过跟头发现字段名不是DE而是drive_end直接报错找不到字段排查了好久。建议写一个统一的数据加载函数兼容两种格式这样后面换数据集就不会再出问题。6.2 LSTM训练不收敛症状是损失函数一直在高位抖动准确率保持在25%左右四分类随机水平上不去。这个问题我在第一次跑LSTM的时候遇到过原因出在数据没有做z-score标准化原始振动信号幅值范围很大LSTM的输入门和遗忘门的sigmoid激活一路饱和梯度根本传不回去。解决办法就是在sequenceInputLayer里设置Normalization, zscore或者在预处理阶段手动标准化一轮训练就收敛了。另一个可能的原因是学习率太大。如果损失曲线像过山车一样上下乱跳把InitialLearnRate从0.01降到0.001大概率能稳住。6.3 SVM训练时间过长卡在交叉验证如果特征维度很高且样本量很大fitcecoc默认会用全部训练数据做K折交叉验证时间会很难看。这时候可以先减小K值比如从5折改成3折先把参数方向摸出来再在最优参数附近用全量数据训练。还有一个技巧是使用OptimizeHyperparameters自动优化时把MaxObjectiveEvaluations设小一点比如10到20次别让它跑满30次不然等着吃晚饭吧。6.4 模型精度总差那么一两个点这是最让人抓狂的情况。我踩过最深的坑是特征提取和模型训练之间的数据顺序错位。比如分帧的时候用了重叠采样你做了数据增强但标签没跟着扩充特征和标签一对不上模型精度自然上不去。排查方法很简单随机打印第100个样本的特征向量和对应标签人工看一眼类别是否匹配得当。另外一个很容易被忽略的问题是测试集参与过归一化。有些人图省事先把全量数据zscore一遍再划分训练测试集这样测试集的信息已经泄露到训练集了看起来测试准确率很高但一到现场真实数据上就拉胯。正确做法必须像我前面代码里那样先划分再只基于训练集计算归一化参数。最后说点实在的从我个人实操经验来看在MATLAB里用LSTM和SVM做设备故障诊断最大的价值不是跑通一个demo而是通过对比理解两类模型的本质区别。我再强调一个原则SVM的性能上限由特征工程决定LSTM的性能上限由数据质量和样本量决定。所以当你遇到模型效果不好的时候先别急着换网络结构先回头审视你的特征提取得够不够好、数据样本够不够多、标签有没有标错。如果日后要把这套方案做成更完整的系统可以考虑把两个模型做集成比如对初判结果置信度低的样本再交给另一个模型复核。我试过用LSTM的概率输出作为SVM的附加特征在小样本情况下有一定提升感兴趣的可以自己实验一下。目前项目代码已经整理成脚本和函数按模块拆好喂入自己的CSV或mat数据就能跑后续在做实时数据流的版本有结果再跟大家分享。本文还有配套的精品资源点击获取