ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

深層学習を使用した sequence-to-sequence 回帰

この例では、深層学習を使用してエンジンの残存耐用期間 (RUL) を予測する方法を説明します。

時系列データまたはシーケンス データから数値を予測するよう深層ニューラル ネットワークに学習させるために、長短期記憶 (LSTM) ネットワークを使用できます。

この例では、[1] に記載のある Turbofan Engine Degradation Simulation Data Set を使用します。この例では、エンジンのさまざまなセンサーを表す時系列データを与えて、サイクル単位で測定されるエンジンの残存耐用期間を予測 (予知保全) するよう LSTM ネットワークに学習させます。学習データには、100 個のエンジンのシミュレートされた時系列データが含まれています。各シーケンスには 17 個の特徴があり、長さはさまざまで、故障するまで使用 (RTF) した事例全体に対応します。テスト データには、100 個の部分シーケンスと、各シーケンスの最後における対応する残存耐用期間の値が含まれています。

データセットには 100 個の学習観測値と 100 個のテスト観測値が含まれています。

データのダウンロード

Turbofan Engine Degradation Simulation Data Set を https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository/ [2] からダウンロードして解凍します。

各時系列は異なるエンジンを表します。開始時点では、各エンジンの初期摩耗の程度や製造上の差異は不明です。各時系列の開始時、エンジンは正常に運転していますが、時系列のある時点で故障が発生します。学習セットでは、システム障害が発生するまで、故障の規模が大きくなります。

このデータには、スペースで区切られた 26 列の数値のある zip 圧縮されたテキスト ファイルが含まれています。各行は 1 回の運転サイクルの間に取得されたデータのスナップショットで、各列は異なる変数です。各列は以下に対応します。

  • 列 1: ユニット番号

  • 列 2: サイクル単位の時間

  • 列 3 ~ 5: 運転設定

  • 列 6 ~ 26: センサー測定値 1 ~ 17

filename = "CMAPSSData.zip";
dataFolder = "data";
unzip(filename,dataFolder)

学習データの準備

この例の終わりに示す関数 preprocessDataTrain を使用してデータを読み込みます。関数 prepareDataTrainfilenamePredictors からデータを抽出し、cell 配列 XTrain および YTrain を返します。これらの cell 配列には、学習予測子と応答シーケンスが含まれています。

filenamePredictors = fullfile(dataFolder,"train_FD001.txt");
[XTrain,YTrain] = prepareDataTrain(filenamePredictors);

定数値を持つ特徴の削除

すべてのタイム ステップで一定のままである特徴は、学習に悪影響を与える可能性があります。最小値と最大値が同じになるデータの行を見つけ、それらの行を削除します。

m = min([XTrain{:}],[],2);
M = max([XTrain{:}],[],2);
idxConstant = M == m;

for i = 1:numel(XTrain)
    XTrain{i}(idxConstant,:) = [];
end

学習予測子の正規化

ゼロ平均と単位分散を持つように学習予測子を正規化します。すべての観測値について平均値と標準偏差を計算するために、シーケンス データを水平方向に連結します。

mu = mean([XTrain{:}],2);
sig = std([XTrain{:}],0,2);

for i = 1:numel(XTrain)
    XTrain{i} = (XTrain{i} - mu) ./ sig;
end

応答のクリップ

エンジンが故障に近いときのシーケンス データから詳しく学習するために、しきい値 150 で応答をクリップします。これによって、ネットワークは RUL 値が大きい事例を同等に扱います。

thr = 150;
for i = 1:numel(YTrain)
    YTrain{i}(YTrain{i} > thr) = thr;
end

次の図は、最初の観測値と対応するクリップされた応答を示しています。

パディング用のデータの準備

ミニバッチに追加するパディングの量を最小限に抑えるために、シーケンス長で学習データを並べ替えます。さらに、学習データを等分するミニバッチ サイズを選択し、ミニバッチ内のパディングの量を減らします。

シーケンス長で学習データを並べ替えます。

