Main Content

이 번역 페이지는 최신 내용을 담고 있지 않습니다. 최신 내용을 영문으로 보려면 여기를 클릭하십시오.

3축 진동 데이터를 사용하여 산업 기계의 이상 감지

이 예제에서는 머신러닝과 딥러닝을 사용하여 진동 데이터의 이상을 감지하는 방법을 보여줍니다. 이 예제에서는 산업 기계의 진동 데이터를 사용합니다. 먼저 진단 특징 디자이너 앱을 사용하여 정상 작동에 해당하는 원시 측정값에서 특징을 추출합니다. 선택한 특징을 사용하여 이상 감지에 대해 3개의 다른 모델(단일 클래스 SVM, 격리 포레스트, LSTM 오토인코더)을 훈련시킵니다. 그런 다음 각각의 훈련된 모델을 사용하여 기계가 정상적으로 작동하는지 여부를 식별합니다.

데이터 세트

데이터 세트에는 산업 기계의 3축 진동 측정값이 포함되어 있습니다. 데이터는 예정된 유지관리 직전과 직후에 모두 수집됩니다. 예정된 유지관리 후에 수집된 데이터는 기계의 정상 작동 상태를 나타내는 것으로 가정합니다. 유지관리를 수행하기 전의 데이터는 정상 상태나 이상 상태를 나타낼 수 있습니다. 각 축의 데이터는 개별 열에 저장됩니다. 데이터 세트를 저장하고 압축을 푼 다음 훈련 데이터를 불러옵니다.

url = 'https://ssd.mathworks.com/supportfiles/predmaint/anomalyDetection3axisVibration/v1/vibrationData.zip';
websave('vibrationData.zip',url);
unzip('vibrationData.zip');
load("MachineData.mat")
trainData
trainData=40×4 table
          ch1                 ch2                 ch3           label 
    ________________    ________________    ________________    ______

    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
    {70000×1 double}    {70000×1 double}    {70000×1 double}    Before
      ⋮

데이터를 더 잘 이해할 수 있도록 유지관리 전과 후의 데이터를 시각화합니다. 앙상블의 네 번째 멤버에 대한 진동 데이터를 플로팅하고 두 상태에 대한 데이터가 다르게 나타나는 것을 확인합니다.

ensMember = 4;
helperPlotVibrationData(trainData, ensMember)

진단 특징 디자이너 앱을 사용하여 특징 추출하기

원시 데이터는 상관 관계가 있고 잡음이 있을 수 있기 때문에 머신러닝 모델을 훈련시키는 데 원시 데이터를 사용하는 것은 효율적이지 않습니다. Diagnostic Feature Designer 앱을 사용하면 대화형 방식으로 데이터를 탐색 및 전처리하고 시간 영역과 주파수 영역의 특징을 추출한 다음 특징에 순위를 지정하여 결함이나 이상이 있는 시스템 진단에 가장 효과적인 특징을 결정할 수 있습니다. 그런 다음 프로그래밍 방식으로 데이터 세트에서 선택한 특징을 추출하는 함수를 내보낼 수 있습니다. 명령 프롬프트에 diagnosticFeatureDesigner를 입력하여 진단 특징 디자이너를 엽니다. 진단 특징 디자이너를 사용하는 방법에 대한 튜토리얼은 예측 정비 알고리즘을 위한 상태 지표 설계하기 항목을 참조하십시오.

새 세션 버튼을 클릭하고 소스로 trainData를 선택한 다음 label상태 변수로 설정합니다. label 변수는 해당하는 데이터에 대한 기계 상태를 식별합니다.

진단 특징 디자이너를 사용하여 특징을 반복하고 순위를 지정할 수 있습니다. 앱은 생성된 모든 특징에 대한 히스토그램 보기를 만들어 각 레이블의 분포를 시각화합니다. 예를 들어 다음 히스토그램은 ch1에서 추출한 다양한 특징의 분포를 보여줍니다. 이러한 히스토그램은 레이블 그룹 분리를 더 잘 설명하기 위해 이 예제에서 사용하는 데이터 세트보다 훨씬 큰 데이터 세트에서 도출됩니다. 현재는 더 작은 데이터 세트를 사용하고 있기 때문에 결과가 다르게 보일 수 있습니다.

