このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
3 軸振動データを使用した産業機械での異常検出
この例では、機械学習と深層学習を使用して振動データにおける異常を検出する方法を説明します。例では、産業機械の振動データを使用します。最初に、診断特徴デザイナー アプリを使用して、通常の動作に対応する生の測定値から特徴を抽出します。選択した特徴を使用して、異常検出用の 3 種類のモデル (1 クラス 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
⋮
データをより良く理解するために、保守前後のデータを可視化します。アンサンブルの 4 番目のメンバーの振動データをプロットします。2 つの状態のデータが異なって見える点に注意してください。
ensMember = 4; helperPlotVibrationData(trainData, ensMember)
診断特徴デザイナー アプリによる特徴の抽出
生のデータには相関やノイズが多いため、機械学習モデルの学習に生のデータを使用することは、あまり効率的ではありません。診断特徴デザイナーアプリでは、対話的にデータの調査と前処理を行い、時間ドメインと周波数ドメインの特徴を抽出したうえで特徴をランク付けして、どれが故障やその他の異常システムの診断に最も効果的か判定できます。次に関数をエクスポートして、選択した特徴をデータ セットからプログラムにより抽出できます。コマンド プロンプトで「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
学習用の完全なデータ セットの準備
ここまでに使用してきたデータ セットは、特徴の抽出と選択の過程を説明するために用いた、はるかに大規模なデータ セットの小さなサブセットに過ぎません。使用可能なすべてのデータでアルゴリズムに学習させると、最良のパフォーマンスがもたらされます。そのために、17,642 の信号からなるより大規模なデータ セットから前もって抽出しておいたものと同じ 12 個の特徴を読み込みます。
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', :);
1 クラス SVM による異常の検出
サポート ベクター マシンは強力な分類器であり、ここでは通常状態のデータのみで学習するバリアントが使用されています。このモデルは、通常状態のデータから "かけ離れた" 異常の識別に効果的です。関数 fitcsvm
と通常状態のデータを使用して、1 クラス 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");
混同行列から、1 クラス SVM がうまく機能していることがわかります。異常状態のサンプルの 0.3% のみが通常として誤分類され、通常状態のデータの約 0.9% が異常として誤分類されています。
孤立森による異常の検出
孤立森の決定木では、各観測を 1 枚の葉に分離します。サンプルがその葉に至るためにいくつの判定を通過するかは、それを他から分離するのがどの程度困難であったかの尺度です。特定サンプルの木の平均深度は異常のスコアとして使用され、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");
このデータでは、孤立森は 1 クラス 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.
検証データでのモデル動作と誤差の可視化
異常状態と通常状態からそれぞれ 1 つのサンプルを抽出し、可視化します。以下のプロットでは、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 個の特徴の平方根平均二乗再構成誤差を示したものです。図には、異常状態のデータの再構成誤差が通常状態のデータよりはるかに高いことが示されています。オートエンコーダーは通常状態のデータで学習したため、類似する信号をよりうまく再構成するという結果は予想どおりです。
% 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 種類のモデルを使用して異常を検出しています。テスト データの異常検出は、1 クラス SVM が 99.7% と最も高いパフォーマンスを示し、他の 2 つのモデルは 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
参考
cvpartition
| fitcsvm
| iforest
| 診断特徴デザイナー