Main Content

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

LSTM 自己符号化器を使用した機械の異常検出

この例では、Signal Processing Toolbox™ の deepSignalAnomalyDetector オブジェクトに実装された長短期記憶 (LSTM) 自己符号化器を使用して、産業機械から取得した振動データの異常を検出する方法を示します。この例は3 軸振動データを使用した産業機械での異常検出 (Predictive Maintenance Toolbox)に基づいています。データ、特徴抽出、および異常検出の代替方法の詳細については、そちらの例を参照してください。

データの読み込み

この例のデータは、バッテリー電極切断機から数日間の稼働中に収集された、3 チャネルの振動測定値で構成されています。各チャネルは振動軸に対応します。データ収集プロセス中のある時点で、マシンのメンテナンスが計画されています。定期メンテナンス後に収集されたデータは、マシンの通常の動作状態を表すものと見なされます。メンテナンス前のデータは、通常の状態または異常な状態を表す可能性があります。

データを取得して解凍し、ワークスペースに読み込みます。

localfile = matlab.internal.examples.downloadSupportFile("predmaint", ...
    "anomalyDetection3axisVibration/v1/vibrationData.zip");
unzip(localfile,tempdir)
data = load(fullfile(tempdir,"FeatureEntire.mat"));
features = data.featureAll;

Predictive Maintenance Toolbox の例では、診断特徴デザイナー (Predictive Maintenance Toolbox)アプリを使用して生データから特徴を抽出し、故障状態の診断に最も効果的な特徴を選択します。

  • 最初のチャネルから、クレスト ファクター、尖度、平方根平均二乗 (RMS) 値、および標準偏差を選択します。

  • 2 番目のチャネルから、平均、RMS 値、歪度、および標準偏差を選択します。

  • 3 番目のチャネルから、クレスト ファクター、信号対ノイズおよび歪み比 (SINAD)、S/N 比 (SNR)、および全高調波歪み (THD) を選択します。

この例では、関連する 12 個の特徴セットで各信号を表します。データ ファイルでは、メンテナンスの前後に測定されたデータから抽出されたものとして各信号にラベルが付けられます。冗長なフレーズ "_stats/Col1_" を削除して、変数名を短縮します。table のランダムな行をいくつか表示します。

for ik = 2:size(features,2)
    features.Properties.VariableNames(ik) = ...
        erase(features.Properties.VariableNames(ik),"_stats/Col1_");
end
head(features(randperm(height(features)),:))
    label     ch1CrestFactor    ch1Kurtosis    ch1RMS    ch1Std     ch2Mean      ch2RMS     ch2Skewness    ch2Std     ch3CrestFactor    ch3SINAD    ch3SNR     ch3THD 
    ______    ______________    ___________    ______    ______    __________    _______    ___________    _______    ______________    ________    _______    _______

    After         1.6853          1.7668       3.1232    3.1229     0.0033337    0.49073      1.5804       0.49073        9.8948        -9.2412     -9.0909    -5.4062
    After         1.9119          2.2294        2.753    2.7525    -0.0097274    0.50029      1.7341        0.5002        6.9006        -8.0354     -7.8494    -5.7064
    After         2.0892          2.9014       2.5194    2.5171     -0.010164    0.53292      3.9178       0.53283        6.9842        -9.0894     -8.9333    -5.4036
    After         1.7445          1.7777       3.0172    3.0161     -0.019713    0.70911      2.7898       0.70884        6.2546        -8.3171     -8.1375    -5.5683
    After         2.0058          1.7628       2.6241    2.6239     -0.039584    0.72208      5.0116         0.721        21.593        -13.534     -13.481    -5.5184
    After         1.7668          1.7662       2.9792    2.9789    -0.0034628    0.65523      2.7817       0.65522        6.8951        -8.3663     -8.1994      -5.83
    After         1.8217          2.0704       2.8893    2.8883     -0.055623    0.89943       3.615       0.89771         6.454        -7.9951     -7.8086     -5.737
    Before        2.8021          2.7288       1.8784    1.8782    -0.0020621     0.2861      2.1066       0.28609        9.0325         -15.02     -15.009    -10.604

メンテナンスの前に信号の約 3 分の 1 が収集されていることを確認します。

countlabels(features)
ans=2×3 table
    label     Count    Percent
    ______    _____    _______

    Before     6218    35.245 
    After     11424    64.755 

データを、ランダムに取得された測定値の 90% から成る学習テストと、その残りから成るテスト セットに分割します。再現可能な結果が必要な場合は、乱数発生器をリセットします。

rng("default")
idx = splitlabels(features,0.9,"randomized");

fTrain = features(idx{1},:);
fTest = features(idx{2},:);

検出器アーキテクチャの定義

deepSignalAnomalyDetectorオブジェクトを使用して、長短期記憶 (LSTM) 自己符号化器を作成します。自己符号化器は、ラベルのないシーケンス データの圧縮表現を学習するニューラル ネットワークの一種です。この自己符号化器は、Predictive Maintenance Toolbox の例の自己符号化器とは詳細がいくらか異なりますが、同様の結果を生成します。

  • 検出器に入力される各信号のチャネルが 1 つだけであることを指定します。

  • 2 つの符号化器層 (1 つは 16 個の隠れユニットをもち、もう 1 つは 32 個の隠れユニットをもつ) と 1 つの復号化器層 (16 個の隠れユニットをもつ) を指定します。

  • 各入力信号を単一のセグメントとして扱うように、検出器の WindowLength プロパティを指定します。用途に応じて、各信号内の異常な点または領域を検出するように検出器に学習させることもできます。

  • オブジェクトが検出しきい値の計算に学習データ セット全体で測定された平均ウィンドウ損失を使用し、0.8 を乗算するように指定します。

