主要内容

基于三轴振动数据的工业机械异常检测

这个例子展示了如何使用机器学习和深度学习来检测振动数据中的异常。该示例使用从一台工业机器收集的振动数据。首先,您使用Diagnostic Feature Designer App从正常操作对应的原始测量中提取特征。使用所选的特征来训练考虑中的每个模型。然后使用每个训练过的模型来识别机器是否在正常状态下运行。

数据集

数据集包含工业机器的3轴振动测量。在定期维护之前和之后立即收集数据。定期维修后收集的数据被认为代表机器的正常运行状态。维护前的数据可以表示正常情况,也可以表示异常情况。每个轴的数据存储在单独的列中,每个文件包含7000个测量值。从MathWorks支持文件站点加载数据,并绘制正常和异常数据集的金宝app示例。

url =“https://ssd.mathworks.com/金宝appsupportfiles/predmaint/anomalyDetection3axisVibration/v1/vibrationData.zip”;websave (“vibrationData.zip”url);解压缩(“vibrationData.zip”);负载(“MachineData.mat”) trainData
trainData =40×4表ch1 ch2 ch3标签  ________________ ________________ ________________ ______ { 70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}在{70000×1双}{70000×1双}{70000×1双}之前⋮

为了更好地理解数据,可以在维护前后对其进行可视化。为图选择集合的第四个成员,您可以看到两种条件的数据看起来明显不同。

enmember = 4;helperPlotVibrationData (trainData ensMember)

提取特征与诊断特征设计应用程序

使用原始数据来训练机器学习模型不是很有效。的诊断功能设计器App让您可以交互式地探索和预处理数据,提取时间和频域特征,然后对特征进行排序,以确定哪个最有效。然后可以导出一个函数,以编程方式从数据集中提取所选的特征。打开DFD app:

diagnosticFeatureDesigner

单击New Session按钮,选择trainData作为源,然后进行设置标签作为一个条件变量.的标签变量为相应的数据标识机器的状态。

您可以使用诊断功能设计器对功能进行迭代并对它们进行排序。为所有生成的特征创建一个直方图视图,以可视化从ch1中提取的各种特征的标签分开的分布。请注意,下面显示的直方图来自一个更大的数据集,因此分离更容易可视化。到目前为止使用的数据集是原始数据的子集,因此您的结果可能不同。

为每个渠道使用排名靠前的四个功能。

  • ch1:峰值因子,峰度,均方根,性病

  • ch2:平均值,均方根,偏度,标准

  • ch3:峰值因子,SINAD,信噪比,THD

导出一个函数,从诊断功能设计器应用程序生成功能,并保存其名称generateFeatures.该函数从命令行中提取整个数据集中每个通道的前4个相关特征。

trainFeatures = generateFeatures(trainData);头(trainFeatures)
ans =表8×13标签ch1_stats / Col1_CrestFactor ch1_stats / Col1_Kurtosis ch1_stats / Col1_RMS ch1_stats / Col1_Std ch2_stats / Col1_Mean ch2_stats / Col1_RMS ch2_stats / Col1_Skewness ch2_stats / Col1_Std ch3_stats / Col1_CrestFactor ch3_stats / Col1_SINAD ch3_stats / Col1_SNR ch3_stats / Col1_THD  ______ __________________________ _______________________ __________________ __________________ ___________________ __________________ _______________________ __________________ __________________________ ______________________________________ __________________前2.2811 1.8087 2.3074 2.3071 -0.032332 0.64962 11.973 -15.945 -15.886 -2.732前2.3276 1.8379 2.2613 2.261 -0.03331 0.59458 5.59365 10.284 -15.984 -15.927 -2.7507前2.3276 1.8626 2.2613 2.2612 -0.012052 0.48248 4.3638 0.48233 8.9125 -15.858 -15.798 -2.7104前2.8781 2.1986 1.8288 1.8285 -0.005049 0.34984 2.3324 0.34981 11.795 -16.191 -16.14 -3.0683前2.8911 2.06 1.8205 1.8203 -0.0018988 0.27366 1.7661 0.2736511.395 -15.947 -15.893 -3.1126前2.8979 2.1204 1.8163 1.8162 -0.0044174 0.3674 2.8969 0.36737 11.685 -15.963 -15.908 -2.9761前2.9494 1.92 1.7846 1.7844 -0.0067284 0.36262 4.1308 0.36256 12.396 -15.999 -15.942 -2.8281前2.5106 1.6774 1.7513 1.7511 -0.0089548 0.32348 3.7691 0.32335 8.8808 -15.79 -15.732 -2.9532

