メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

3 軸振動データを使用した産業機械の異常の検出

機械の異常検出は難しいことがよくあります。これは、一般に異常動作よりも定格動作の方が、利用できるデータがはるかに多いためです。2 クラスのモデル学習では、このデータの不均衡により、学習済みモデルの大きいクラスの方に偏る結果となります。

定格状態と異常状態の両方のデータでモデルに学習させる代わりに、モデルがすべての外れ値データを異常として検出する程度の忠実度まで、定格状態のデータのみでモデルに学習させる方法があります。

この例では、そのような方法を用いて、機械学習と深層学習のモデルを使用して産業機械の振動データにおける異常を検出する方法を示します。この例では、機械のデータについて、保守イベントの "前" は異常状態であり、イベントの "後" は定格状態であるとします。このように分けることで、次の図に示すように、学習には定格状態のみのデータを使用し、テストには混在するデータを使用できます。

プロセスの手順は次のとおりです。

1) データ量を減らしたデータ セットを使用して、診断特徴デザイナー アプリを使って生の振動測定値から特徴を抽出、ランク付けして選択します。その後、アプリで生成されたコードを使用して、完全なデータ セット用の選択した特徴を生成します。

2) この特徴データを学習セットと、独立したテスト セットに分割します。その後、学習セットから、ラベルが 'After' のすべての特徴を抽出して、定格状態のデータのみを含む新しい学習セットを作成します。

3) 独立したテスト セットはそのままにします。このテスト セットには、'Before' (異常状態) または 'After' (定格状態) のいずれかのラベルをもつ混在したデータが含まれます。

4) 学習セットを使用して、異常検出用の 3 種類のモデル (1 クラス SVM、孤立森、LSTM ネットワーク) に学習させます。

5) 学習済みの各モデルをテスト セットを使用してテストし、各信号が異常状態であるか定格状態であるかをどの程度うまく識別するかについて、それぞれのモデルを評価して比較します。

データ セットのダウンロードと読み込み

ラベル付きの 3 軸振動測定値を含むデータ セットをダウンロードし、解凍して読み込みます。

url = 'https://ssd.mathworks.com/supportfiles/predmaint/anomalyDetection3axisVibration/v1/vibrationData.zip';
websave('vibrationData.zip',url);
unzip('vibrationData.zip');
load("MachineData.mat")
head(trainData,3)
          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

各軸のデータは別々の列に保存されています。保守前に収集されたデータはラベルが Before で、異常状態のデータと見なされます。保守後に収集されたデータはラベルが 'After' で、定格状態のデータと見なされます。

データをより良く理解するために、保守前後のデータを可視化します。アンサンブルの 4 番目のメンバーの振動データをプロットします。2 つの状態のプロット データが異なって見える点に注意してください。

ensMember = 4;
helperPlotVibrationData(trainData, ensMember)

Figure contains 3 axes objects. Axes object 1 with title Channel 1, xlabel Observations, ylabel Vibration Data contains 2 objects of type line. These objects represent Before, After. Axes object 2 with title Channel 2, xlabel Observations, ylabel Vibration Data contains 2 objects of type line. These objects represent Before, After. Axes object 3 with title Channel 3, xlabel Observations, ylabel Vibration Data contains 2 objects of type line. These objects represent Before, After.

診断特徴デザイナー アプリによる特徴の抽出

生のデータには相関やノイズが多いため、機械学習モデルの学習に生のデータを使用することは、あまり効率的ではありません。診断特徴デザイナーアプリでは、対話的にデータの調査と前処理を行い、時間ドメインと周波数ドメインの特徴を抽出したうえで特徴をランク付けして、どれが故障やその他の異常システムの診断に最も効果的か判定できます。次に関数をエクスポートして、選択した特徴をデータ セットからプログラムにより抽出できます。コマンド プロンプトで「diagnosticFeatureDesigner」と入力して、診断特徴デザイナーを開きます。診断特徴デザイナーの使用方法のチュートリアルについては、予知保全アルゴリズムの状態インジケーターの設計を参照してください。