detector = deepSignalAnomalyDetector(1,"lstm", ...
    EncoderHiddenUnits=[16 32], ...
    DecoderHiddenUnits=16, ...
    WindowLength="fullSignal", ...
    ThresholdMethod="mean", ...
    ThresholdParameter=0.8);

学習用データの準備

異常検出器への入力に適した形式にデータを変換する関数を定義します。関数は、データ行列から categorical 列を削除し、数値行列を各セルが行列行を表す cell 配列に変換して、各セルを転置します。

t2c = @(in)cellfun(@transpose, ...
    mat2cell(in(:,2:end).Variables,ones(height(in),1)), ...
    UniformOutput=false);

学習オプションの指定

ミニバッチ サイズを 500 として 200 エポック学習させます。Adam ソルバーを使用します。

options = trainingOptions("adam", ...
   Plots="training-progress", ...
   Verbose=false, ...
   MiniBatchSize=500,...
   MaxEpochs=200);

検出器の学習

関数trainDetectorを使用して、正常であると想定されるラベルなしデータを LSTM 自己符号化器に学習させます。これは教師なし学習の例です。

trainAfter = fTrain(fTrain.label=="After",:);

trainDetector(detector,t2c(trainAfter),options)

検出器のテスト

学習済みの自己符号化器にテスト データ セットを与えると、オブジェクトは学習内容に基づいて学習中に各信号を再構築します。次に、オブジェクトは信号とその再構成の間の偏差を測定する再構成損失を計算し、指定されたしきい値を再構成誤差が超えたときに信号を異常であると識別します。関数detectは、異常な信号を true とする logical 配列を出力します。

定期メンテナンスの前に収集されたテスト データの異常をカウントします。異常の数を信号数に対する割合として表します。

testBefore = fTest(fTest.label=="Before",:);

aBefore = cell2mat(detect(detector,t2c(testBefore)));
nBefore = sum(aBefore)/height(testBefore)*100
nBefore = 99.0354

定期メンテナンスの後に収集されたテスト データの異常をカウントします。異常の数を信号数に対する割合として表し、その値がメンテナンス前のデータよりも大幅に小さいことを確認します。

testAfter = fTest(fTest.label=="After",:);

aAfter = cell2mat(detect(detector,t2c(testAfter)));
nAfter = sum(aAfter)/height(testAfter)*100
nAfter = 2.6270

通常の状態および異常な状態に対応する、ランダムに選択されたサンプル信号を可視化して特徴付けます。関数plotAnomaliesは、入力信号と自己符号化器によるその再構成を表示します。関数 detect の 2 番目の出力引数は、各入力信号の集計された再構成損失です。

[~,lB] = detect(detector,t2c(testBefore));

ndN = find(~aBefore);
ndN = ndN(randi(length(ndN)));
plotAnomalies(detector,t2c(testBefore(ndN,:)), ...
    PlotReconstruction=true)
text(2,-3,"Signal " + ndN + ", Loss = " + lB(ndN))
ylim([-16 11])
grid on

検出器は、信号を異常であると識別すると、その信号を太いラインかつ異なる色で表示します。

ndA = find(aBefore);
ndA = ndA(randi(length(ndA)));
plotAnomalies(detector,t2c(testBefore(ndA,:)), ...
    PlotReconstruction=true)
text(2,-3,"Signal " + ndA + ", Loss = " + lB(ndA))
ylim([-16 11])
grid on

損失のプロットおよびしきい値の可視化

関数plotLossを使用して、定期メンテナンス前後のテスト データの信号ごとの再構成損失をプロットします。予想どおり、メンテナンス前のデータの再構成損失は、メンテナンス後のデータよりもはるかに高くなります。関数は、計算されたしきい値も表示します。

clf
q = plotLoss(detector,t2c(fTest));
xl = xline(height(testBefore),":",LineWidth=2, ...
    DisplayName="Scheduled Maintenance");
legend(xl,Box="off")
ylim([0 15])

関数plotLossDistributionは、累積分布関数 (CDF) と、検出器が計算した再構成損失のヒストグラムを表示します。メンテナンス後のテスト データとメンテナンス前のデータの再構成損失分布を比較します。しきい値を調整することで、正常なデータと異常なデータをより適切に分離できます。

plotLossDistribution(detector,t2c(testAfter),t2c(testBefore))

検出器または分類器の受信者動作特性 (ROC) 曲線は、分離しきい値の変化に伴うその性能を表します。ROC 曲線の下の領域 (AUC) は、曲線によって与えられる情報を要約します。AUC 値が 1 に近いければ、検出器または分類器のパフォーマンスが良好であることを示します。この例では、ROC 曲線をプロットし、異常検出器の AOC を計算します。

[~,lT] = detect(detector,t2c(fTest));
rocc = rocmetrics(fTest.label=="Before",cell2mat(lT),true);
plot(rocc,ShowModelOperatingPoint=false)

まとめ

この例では、deepSignalAnomalyDetector オブジェクトについて紹介し、それを使用して産業機械の振動データの異常を検出します。

参考

関数

オブジェクト

関連するトピック