for i=1:numel(XTrain)
    sequence = XTrain{i};
    sequenceLengths(i) = size(sequence,2);
end

[sequenceLengths,idx] = sort(sequenceLengths,'descend');
XTrain = XTrain(idx);
YTrain = YTrain(idx);

並べ替えられたシーケンス長を棒グラフで表示します。

figure
bar(sequenceLengths)
xlabel("Sequence")
ylabel("Length")
title("Sorted Data")

学習データを等分するミニバッチ サイズを選択し、ミニバッチ内のパディングの量を減らします。ミニバッチ サイズを 20 に指定します。この図は、並べ替えていないシーケンスと並べ替えたシーケンスに追加されたパディングを示しています。

miniBatchSize = 20;

ネットワーク アーキテクチャの定義

ネットワーク アーキテクチャの定義。隠れユニットが 200 個ある LSTM 層と、その後に続くサイズが 50 の全結合層とドロップアウトの確率が 0.5 のドロップアウト層で構成された LSTM ネットワークを作成します。

numResponses = size(YTrain{1},1);
featureDimension = size(XTrain{1},1);
numHiddenUnits = 200;

layers = [ ...
    sequenceInputLayer(featureDimension)
    lstmLayer(numHiddenUnits,'OutputMode','sequence')
    fullyConnectedLayer(50)
    dropoutLayer(0.5)
    fullyConnectedLayer(numResponses)
    regressionLayer];

学習オプションを指定します。ソルバー 'adam' を使用して、サイズ 20 のミニバッチで 60 エポックの学習を行います。学習率を 0.01 に指定します。勾配の発散を防ぐために、勾配のしきい値を 1 に設定します。シーケンスを長さで並べ替えられた状態に保つために、'Shuffle''never' に設定します。

maxEpochs = 60;
miniBatchSize = 20;

options = trainingOptions('adam', ...
    'MaxEpochs',maxEpochs, ...
    'MiniBatchSize',miniBatchSize, ...
    'InitialLearnRate',0.01, ...
    'GradientThreshold',1, ...
    'Shuffle','never', ...
    'Plots','training-progress',...
    'Verbose',0);

ネットワークの学習

trainNetwork を使用してネットワークに学習させます。

net = trainNetwork(XTrain,YTrain,layers,options);

ネットワークのテスト

この例の終わりに示す関数 prepareDataTest を使用してテスト データを準備します。関数 prepareDataTestfilenamePredictors および filenameResponses からデータを抽出し、cell 配列 XTest および YTest を返します。これらの cell 配列には、テスト予測子と応答シーケンスがそれぞれ含まれています。

filenamePredictors = fullfile(dataFolder,"test_FD001.txt");
filenameResponses = fullfile(dataFolder,"RUL_FD001.txt");
[XTest,YTest] = prepareDataTest(filenamePredictors,filenameResponses);

学習データから計算された idxConstant を使用して定数値を持つ特徴を削除します。学習データと同じパラメーターを使用してテスト予測子を正規化します。学習データに使用したのと同じしきい値でテストの応答をクリップします。

for i = 1:numel(XTest)
    XTest{i}(idxConstant,:) = [];
    XTest{i} = (XTest{i} - mu) ./ sig;
    YTest{i}(YTest{i} > thr) = thr;
end

predict を使用してテスト データについて予測を実行します。この関数がデータにパディングを追加するのを防ぐために、ミニバッチ サイズを 1 に指定します。

YPred = predict(net,XTest,'MiniBatchSize',1);

この LSTM ネットワークは、1 タイム ステップずつ部分シーケンスについて予測を行います。各タイム ステップで、ネットワークは、このタイム ステップでの値と前のタイム ステップから計算されたネットワークの状態のみを使用して予測を行います。このネットワークは、各予測間にその状態を更新します。関数 predict は、これらの予測のシーケンスを返します。予測の最後の要素は、部分シーケンスについて予測された RUL に対応します。