异常检测的列车模型

到目前为止使用的数据集只是一个更大数据集的一个小子集,以说明特征提取和选择的过程。在所有可用数据上训练你的算法会产生最好的性能。为此,加载之前从17,642个信号的更大数据集中提取的12个特征。

负载(“FeatureEntire.mat”)头(featureAll)
ans =表8×13标签ch1_stats / Col1_CrestFactor ch1_stats / Col1_Kurtosis ch1_stats / Col1_RMS ch1_stats / Col1_Std ch2_stats / Col1_Mean ch2_stats / Col1_RMS ch2_stats / Col1_Skewness ch2_stats / Col1_Std ch3_stats / Col1_CrestFactor ch3_stats / Col1_SINAD ch3_stats / Col1_SNR ch3_stats / Col1_THD  ______ __________________________ _______________________ __________________ __________________ ___________________ __________________ _______________________ __________________ __________________________ ______________________________________ __________________前2.3683 1.927 2.2225 2.2225 -0.015149 0.62512 4.4476 -4.9977 -4.4608前2.402 1.9206 2.1807 2.1803 -0.018269 0.56773 3.9985 0.56744 8.7481 -12.532 -12.419 -3.2353前2.4157 1.9523 2.1789 2.1788 -0.0063652 0.45646 2.8886 0.45642 8.3111 -12.977 -12.869 -2.9591前2.4595 1.8205 2.14 2.1401 0.0017307 0.41418 -13.566 -13.468 -2.7944前2.2502 1.8609 2.3391 2.339 -0.0081829 0.3694 3.3498 0.369316.8134 -13.33 -13.225 -2.7182前2.4211 2.2479 2.1286 2.1285 0.011139 0.36638 1.8602 0.36621 7.4712 -13.324 -13.226 -3.0313前3.3111 4.0304 1.5896 1.5896 -0.0080759 0.47218 2.1132 0.47211 8.2412 -13.85 -13.758 -2.7822前2.2655 2.0656 2.3233 2.3233 -0.0049447 0.37829 2.4936 0.37827 7.6947 -13.781 -13.683 -2.5601

使用cvpartition将数据划分为一个训练集和一个独立的测试集。helperExtractLabeledDataHelper函数用于查找标签'对应的所有特征featureTrain变量。

rng (0)%设置可再现性idx = cvpartition(featureAll.label,“坚持”, 0.1);featureTrain = featureAll(idx.)培训:);featureTest = featureAll(idx。测试:);

对于每个模型,只对维护后的数据进行训练,假设数据正常。只提取维护后的数据featureTrain

trueAnomaliesTest = featureTest.label;featurennormal = featureTrain(featureTrain.label==“后”:);

用一类支持向量机检测异常

金宝app支持向量机是强大的分类器,其变体只训练一个类,对正常数据建模。这个模型可以很好地识别与正常数据“相距甚远”的异常。选择正常情况下的训练数据,用fitcsvm函数。

mdlSVM = fitcsvm(featunormal,“标签”“标准化”,真的,“OutlierFraction”, 0);

使用包含正常和异常数据的测试数据验证训练后的支持向量机模型。