각 채널에 대해 상위 4개의 순위 특징을 사용합니다.

  • ch1 : 파고율, 첨도, RMS, 표준편차

  • ch2 : 평균, RMS, 왜도, 표준편차

  • ch3 : 파고율, SINAD, SNR, THD

진단 특징 디자이너 앱에서 특징을 생성하는 함수를 내보내고 이름 generateFeatures로 저장합니다. 이 함수는 명령줄에서 전체 데이터 세트의 각 채널에서 상위 4개의 관련 특징을 추출합니다.

trainFeatures = generateFeatures(trainData);
head(trainFeatures)
    label     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
    ______    __________________________    _______________________    __________________    __________________    ___________________    __________________    _______________________    __________________    __________________________    ____________________    __________________    __________________

    Before              2.2811                      1.8087                   2.3074                2.3071               -0.032332              0.64962                   4.523                  0.64882                    11.973                    -15.945                -15.886                -2.732      
    Before              2.3276                      1.8379                   2.2613                 2.261                -0.03331              0.59458                   5.548                  0.59365                    10.284                    -15.984                -15.927               -2.7507      
    Before              2.3276                      1.8626                   2.2613                2.2612               -0.012052              0.48248                  4.3638                  0.48233                    8.9125                    -15.858                -15.798               -2.7104      
    Before              2.8781                      2.1986                   1.8288                1.8285               -0.005049              0.34984                  2.3324                  0.34981                    11.795                    -16.191                 -16.14               -3.0683      
    Before              2.8911                        2.06                   1.8205                1.8203              -0.0018988              0.27366                  1.7661                  0.27365                    11.395                    -15.947                -15.893               -3.1126      
    Before              2.8979                      2.1204                   1.8163                1.8162              -0.0044174               0.3674                  2.8969                  0.36737                    11.685                    -15.963                -15.908               -2.9761      
    Before              2.9494                        1.92                   1.7846                1.7844              -0.0067284              0.36262                  4.1308                  0.36256                    12.396                    -15.999                -15.942               -2.8281      
    Before              2.5106                      1.6774                   1.7513                1.7511              -0.0089548              0.32348                  3.7691                  0.32335                    8.8808                     -15.79                -15.732               -2.9532      

훈련을 위한 전체 데이터 세트 준비하기

지금까지 사용한 데이터 세트는 특징을 추출하고 선택하는 과정을 설명하기 위한 것으로 훨씬 더 큰 데이터 세트의 일부에 불과합니다. 사용 가능한 모든 데이터로 알고리즘을 훈련시키면 최상의 성과를 얻을 수 있습니다. 이를 위해, 앞에서 추출한 것과 동일한 12개의 특징을 17,642개 신호로 이루어진 더 큰 데이터 세트에서 불러옵니다.

load("FeatureEntire.mat")
head(featureAll)
    label     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
    ______    __________________________    _______________________    __________________    __________________    ___________________    __________________    _______________________    __________________    __________________________    ____________________    __________________    __________________

    Before              2.3683                       1.927                   2.2225                2.2225               -0.015149              0.62512                  4.2931                  0.62495                    5.6569                    -5.4476                -4.9977               -4.4608      
    Before               2.402                      1.9206                   2.1807                2.1803               -0.018269              0.56773                  3.9985                  0.56744                    8.7481                    -12.532                -12.419               -3.2353      
    Before              2.4157                      1.9523                   2.1789                2.1788              -0.0063652              0.45646                  2.8886                  0.45642                    8.3111                    -12.977                -12.869               -2.9591      
    Before              2.4595                      1.8205                     2.14                2.1401               0.0017307              0.41418                  2.0635                  0.41418                    7.2318                    -13.566                -13.468               -2.7944      
    Before              2.2502                      1.8609                   2.3391                 2.339              -0.0081829               0.3694                  3.3498                  0.36931                    6.8134                     -13.33                -13.225               -2.7182      
    Before              2.4211                      2.2479                   2.1286                2.1285                0.011139              0.36638                  1.8602                  0.36621                    7.4712                    -13.324                -13.226               -3.0313      
    Before              3.3111                      4.0304                   1.5896                1.5896              -0.0080759              0.47218                  2.1132                  0.47211                    8.2412                     -13.85                -13.758               -2.7822      
    Before              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을 사용하여 데이터를 훈련 세트와 독립적인 테스트 세트로 분할합니다. helperExtractLabeledData 헬퍼 함수를 사용하여 featureTrain 변수에서 레이블 'After'에 해당하는 모든 특징을 찾습니다.