または、predictAndUpdateState を使用して 1 タイム ステップずつ予測できます。これは、タイム ステップの値がストリームで到着する場合に役立ちます。通常、1 タイム ステップずつ予測するよりも、シーケンス全体について予測する方が高速です。1 つのタイム ステップでの予測間にネットワークを更新して将来のタイム ステップを予測する方法を示す例については、深層学習を使用した時系列予測を参照してください。

予測の一部をプロットで可視化します。

idx = randperm(numel(YPred),4);
figure
for i = 1:numel(idx)
    subplot(2,2,i)
    
    plot(YTest{idx(i)},'--')
    hold on
    plot(YPred{idx(i)},'.-')
    hold off
    
    ylim([0 thr + 25])
    title("Test Observation " + idx(i))
    xlabel("Time Step")
    ylabel("RUL")
end
legend(["Test Data" "Predicted"],'Location','southeast')

与えられた部分シーケンスについて、予測された現在の RUL は予測シーケンスの最後の要素です。予測の平方根平均二乗誤差 (RMSE) を計算し、予測誤差をヒストグラムで可視化します。

for i = 1:numel(YTest)
    YTestLast(i) = YTest{i}(end);
    YPredLast(i) = YPred{i}(end);
end
figure
rmse = sqrt(mean((YPredLast - YTestLast).^2))
rmse = single
    16.9854
histogram(YPredLast - YTestLast)
title("RMSE = " + rmse)
ylabel("Frequency")
xlabel("Error")

関数の例

関数 prepareDataTrainfilenamePredictors からデータを抽出し、cell 配列 XTrain および YTrain を返します。これらの cell 配列には、学習予測子と応答シーケンスがそれぞれ含まれています。

このデータには、スペースで区切られた 26 列の数値のある zip 圧縮されたテキスト ファイルが含まれています。各行は 1 回の運転サイクルの間に取得されたデータのスナップショットで、各列は異なる変数です。各列は以下に対応します。

  • 1: ユニット番号

  • 2: サイクル単位の時間

  • 3 ~ 5: 運転設定

  • 6 ~ 26: センサー測定値 1 ~ 17

function [XTrain,YTrain] = prepareDataTrain(filenamePredictors)

dataTrain = dlmread(filenamePredictors);

numObservations = max(dataTrain(:,1));

XTrain = cell(numObservations,1);
YTrain = cell(numObservations,1);
for i = 1:numObservations
    idx = dataTrain(:,1) == i;
    
    X = dataTrain(idx,3:end)';
    XTrain{i} = X;
    
    timeSteps = dataTrain(idx,2)';
    Y = fliplr(timeSteps);
    YTrain{i} = Y;
end

end

関数 prepareDataTestfilenamePredictors および filenameResponses からデータを抽出し、cell 配列 XTest および YTest を返します。これらの cell 配列には、テスト予測子と応答シーケンスが含まれています。filenamePredictors では、時系列はシステム障害より前のある時点で終了します。filenameResponses のデータから、テスト データに対する実際の RUL 値のベクトルが得られます。

function [XTest,YTest] = prepareDataTest(filenamePredictors,filenameResponses)

XTest = prepareDataTrain(filenamePredictors);

RULTest = dlmread(filenameResponses);

numObservations = numel(RULTest);

YTest = cell(numObservations,1);
for i = 1:numObservations
    X = XTest{i};
    sequenceLength = size(X,2);
    
    rul = RULTest(i);
    YTest{i} = rul+sequenceLength-1:-1:rul;
end

end

参考

| | | |

参照

[1] Saxena, Abhinav, Kai Goebel, Don Simon, and Neil Eklund. "Damage propagation modeling for aircraft engine run-to-failure simulation." In Prognostics and Health Management, 2008. PHM 2008. International Conference on, pp. 1-9. IEEE, 2008.

[2] Saxena, Abhinav, Kai Goebel. "Turbofan Engine Degradation Simulation Data Set." NASA Ames Prognostics Data Repository https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository/, NASA Ames Research Center, Moffett Field, CA

関連するトピック