[新規セッション] ボタンをクリックし、trainData をソースとして選択してから、label[状態変数] に設定します。変数 label は、対応するデータについて機械の状態を特定します。

診断特徴デザイナーを使用して特徴について反復し、それらをランク付けできます。アプリによって、生成されたすべての特徴のヒストグラム ビューが作成され、ラベルごとの分布が可視化されます。たとえば、以下のヒストグラムは、ch1 から抽出した各種の特徴の分布を示しています。これらのヒストグラムは、ラベルグループの分離がわかりやすくなるよう、この例で使用するデータ セットよりもはるかに大規模なデータ セットから導出されたものです。使用するデータ セットは比較的小規模であるため、結果は異なります。

各チャネルにつき上位 4 つのランク付けされた特徴を使用します。

  • ch1 :クレスト ファクター、尖度、RMS、標準偏差

  • ch2 :平均、RMS、歪度、標準偏差

  • ch3 :クレスト ファクター、SINAD、SNR、THD

特徴を生成するための関数を診断特徴デザイナー アプリからエクスポートして、generateFeatures の名前で保存します。この関数はコマンド ラインから、データ セット全体の各チャネルにつき上位 4 つの関連する特徴を抽出します。

trainFeatures = generateFeatures(trainData);
head(trainFeatures(:,1:6))
    label     ch1_stats/Col1_CrestFactor    ch1_stats/Col1_Kurtosis    ch1_stats/Col1_RMS    ch1_stats/Col1_Std    ch2_stats/Col1_Mean
    ______    __________________________    _______________________    __________________    __________________    ___________________

    Before              2.2811                      1.8087                   2.3074                2.3071               -0.032332     
    Before              2.3276                      1.8379                   2.2613                 2.261                -0.03331     
    Before              2.3276                      1.8626                   2.2613                2.2612               -0.012052     
    Before              2.8781                      2.1986                   1.8288                1.8285               -0.005049     
    Before              2.8911                        2.06                   1.8205                1.8203              -0.0018988     
    Before              2.8979                      2.1204                   1.8163                1.8162              -0.0044174     
    Before              2.9494                        1.92                   1.7846                1.7844              -0.0067284     
    Before              2.5106                      1.6774                   1.7513                1.7511              -0.0089548     

学習およびテスト用の完全なデータ セットの準備

ここまでに使用してきたデータ セットは、特徴の抽出と選択の過程を説明するために用いた、はるかに大規模なデータ セットの小さなサブセットに過ぎません。使用可能なすべてのデータでアルゴリズムに学習させると、最良のパフォーマンスがもたらされます。そのために、17,642 の信号からなるより大規模なデータ セットから前もって抽出しておいたものと同じ 12 個の特徴を読み込みます。

load("FeatureEntire.mat")
head(featureAll(:,1:6))
    label     ch1_stats/Col1_CrestFactor    ch1_stats/Col1_Kurtosis    ch1_stats/Col1_RMS    ch1_stats/Col1_Std    ch2_stats/Col1_Mean
    ______    __________________________    _______________________    __________________    __________________    ___________________

    Before              2.3683                       1.927                   2.2225                2.2225               -0.015149     
    Before               2.402                      1.9206                   2.1807                2.1803               -0.018269     
    Before              2.4157                      1.9523                   2.1789                2.1788              -0.0063652     
    Before              2.4595                      1.8205                     2.14                2.1401               0.0017307     
    Before              2.2502                      1.8609                   2.3391                 2.339              -0.0081829     
    Before              2.4211                      2.2479                   2.1286                2.1285                0.011139     
    Before              3.3111                      4.0304                   1.5896                1.5896              -0.0080759     
    Before              2.2655                      2.0656                   2.3233                2.3233              -0.0049447     

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 による異常の検出

サポート ベクター マシンは強力な分類器であり、ここでは定格状態のデータのみで学習するバリアントが使用されています。このモデルは、定格状態のデータから "かけ離れた" 異常の識別に効果的です。ocsvm 関数と定格状態のデータを使用して、1 クラス SVM モデルに学習させます。