rng(0) % set for reproducibility
idx = cvpartition(featureAll.label, 'holdout', 0.1);
featureTrain = featureAll(idx.training, :);
featureTest = featureAll(idx.test, :);

정상인 것으로 간주되는 유지관리 이후의 데이터에 대해서만 각 모델을 훈련합니다. featureTrain에서 이 데이터만 추출합니다.

trueAnomaliesTest = featureTest.label;
featureNormal = featureTrain(featureTrain.label=='After', :);

단일 클래스 SVM을 사용하여 이상 감지하기

서포트 벡터 머신은 강력한 분류기로, 여기서는 정상 데이터에 대해서만 훈련하도록 변형하여 사용합니다. 이 모델은 정상 데이터와 "거리가 먼" 이상을 식별하는 데 매우 효과적입니다. fitcsvm 함수와 정상 상태 데이터를 사용하여 단일 클래스 SVM 모델을 훈련시킵니다.

mdlSVM = fitcsvm(featureNormal, 'label', 'Standardize', true, 'OutlierFraction', 0);

정상 데이터와 이상 데이터가 모두 포함된 테스트 데이터를 사용하여 훈련된 SVM 모델을 검증합니다.

featureTestNoLabels = featureTest(:, 2:end);
[~,scoreSVM] = predict(mdlSVM,featureTestNoLabels);
isanomalySVM = scoreSVM<0;
predSVM = categorical(isanomalySVM, [1, 0], ["Anomaly", "Normal"]);
trueAnomaliesTest = renamecats(trueAnomaliesTest,["After","Before"], ["Normal","Anomaly"]);
figure;
confusionchart(trueAnomaliesTest, predSVM, Title="Anomaly Detection with One-class SVM", Normalization="row-normalized");

혼동행렬을 통해 단일 클래스 SVM이 좋은 성능을 보이는 것을 알 수 있습니다. 이상 샘플의 0.3%만 정상으로 오분류되고 정상 데이터의 약 0.9%가 이상으로 오분류되었습니다.

격리 포레스트를 사용하여 이상 감지하기

격리 포레스트의 결정 트리는 각 관측값을 리프로 격리합니다. 한 샘플이 리프에 도달하기까지 거쳐야 하는 결정의 수는 해당 샘플을 다른 샘플로부터 격리하는 것이 얼마나 어려운지 나타내는 척도입니다. 특정 샘플에 대한 트리의 평균 깊이가 이상 점수로 사용되며 iforest에 의해 반환됩니다.

정상 데이터로만 격리 포레스트 모델을 훈련시킵니다.

[mdlIF,~,scoreTrainIF] = iforest(featureNormal{:,2:13},'ContaminationFraction',0.09);

테스트 데이터를 사용하여 훈련된 격리 포레스트 모델을 검증합니다. 혼동행렬 차트를 사용하여 이 모델의 성능을 시각화합니다.

[isanomalyIF,scoreTestIF] = isanomaly(mdlIF,featureTestNoLabels.Variables);
predIF = categorical(isanomalyIF, [1, 0], ["Anomaly", "Normal"]);
figure;
confusionchart(trueAnomaliesTest,predIF,Title="Anomaly Detection with Isolation Forest",Normalization="row-normalized");

이 데이터에서 격리 포레스트는 단일 클래스 SVM만큼 성능이 좋지 않습니다. 이렇게 성능이 떨어지는 이유는 훈련 데이터에는 정상 데이터만 포함되어 있고 테스트 데이터에는 약 30%의 이상 데이터가 포함되어 있기 때문입니다. 따라서 격리 포레스트는 훈련 데이터와 테스트 데이터 둘 다 이상 데이터와 정상 데이터의 비율이 비슷한 경우에 선택하는 것이 좋습니다.

LSTM 오토인코더 신경망을 사용하여 이상 감지하기