featureTestNoLabels = featureTest(:, 2:end);[~,scoreSVM] = predict(mdlSVM,featureTestNoLabels);isanomalySVM = scoreSVM<0;predSVM = categorical(isanomalySVM, [1,0], [“异常”“正常”]);trueAnomaliesTest = renamecats(trueAnomaliesTest,[“后”“之前”]、[“正常”“异常”]);图;confusichart (trueAnomaliesTest, predSVM, Title=《一类支持向量机异常检测》归一化=“row-normalized”);

从混淆矩阵可以看出,单类支持向量机做得很好。只有0.3%的异常样本被错误地归类为正常,大约0.9%的正常数据被错误地归类为异常。

使用隔离林检测异常

隔离森林的决策树将每个观察结果隔离在一片叶子中。一个样本要经过多少次决策才能到达它的叶子,这是将它从其他样本中分离出来的复杂程度的衡量标准。特定样本的树的平均深度被用作它们的异常分数,并由iforest.同样,只在正常数据上训练隔离森林模型。

[mdlIF,~,scoreTrainIF] = forest(featunormal {:,2:13},“ContaminationFraction”, 0.09);

使用包含正常数据和异常数据的测试数据验证训练的隔离林模型。通过使用混淆图表来可视化此模型的性能。

[isanomalyIF,scoreTestIF] = isanomaly(mdlIF,featureTestNoLabels.Variables);predIF = categorical(isanomalyIF, [1,0], [“异常”“正常”]);图;confusionchart (trueAnomaliesTest predIF, Title ="使用隔离林进行异常检测"归一化=“row-normalized”);

在这个数据上,隔离森林没有单类SVM做得好,但在这个几乎平衡的数据集中有这么多“异常”,这不是典型的异常检测。这是因为训练数据中只包含正常数据,而测试数据中包含约30%的异常数据。这表明,当异常数据与正常数据的分布更接近时,隔离森林模型更适合。

使用LSTM自动编码器网络检测异常

自动编码器是一种神经网络,它学习未标记数据的压缩表示。LSTM自编码器是该网络的一种变体,它可以学习序列数据的压缩表示。该LSTM自编码器将仅使用正常数据进行训练,训练后的网络将用于识别何时遇到不像正常数据的序列。

featresafter = helperExtractLabeledData(featureTrain,...“后”);

然后,构建biLSTM自编码器网络并设置训练选项。

featureDimension = 1;定义biLSTM网络层layers = [sequenceInputLayer(featureDimension, featureDimension)“名字”“在”) bilstmLayer (16“名字”“bilstm1”) reluLayer (“名字”“relu1”) bilstmLayer (32,“名字”“bilstm2”) reluLayer (“名字”“relu2”) bilstmLayer (16“名字”“bilstm3”) reluLayer (“名字”“relu3”) fullyConnectedLayer (featureDimension“名字”“俱乐部”) regressionLayer (“名字”“出”));%设置培训选项选项= trainingOptions(“亚当”...“阴谋”“训练进步”...“MiniBatchSize”, 500,...“MaxEpochs”, 200);

MaxEpochs“培训选项”设置为“200”。为了获得更高的验证精度,可以将该参数设置为更大的值。然而,这可能会导致网络过拟合。现在训练模型。