rng(0) % For reproducibility
mdlOCSVM = ocsvm(featureNormal{:,2:13}, "ContaminationFraction", 0, "StandardizeData", true, "KernelScale", 4);

定格状態と異常状態の両方のデータを含むテスト データを使用して、学習済みの SVM モデルを検証します。

featureTestNoLabels = featureTest(:, 2:end);
isanomalyOCSVM = isanomaly(mdlOCSVM, featureTestNoLabels.Variables, "ScoreThreshold", -0.4);
predOCSVM = categorical(isanomalyOCSVM, [1, 0], ["Anomaly", "Nominal"]);

trueAnomaliesTest = renamecats(trueAnomaliesTest,["After","Before"], ["Nominal","Anomaly"]);
figure;
confusionchart(trueAnomaliesTest, predOCSVM, Title="Anomaly Detection with One-class SVM", Normalization="row-normalized");

Figure contains an object of type ConfusionMatrixChart. The chart of type ConfusionMatrixChart has title Anomaly Detection with One-class SVM.

混同行列から、1 クラス SVM がうまく機能していることがわかります。真陽性識別率が高く、誤分類率が非常に小さくなっています。

孤立森による異常の検出

孤立森の決定木では、各観測を 1 枚の葉に分離します。サンプルがその葉に至るためにいくつの判定を通過するかは、それを他から分離するのがどの程度困難であったかの尺度です。特定サンプルの木の平均深度は異常のスコアとして使用され、iforest によって返されます。

定格状態のデータのみで孤立森モデルに学習させます。

[mdlIF,~,scoreTrainIF] = iforest(featureNormal{:,2:13},'ContaminationFraction',0, 'NumLearners', 200, "NumObservationsPerLearner", 512);

テスト データを使用して、学習済みの孤立森モデルを検証します。混同チャートを使用して、このモデルのパフォーマンスを可視化します。

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

Figure contains an object of type ConfusionMatrixChart. The chart of type ConfusionMatrixChart has title Anomaly Detection with Isolation Forest.

このデータでは、孤立森は 1 クラス SVM ほどうまく機能しません。孤立森モデルのパフォーマンスは、追加データとハイパーパラメーター調整のアクティビティによってさらに改善できます。

双方向 LSTM ネットワークによる異常の検出

双方向 LSTM (BiLSTM) ネットワークはニューラル ネットワークの一種で、過去のコンテキストと将来のコンテキストの両方を考慮してシーケンス データを処理するように設計されています。BiLSTM ネットワークは、時系列データにおける逐次的な依存関係を把握するのに優れています。このコンテキストでは、定格状態のデータのシーケンスのみを使用して BiLSTM ネットワークに学習させることで、想定されるパターンに従わない信号の異常や逸脱を効果的に識別できます。

まず、保守後のデータから特徴を抽出します。

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

BiLSTM ネットワークを構成し、学習オプションを設定します。

featureDimension = 1;

% Define biLSTM network layers
layers = [ sequenceInputLayer(featureDimension)
   bilstmLayer(16)
   reluLayer
   bilstmLayer(32)
   reluLayer
   bilstmLayer(16)
   reluLayer
   fullyConnectedLayer(featureDimension)];

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

学習オプション パラメーター MaxEpochs は 200 に設定されます。検証の精度を高めるには、このパラメーターをより大きい数に設定することができます。ただし、ネットワークが過適合になる可能性があります。

trainnet を使用してモデルを学習させ、損失関数として平均二乗誤差 (mse) を指定します。

net = trainnet(featuresAfter, featuresAfter, layers, "mse", options);

検証データでのモデル動作と誤差の可視化