오토인코더는 레이블이 지정되지 않은 데이터의 압축 표현을 학습하는 신경망의 한 유형입니다. LSTM 오토인코더는 이 신경망을 변형한 것으로, 시퀀스 데이터의 압축 표현을 학습할 수 있습니다. 여기에서는 정상 데이터만 사용하여 LSTM 오토인코더를 훈련시키고, 이 훈련된 신경망을 사용하여 신호가 정상으로 보이지 않는 경우를 식별합니다.

먼저 유지관리 후의 데이터에서 특징을 추출합니다.

featuresAfter = helperExtractLabeledData(featureTrain, ...
   "After");

LSTM 오토인코더 신경망을 생성하고 훈련 옵션을 설정합니다.

featureDimension = 1;

% Define biLSTM network layers
layers = [ sequenceInputLayer(featureDimension, 'Name', 'in')
   bilstmLayer(16, 'Name', 'bilstm1')
   reluLayer('Name', 'relu1')
   bilstmLayer(32, 'Name', 'bilstm2')
   reluLayer('Name', 'relu2')
   bilstmLayer(16, 'Name', 'bilstm3')
   reluLayer('Name', 'relu3')
   fullyConnectedLayer(featureDimension, 'Name', 'fc')
   regressionLayer('Name', 'out') ];

% Set Training Options
options = trainingOptions('adam', ...
   'Plots', 'training-progress', ...
   'MiniBatchSize', 500,...
   'MaxEpochs',200);

MaxEpochs 훈련 옵션 파라미터가 200으로 설정되어 있습니다. 검증 정확도를 높이려면 이 파라미터를 더 큰 숫자로 설정할 수 있습니다. 그러나 신경망에 과적합이 발생할 수 있습니다.

모델을 훈련시킵니다.