net = trainNetwork(featuresAfter, featuresAfter, layers, options);
单CPU训练。|========================================================================================| | 时代| |迭代时间| Mini-batch | Mini-batch |基地学习  | | | | ( hh: mm: ss) | RMSE | |率损失  | |========================================================================================| | 1 | 1 | 00:00:04 | 5.81 | 16.9 | 0.0010 | | 3 | 50 | 00:00:16 | 5.43 | 14.8 | 0.0010 | | 100 | | 00:00:28 | 3.99 | 7.9 | 0.0010 | | 150 | | 00:00:39 | 4.27 | 9.1 | 0.0010 | | 200 | |00:00:51 | 3.48 | 6.1 | 0.0010 | | 250 | | 00:01:03 | 3.97 | 7.9 | 0.0010 | | 300 | | 00:01:15 | 3.17 | 5.0 | 0.0010 | | 350 | | 00:01:27 | 3.72 | 6.9 | 0.0010 | | 400 | | 00:01:39 | 2.89 | 4.2 | 0.0010 | | 23 | 450 | 00:01:51 | 3.49 | 6.1 | 0.0010 | | 25 | 500 | 00:02:03 | 2.67 | 3.6 | 0.0010 | | 550 | | 28 00:02:15 | 3.31 | 5.5 | 0.0010 | | 600 | | 00:02:27 | 2.49 | 3.1 | 0.0010 | | 33 | 650 | 00:02:39 | 3.14 | 4.9 | 0.0010 | | | 700 | 00:02:51 | 2.29 | 2.6 | 0.0010 | | |750 | 00:03:03 | 2.96 | 4.4 | 0.0010 | | 800 | | 00:03:16 | 2.12 | 2.2 | 0.0010 | | 43 | 850 | 00:03:28 | 2.81 | 4.0 | 0.0010 | | 900 | | 00:03:40 | 1.98 | 2.0 | 0.0010 | | 48 | 950 | 00:03:51 | 2.71 | 3.7 | 0.0010 | | 1000 | | 00:04:04 | 1.89 | 1.8 | 0.0010 | | 53 | 1050 | 00:04:16 | 2.62 | 3.4 | 0.0010 | | 55 | 1100 | 00:04:28 | 1.81 | 1.6 | 0.0010 | | 58 | 1150 | 00:04:41 | 2.54 | 3.2 | 0.0010 | | 1200 | | 00:04:53 | 1.74 | 1.5 | 0.0010 | 63 | 1250 | | 00:05:06 | 2.47 | 3.0 |0.0010 | | 65 | 1300 | 00:05:18 | 1.66 | 1.4 | 0.0010 | 68 | 1350 | | 00:05:31 | 2.38 | 2.8 | 0.0010 | 70 | 1400 | | 00:05:43 | 1.53 | 1.2 | 0.0010 | 73 | 1450 | | 00:05:55 | 2.28 | 2.6 | 0.0010 | 75 | 1500 | | 00:06:08 | 1.44 | 1.0 | 0.0010 | 78 | 1550 | | 00:06:20 | 2.20 | 2.4 | 0.0010 | 80 | 1600 | | 00:06:33 | 1.36 | 0.9 | 0.0010 | 83 | 1650 | | 00:06:46 | 2.14 | 2.3 | 0.0010 | 85 | 1700 | | 00:07:00 | 1.29 | 0.8 | 0.0010 | 88 | 1750 | | 00:07:14 | 2.07 | 2.1 | 0.0010 | | 90 | 1800 |00:07:28 | 1.22 | 0.8 | 0.0010 | 93 | 1850 | | 00:07:42 | 2.01 | 2.0 | 0.0010 | 95 | 1900 | | 00:07:56 | 1.16 | 0.7 | 0.0010 | 98 | 1950 | | 00:08:10 | 1.95 | 1.9 | 0.0010 | 100 | 2000 | | 00:08:24 | 1.10 | 0.6 | 0.0010 | 103 | 2050 | | 00:08:38 | 1.90 | 1.8 | 0.0010 | 105 | 2100 | | 00:08:52 | 1.05 | 0.5 | 0.0010 | 108 | 2150 | | 00:09:06 | 1.86 | 1.7 | 0.0010 | 110 | 2200 | | 00:09:20 | 1.00 | 0.5 | 0.0010 | 113 | 2250 | | 00:09:34 | 1.82 | 1.6 | 0.0010 | 115 | 2300 | | 00:09:48 | 0.96 | 0.5 |0.0010 | | 118 | 2350 | 00:10:02 | 1.78 | 1.6 | 0.0010 | | 120 | 2400 | 00:10:16 | 0.91 | 0.4 | 0.0010 | | 123 | 2450 | 00:10:30 | 1.74 | 1.5 | 0.0010 | | 125 | 2500 | 00:10:44 | 0.88 | 0.4 | 0.0010 | | 128 | 2550 | 00:10:58 | 1.71 | 1.5 | 0.0010 | | 130 | 2600 | 00:11:12 | 0.84 | 0.4 | 0.0010 | | 133 | 2650 | 00:11:26 | 1.68 | 1.4 | 0.0010 | | 135 | 2700 | 00:11:40 | 0.81 | 0.3 | 0.0010 | | 138 | 2750 | 00:11:54 | 1.65 | 1.4 | 0.0010 | | 140 | 2800 | 00:12:08 | 0.78 | 0.3 | 0.0010 | | 143 | 2850 | 00:12:22 | 1.62 | 1.3 | 0.0010 | | 145 | 2900 | 00:12:36 | 0.76 | 0.3 | 0.0010 | | 148 | 2950 | 00:12:49 | 1.59 | 1.3 | 0.0010 | | 150 | 3000 | 00:13:02 | 0.73 | 0.3 | 0.0010 | | 153 | 3050 | 00:13:15 | 1.57 | 1.2 | 0.0010 | | 155 | 3100 | 00:13:29 | 0.71 | 0.3 | 0.0010 | | 158 | 3150 | 00:13:42 | 1.55 | 1.2 | 0.0010 | | 160 | 3200 | 00:13:55 | 0.68 | 0.2 | 0.0010 | | 163 | 3250 | 00:14:09 | 1.52 | 1.2 | 0.0010 | | 165 | 3300 | 00:14:22 | 0.66 | 0.2 | 0.0010 | | 168 | 3350 | 00:14:36 | 1.50 | 1.1 | 0.0010 | | 170 | 3400 | 00:14:50 | 0.64 | 0.2 | 0.0010 | | 173 | 3450 | 00:15:03 | 1.48 | 1.1 | 0.0010 | | 175 | 3500 | 00:15:16 | 0.62 | 0.2 | 0.0010 | | 178 | 3550 | 00:15:30 | 1.46 | 1.1 | 0.0010 | | 180 | 3600 | 00:15:43 | 0.60 | 0.2 | 0.0010 | | 183 | 3650 | 00:15:56 | 1.44 | 1.0 | 0.0010 | | 185 | 3700 | 00:16:10 | 0.59 | 0.2 | 0.0010 | | 188 | 3750 | 00:16:23 | 1.42 | 1.0 | 0.0010 | | 190 | 3800 | 00:16:37 | 0.57 | 0.2 | 0.0010 | | 193 | 3850 | 00:16:50 | 1.40 | 1.0 | 0.0010 | | 195 | 3900 | 00:17:04 | 0.55 | 0.2 | 0.0010 | | 198 | 3950 | 00:17:17 | 1.38 | 1.0 | 0.0010 | | 200 | 4000 | 00:17:31 | 0.54 | 0.1 | 0.0010 | |========================================================================================| Training finished: Reached final iteration.