Anomalous 状態と Nominal 状態からそれぞれ 1 つのサンプルを抽出し、可視化します。以下のプロットでは、12 個の特徴 (X 軸上に表示) のそれぞれについて、BiLSTM モデルの再構成誤差を示しています。このプロットでは、再構成された特徴値を "Reconstructed" 信号と示してあります。このサンプルでは、特徴 10、11、12 が異常入力に対してうまく再構成されず、したがって、誤差が大きくなります。再構成誤差を使用して異常を特定できます。

testNormal = featureTest(1200, 2:end).Variables';
testAnomaly = featureTest(201, 2:end).Variables';

% Predict decoded signal for both
reconstructedNormal = predict(net,testNormal);
reconstructedAnomaly = predict(net,testAnomaly);

% Visualize
helperVisualizeModelBehavior(testNormal, testAnomaly, reconstructedNormal, reconstructedAnomaly)

Figure contains 2 axes objects. Axes object 1 with title Nominal Input, ylabel Error contains an object of type stem. These objects represent Input, Reconstructed, Error. Axes object 2 with title Abnormal Input, ylabel Error contains an object of type stem. These objects represent Input, Reconstructed, Error.

すべての定格状態のデータと異常状態のデータの特徴を抽出します。学習済み BiLSTM モデルを使用して、保守前と保守後の両方のデータについて、選択した 12 個の特徴を予測します。以下のプロットは、12 個の特徴の平方根平均二乗再構成誤差を示したものです。図には、異常状態のデータの再構成誤差が定格状態のデータよりはるかに高いことが示されています。ネットワークは定格状態のデータで学習したため、類似する信号をよりうまく再構成するという結果は予想どおりです。

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

% Predict output before maintenance and calculate error
yHatBefore = minibatchpredict(net, XTestBefore, 'UniformOutput', false);
errorBefore = helperCalculateError(XTestBefore, yHatBefore);

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

% Predict output after maintenance and calculate error
yHatAfter = minibatchpredict(net, XTestAfter, 'UniformOutput', false);
errorAfter = helperCalculateError(XTestAfter, yHatAfter);

helperVisualizeError(errorBefore, errorAfter);

Figure contains 2 axes objects. Axes object 1 with xlabel Observations, ylabel Reconstruction Error contains an object of type line. Axes object 2 with xlabel Observations, ylabel Reconstruction Error contains an object of type line.

異常の特定

検証データ全体について、再構成誤差を計算します。

XTestAll = helperExtractLabeledData(featureTest, "All");

yHatAll = minibatchpredict(net, XTestAll, 'UniformOutput', false);
errorAll = helperCalculateError(XTestAll, yHatAll);

再構成誤差がすべての観測の平均の 0.5 倍となっている点を異常と定義します。このしきい値は前回の実験を通して決定されたものであり、必要に応じて変更することができます。

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

helperVisualizeAnomalies(anomalies, errorAll, featureTest);

Figure contains an axes object and an object of type ConfusionMatrixChart. The axes object with xlabel Observation, ylabel Reconstruction Error contains 2 objects of type line. One or more of the lines displays its values using only markers These objects represent Error, Candidate Anomaly.

この例では、3 種類のモデルを使用して異常を検出しています。3 つのいずれのモデルでも、高い精度と低い誤分類率で異常を検出できます。モデルの相対的なパフォーマンスは、別の特徴セットを選択した場合や、各モデルに別のハイパーパラメーターを使用した場合に変化する可能性があります。診断特徴デザイナー 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", "Nominal"]);
trueAE = renamecats(featureTest.label,["Before","After"],["Anomaly","Nominal"]);

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, reconstructedNorm, reconstructedAbNorm)
%HELPERVISUALIZEMODELBEHAVIOR Visualize model behavior on sample validation data

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

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

nexttile()
hold on
yyaxis left
plot(abnormalData)
plot(reconstructedAbNorm',":","LineWidth",1.5)
hold off
title("Abnormal Input")
grid on
ylabel("Feature Value")
yyaxis right
stem(abs(abnormalData' - reconstructedAbNorm'))
ylim([0 2])
ylabel("Error")
legend(["Input", "Reconstructed","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 biLSTM 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

参考

| | | |

トピック