net = trainNetwork(featuresAfter, featuresAfter, layers, options);
Training on single GPU.
|========================================================================================|
|  Epoch  |  Iteration  |  Time Elapsed  |  Mini-batch  |  Mini-batch  |  Base Learning  |
|         |             |   (hh:mm:ss)   |     RMSE     |     Loss     |      Rate       |
|========================================================================================|
|       1 |           1 |       00:00:14 |         5.81 |         16.9 |          0.0010 |
|       3 |          50 |       00:00:18 |         5.43 |         14.8 |          0.0010 |
|       5 |         100 |       00:00:20 |         3.99 |          7.9 |          0.0010 |
|       8 |         150 |       00:00:23 |         4.27 |          9.1 |          0.0010 |
|      10 |         200 |       00:00:25 |         3.47 |          6.0 |          0.0010 |
|      13 |         250 |       00:00:28 |         3.97 |          7.9 |          0.0010 |
|      15 |         300 |       00:00:30 |         3.17 |          5.0 |          0.0010 |
|      18 |         350 |       00:00:33 |         3.72 |          6.9 |          0.0010 |
|      20 |         400 |       00:00:35 |         2.89 |          4.2 |          0.0010 |
|      23 |         450 |       00:00:37 |         3.49 |          6.1 |          0.0010 |
|      25 |         500 |       00:00:40 |         2.67 |          3.6 |          0.0010 |
|      28 |         550 |       00:00:42 |         3.31 |          5.5 |          0.0010 |
|      30 |         600 |       00:00:45 |         2.49 |          3.1 |          0.0010 |
|      33 |         650 |       00:00:47 |         3.14 |          4.9 |          0.0010 |
|      35 |         700 |       00:00:50 |         2.29 |          2.6 |          0.0010 |
|      38 |         750 |       00:00:52 |         2.96 |          4.4 |          0.0010 |
|      40 |         800 |       00:00:55 |         2.11 |          2.2 |          0.0010 |
|      43 |         850 |       00:00:57 |         2.82 |          4.0 |          0.0010 |
|      45 |         900 |       00:01:00 |         1.98 |          2.0 |          0.0010 |
|      48 |         950 |       00:01:02 |         2.71 |          3.7 |          0.0010 |
|      50 |        1000 |       00:01:05 |         1.89 |          1.8 |          0.0010 |
|      53 |        1050 |       00:01:07 |         2.63 |          3.5 |          0.0010 |
|      55 |        1100 |       00:01:10 |         1.81 |          1.6 |          0.0010 |
|      58 |        1150 |       00:01:12 |         2.55 |          3.3 |          0.0010 |
|      60 |        1200 |       00:01:15 |         1.74 |          1.5 |          0.0010 |
|      63 |        1250 |       00:01:17 |         2.48 |          3.1 |          0.0010 |
|      65 |        1300 |       00:01:20 |         1.67 |          1.4 |          0.0010 |
|      68 |        1350 |       00:01:22 |         2.40 |          2.9 |          0.0010 |
|      70 |        1400 |       00:01:25 |         1.54 |          1.2 |          0.0010 |
|      73 |        1450 |       00:01:27 |         2.30 |          2.6 |          0.0010 |
|      75 |        1500 |       00:01:29 |         1.45 |          1.1 |          0.0010 |
|      78 |        1550 |       00:01:32 |         2.23 |          2.5 |          0.0010 |
|      80 |        1600 |       00:01:34 |         1.37 |          0.9 |          0.0010 |
|      83 |        1650 |       00:01:37 |         2.16 |          2.3 |          0.0010 |
|      85 |        1700 |       00:01:39 |         1.30 |          0.8 |          0.0010 |
|      88 |        1750 |       00:01:42 |         2.10 |          2.2 |          0.0010 |
|      90 |        1800 |       00:01:44 |         1.23 |          0.8 |          0.0010 |
|      93 |        1850 |       00:01:47 |         2.04 |          2.1 |          0.0010 |
|      95 |        1900 |       00:01:49 |         1.17 |          0.7 |          0.0010 |
|      98 |        1950 |       00:01:52 |         1.99 |          2.0 |          0.0010 |
|     100 |        2000 |       00:01:54 |         1.11 |          0.6 |          0.0010 |
|     103 |        2050 |       00:01:57 |         1.94 |          1.9 |          0.0010 |
|     105 |        2100 |       00:01:59 |         1.06 |          0.6 |          0.0010 |
|     108 |        2150 |       00:02:02 |         1.90 |          1.8 |          0.0010 |
|     110 |        2200 |       00:02:04 |         1.01 |          0.5 |          0.0010 |
|     113 |        2250 |       00:02:06 |         1.86 |          1.7 |          0.0010 |
|     115 |        2300 |       00:02:09 |         0.97 |          0.5 |          0.0010 |
|     118 |        2350 |       00:02:11 |         1.82 |          1.7 |          0.0010 |
|     120 |        2400 |       00:02:14 |         0.93 |          0.4 |          0.0010 |
|     123 |        2450 |       00:02:16 |         1.79 |          1.6 |          0.0010 |
|     125 |        2500 |       00:02:18 |         0.90 |          0.4 |          0.0010 |
|     128 |        2550 |       00:02:21 |         1.76 |          1.6 |          0.0010 |
|     130 |        2600 |       00:02:23 |         0.87 |          0.4 |          0.0010 |
|     133 |        2650 |       00:02:25 |         1.73 |          1.5 |          0.0010 |
|     135 |        2700 |       00:02:28 |         0.84 |          0.4 |          0.0010 |
|     138 |        2750 |       00:02:30 |         1.71 |          1.5 |          0.0010 |
|     140 |        2800 |       00:02:32 |         0.81 |          0.3 |          0.0010 |
|     143 |        2850 |       00:02:35 |         1.68 |          1.4 |          0.0010 |
|     145 |        2900 |       00:02:37 |         0.78 |          0.3 |          0.0010 |
|     148 |        2950 |       00:02:40 |         1.66 |          1.4 |          0.0010 |
|     150 |        3000 |       00:02:42 |         0.76 |          0.3 |          0.0010 |
|     153 |        3050 |       00:02:44 |         1.63 |          1.3 |          0.0010 |
|     155 |        3100 |       00:02:47 |         0.74 |          0.3 |          0.0010 |
|     158 |        3150 |       00:02:49 |         1.61 |          1.3 |          0.0010 |
|     160 |        3200 |       00:02:52 |         0.72 |          0.3 |          0.0010 |
|     163 |        3250 |       00:02:54 |         1.59 |          1.3 |          0.0010 |
|     165 |        3300 |       00:02:56 |         0.69 |          0.2 |          0.0010 |
|     168 |        3350 |       00:02:59 |         1.57 |          1.2 |          0.0010 |
|     170 |        3400 |       00:03:01 |         0.68 |          0.2 |          0.0010 |
|     173 |        3450 |       00:03:03 |         1.55 |          1.2 |          0.0010 |
|     175 |        3500 |       00:03:06 |         0.66 |          0.2 |          0.0010 |
|     178 |        3550 |       00:03:08 |         1.53 |          1.2 |          0.0010 |
|     180 |        3600 |       00:03:10 |         0.64 |          0.2 |          0.0010 |
|     183 |        3650 |       00:03:13 |         1.51 |          1.1 |          0.0010 |
|     185 |        3700 |       00:03:15 |         0.62 |          0.2 |          0.0010 |
|     188 |        3750 |       00:03:18 |         1.49 |          1.1 |          0.0010 |
|     190 |        3800 |       00:03:20 |         0.61 |          0.2 |          0.0010 |
|     193 |        3850 |       00:03:22 |         1.48 |          1.1 |          0.0010 |
|     195 |        3900 |       00:03:25 |         0.59 |          0.2 |          0.0010 |
|     198 |        3950 |       00:03:27 |         1.46 |          1.1 |          0.0010 |
|     200 |        4000 |       00:03:29 |         0.58 |          0.2 |          0.0010 |
|========================================================================================|
Training finished: Max epochs completed.