在验证数据上可视化模型行为和错误

从异常和正常条件中提取并可视化一个样本。请注意,下面的图表比较了12个特征中每个特征值的误差(在x轴上表示)。在这个样本中,特征10、11和12对于异常输入重构得不好,因此有很高的误差值。该模型使用这个误差值来识别异常。

testNormal = {featureTest(1200, 2:end).Variables};testAnomaly = {featureTest(200, 2:end).Variables};预测两者的解码信号decodedNormal =预测(net,testNormal);decodedAnomaly =预测(net,testAnomaly);%可视化helpvisualizemodelbehavior (testNormal, testAnomaly, decodedNormal, decodedAnomaly)

提取正常和异常数据的特征。从图中可以看出,异常数据的重构误差明显高于正常数据。这是有道理的,因为自编码器是在正常数据上训练的,所以它会更好地重建相似的信号。

维护前提取数据XTestBefore = helperExtractLabeledData(featureTest,“之前”);维修前预测输出,计算误差yHatBefore = predict(net, XTestBefore);errorBefore = helperCalculateError(XTestBefore, yHatBefore);维护后提取数据XTestAfter = helperExtractLabeledData(特征测试,“后”);维修后预测输出,计算误差yHatAfter = predict(net, XTestAfter);errorAfter = helperCalculateError(XTestAfter, yHatAfter);helperVisualizeError (errorBefore errorAfter);