검증 데이터에 대해 모델 동작 및 오차 시각화하기

이상 상태와 정상 상태에서 각각 샘플을 추출하고 시각화합니다. 다음 플롯은 12개 특징(X축에 표시됨) 각각에 대해 오토인코더 모델의 복원 오차를 보여줍니다. 복원된 특징 값은 플롯에서 "Decoded" 신호로 표시되어 있습니다. 이 샘플에서 특징 10, 11, 12는 이상 입력에 대해 제대로 복원되지 않아 높은 오차를 갖습니다. 복원 오차를 사용하여 이상을 식별할 수 있습니다.

testNormal = {featureTest(1200, 2:end).Variables};
testAnomaly = {featureTest(200, 2:end).Variables};

% Predict decoded signal for both
decodedNormal = predict(net,testNormal);
decodedAnomaly = predict(net,testAnomaly);

% Visualize
helperVisualizeModelBehavior(testNormal, testAnomaly, decodedNormal, decodedAnomaly)

모든 정상 데이터와 이상 데이터의 특징을 추출합니다. 훈련된 오토인코더 모델을 사용하여 유지관리 전과 후의 데이터에서 대해 선택된 특징 12개를 예측합니다. 다음 플롯은 12개 특징에 대한 RMS 복원 오차를 보여줍니다. 아래 그림에서 이상 데이터의 복원 오차가 정상 데이터보다 훨씬 높은 것을 볼 수 있습니다. 이 오토인코더는 정상 데이터에서 훈련되었기 때문에 이와 유사한 신호를 더 잘 복원하며, 따라서 이는 예상된 결과입니다.

% Extract data Before maintenance
XTestBefore = helperExtractLabeledData(featureTest, "Before");

% Predict output before maintenance and calculate error
yHatBefore = predict(net, XTestBefore);
errorBefore = helperCalculateError(XTestBefore, yHatBefore);

% Extract data after maintenance
XTestAfter = helperExtractLabeledData(featureTest, "After");

% Predict output after maintenance and calculate error
yHatAfter = predict(net, XTestAfter);
errorAfter = helperCalculateError(XTestAfter, yHatAfter);

helperVisualizeError(errorBefore, errorAfter);

이상 식별하기

전체 검증 데이터에서 복원 오차를 계산합니다.

XTestAll = helperExtractLabeledData(featureTest, "All");

yHatAll = predict(net, XTestAll);
errorAll = helperCalculateError(XTestAll, yHatAll);

이상을 모든 관측값에서 평균보다 0.5배의 복원 오차가 있는 점으로 정의합니다. 이 임계값은 이전 실험을 통해 결정되었으며 필요에 따라 바뀔 수 있습니다.

thresh = 0.5;
anomalies = errorAll > thresh*mean(errorAll);

helperVisualizeAnomalies(anomalies, errorAll, featureTest);

이 예제에서는 3개의 각기 다른 모델을 사용하여 이상을 감지합니다. 단일 클래스 SVM은 테스트 데이터의 이상 감지에 대해 99.7%의 최고 성능을 보였으며 다른 두 모델은 약 93%의 정확도를 보였습니다. 여러 모델의 상대적인 성능은 다른 특징 세트를 선택하거나 각 모델에 다른 하이퍼파라미터를 사용하는 경우 바뀔 수 있습니다. 진단 특징 디자이너 MATLAB 앱을 사용하여 특징 선택을 추가로 시험해 보십시오.

지원 함수

function E = helperCalculateError(X, Y)
% HELPERCALCULATEERROR calculates the rms error value between the
% inputs X, Y
E = zeros(length(X),1);
for i = 1:length(X)
   E(i,:) = sqrt(sum((Y{i} - X{i}).^2));
end

end

function helperVisualizeError(errorBefore, errorAfter)
% HELPERVISUALIZEERROR creates a plot to visualize the errors on detecting
% before and after conditions
figure("Color", "W")
tiledlayout("flow")

nexttile
plot(1:length(errorBefore), errorBefore, 'LineWidth',1.5), grid on
title(["Before Maintenance", ...
   sprintf("Mean Error: %.2f\n", mean(errorBefore))])
xlabel("Observations")
ylabel("Reconstruction Error")
ylim([0 15])

nexttile
plot(1:length(errorAfter), errorAfter, 'LineWidth',1.5), grid on,
title(["After Maintenance", ...
   sprintf("Mean Error: %.2f\n", mean(errorAfter))])
xlabel("Observations")
ylabel("Reconstruction Error")
ylim([0 15])

end

function helperVisualizeAnomalies(anomalies, errorAll, featureTest)
% HELPERVISUALIZEANOMALIES creates a plot of the detected anomalies
anomalyIdx = find(anomalies);
anomalyErr = errorAll(anomalies);

predAE = categorical(anomalies, [1, 0], ["Anomaly", "Normal"]);
trueAE = renamecats(featureTest.label,["Before","After"],["Anomaly","Normal"]);

acc = numel(find(trueAE == predAE))/numel(predAE)*100;
figure;
t = tiledlayout("flow");
title(t, "Test Accuracy: " + round(mean(acc),2) + "%");
nexttile
hold on
plot(errorAll)
plot(anomalyIdx, anomalyErr, 'x')
hold off
ylabel("Reconstruction Error")
xlabel("Observation")
legend("Error", "Candidate Anomaly")

nexttile
confusionchart(trueAE,predAE)

end

function helperVisualizeModelBehavior(normalData, abnormalData, decodedNorm, decodedAbNorm)
%HELPERVISUALIZEMODELBEHAVIOR Visualize model behavior on sample validation data

figure("Color", "W")
tiledlayout("flow")

nexttile()
hold on
colororder('default')
yyaxis left
plot(normalData{:})
plot(decodedNorm{:},":","LineWidth",1.5)
hold off
title("Normal Input")
grid on
ylabel("Feature Value")
yyaxis right
stem(abs(normalData{:} - decodedNorm{:}))
ylim([0 2])
ylabel("Error")
legend(["Input", "Decoded","Error"],"Location","southwest")

nexttile()
hold on
yyaxis left
plot(abnormalData{:})
plot(decodedAbNorm{:},":","LineWidth",1.5)
hold off
title("Abnormal Input")
grid on
ylabel("Feature Value")
yyaxis right
stem(abs(abnormalData{:} - decodedAbNorm{:}))
ylim([0 2])
ylabel("Error")
legend(["Input", "Decoded","Error"],"Location","southwest")

end

function X = helperExtractLabeledData(featureTable, label)
%HELPEREXTRACTLABELEDDATA Extract data from before or after operating
%conditions and re-format to support input to autoencoder network

% Select data with label After
if label == "All"
   Xtemp = featureTable(:, 2:end).Variables;
else
   tF = featureTable.label == label;
   Xtemp = featureTable(tF, 2:end).Variables;
end

% Arrange data into cells
X = cell(length(Xtemp),1);
for i = 1:length(Xtemp)
   X{i,:} = Xtemp(i,:);
end

end

참고 항목

| | |

관련 항목