识别异常

计算完整验证数据上的误差。

XTestAll = helperExtractLabeledData(特征测试,“所有”);yHatAll =预测(net, XTestAll);errorAll = helperCalculateError(XTestAll, yHatAll);

将异常定义为所有观测值的重建误差大于平均值0.5倍的点。这个阈值是通过实验确定的,可以根据需要进行更改。

脱粒= 0.5;exceptions = errorAll > thresh*mean(errorAll);helpervisualizeanomaly(异常,errorAll, featureTest);

金宝app支持功能

函数E = helperCalculateError(X, Y)% HELPERCALCULATEERROR函数计算%输入X, YE = 0(长度(X),1);i = 1:长度E (X)我:=√(总和(X (Y{我}-{我})^ 2));结束结束函数helperVisualizeError (errorBefore errorAfter)创建一个图来可视化检测错误%图(“颜色”“W”) tiledlayout (“流”nexttile plot(1:length(errorBefore), errorBefore,“线宽”1.5),网格标题([“维护”...sprintf (“平均误差:%.2f\n”, mean(errorBefore)))“观察”) ylabel (“重建错误”) ylim([0 15]) nexttile plot(1:length(errorAfter), errorAfter,“线宽”1.5),网格、标题([“维修之后”...sprintf (“平均误差:%.2f\n”, mean(errorAfter)))“观察”) ylabel (“重建错误”) ylim([0 15])结束函数helppervisualizeanomaly(异常,errorAll, featureTest)% helpervisualizeanomaly创建检测到的异常图anomalyIdx = find(异常);anomalyErr = errorAll(异常);predAE = categorical(异常,[1,0],[“异常”“正常”]);trueAE = renamecats(featureTest.label,[“之前”“后”]、[“异常”“正常”]);(find(trueAE == predAE))/ (predAE)*100;图;T =平铺布局(“流”);标题(t)“测试精度:”+ round(mean(acc),2) +“%”);nexttile举行plot(anomalyIdx, anomalyErr)“x”)举行ylabel (“重建错误”)包含(“观察”)传说(“错误”“候选人异常”nexttile混淆图(trueAE,predAE)结束函数helperVisualizeModelBehavior(normalData, abnormalData, decodedNorm, decodedAbNorm)可视化样本验证数据上的模型行为图(“颜色”“W”) tiledlayout (“流”nexttile()等待colororder (“默认”) yyaxis情节(normalData{}):情节(decodedNorm {:},”:““线宽”, 1.5)标题(“正常输入”网格)ylabel (“特征值”) yyaxis正确的stem(abs(normalData{:} - decodedNorm{:})) ylim([0 2]) ylabel(“错误”)传说([“输入”“解码”“错误”),“位置”“西南”nexttile()等待yyaxis情节(abnormalData{}):情节(decodedAbNorm {:},”:““线宽”, 1.5)标题(“非正常输入”网格)ylabel (“特征值”) yyaxis正确的stem(abs(abnormalData{:} - decodedAbNorm{:})) ylim([0 2]) ylabel(“错误”)传说([“输入”“解码”“错误”),“位置”“西南”结束函数X = helperExtractLabeledData(特征表,标签)从操作前或操作后提取数据%条件和重新格式化,以支持输入到自动编码器网络金宝app%选择标签为“之后”的数据如果标签= =“所有”Xtemp = featureTable(:, 2:end).Variables;其他的tF = featureTable。标签==标签;Xtemp = featureTable(tF, 2:end).Variables;结束将数据排列到单元格中X = cell(length(Xtemp),1);i = 1:长度(Xtemp) X{i,:} = Xtemp(i,:);结束结束