Main Content

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

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

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

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

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

データのダウンロード

Turbofan Engine Degradation Simulation データ セットをダウンロードして解凍します。

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

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

  • 列 1 – ユニット番号

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

  • 列 3 ~ 5 – 運転設定

  • 列 6 ~ 26 – センサー測定値 1 ~ 21

Turbofan Engine Degradation Simulation データ セットを格納するディレクトリを作成します。

dataFolder = fullfile(tempdir,"turbofan");
if ~exist(dataFolder,"dir")
    mkdir(dataFolder);
end

Turbofan Engine Degradation Simulation データ セットをダウンロードして解凍します。

filename = matlab.internal.examples.downloadSupportFile("nnet","data/TurbofanEngineDegradationSimulationData.zip");
unzip(filename,dataFolder)

学習データの準備

この例に添付されている関数 processTurboFanDataTrain を使用してデータを読み込みます。関数 processTurboFanDataTrainfilenamePredictors からデータを抽出し、cell 配列 XTrain および TTrain を返します。これらの cell 配列には、学習予測子と応答シーケンスが含まれています。

filenamePredictors = fullfile(dataFolder,"train_FD001.txt");
[XTrain,TTrain] = processTurboFanDataTrain(filenamePredictors);

定数値を持つ特徴の削除

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

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

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

シーケンスに含まれている残りの特徴の数を表示します。

numFeatures = size(XTrain{1},2)
numFeatures = 17

学習予測子の正規化

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

XTrainConcatenatedTimesteps = cat(1,XTrain{:});
mu = mean(XTrainConcatenatedTimesteps,1);
sig = std(XTrainConcatenatedTimesteps,0,1);

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

応答のクリップ

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

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

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

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

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

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

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

[sequenceLengths,idx] = sort(sequenceLengths,"descend");
XTrain = XTrain(idx);
TTrain = TTrain(idx);

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

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

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

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

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

numResponses = size(TTrain{1},2);
numHiddenUnits = 200;

layers = [ ...
    sequenceInputLayer(numFeatures)
    lstmLayer(numHiddenUnits,OutputMode="sequence")
    fullyConnectedLayer(50)
    dropoutLayer(0.5)
    fullyConnectedLayer(numResponses)];

学習オプションを指定します。ソルバー "adam" を使用して、サイズ 20 のミニバッチで 60 エポックの学習を行います。学習率を 0.01 に指定します。勾配の発散を防ぐために、勾配しきい値を 1 に設定します。シーケンスを長さで並べ替えられた状態に保つために、Shuffle オプションを "never" に設定します。学習の進行状況をプロットに表示し、平方根平均二乗誤差 (RMSE) メトリクスを監視します。

maxEpochs = 60;
miniBatchSize = 20;

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

ネットワークの学習

関数trainnetを使用してニューラル ネットワークに学習させます。回帰の場合は、平均二乗誤差損失を使用します。既定では、関数 trainnet は利用可能な GPU がある場合にそれを使用します。GPU での学習には、Parallel Computing Toolbox™ ライセンスとサポートされている GPU デバイスが必要です。サポートされているデバイスについては、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。そうでない場合、関数 trainnet は CPU を使用します。実行環境を指定するには、ExecutionEnvironment 学習オプションを使用します。

net = trainnet(XTrain,TTrain,layers,"mse",options);

ネットワークのテスト

この例に添付されている関数 processTurboFanDataTest を使用してテスト データを準備します。関数 processTurboFanDataTestfilenamePredictors および filenameResponses からデータを抽出し、cell 配列 XTest および TTest を返します。これらの cell 配列には、テスト予測子と応答シーケンスがそれぞれ含まれています。

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

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

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

ニューラル ネットワークを使用して予測を実行します。複数の観測値を使用して予測を行うには、関数minibatchpredictを使用します。関数 minibatchpredict は利用可能な GPU がある場合に自動的にそれを使用します。GPU を使用するには、Parallel Computing Toolbox™ ライセンスとサポートされている GPU デバイスが必要です。サポートされているデバイスについては、「GPU 計算の要件」を参照してください。そうでない場合、関数は CPU を使用します。この関数がデータにパディングを追加するのを防ぐために、ミニバッチ サイズを 1 に指定します。予測を cell 配列で返すには、UniformOutputfalse に設定します。

YTest = minibatchpredict(net,XTest,MiniBatchSize=1,UniformOutput=false);

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

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

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

idx = randperm(numel(YTest),4);
figure
for i = 1:numel(idx)
    subplot(2,2,i)
    
    plot(TTest{idx(i)},"--")
    hold on
    plot(YTest{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(TTest)
    TTestLast(i) = TTest{i}(end);
    YTestLast(i) = YTest{i}(end);
end
figure
rmse = sqrt(mean((YTestLast - TTestLast).^2))
rmse = single
    21.1070
histogram(YTestLast - TTestLast)
title("RMSE = " + rmse)
ylabel("Frequency")
xlabel("Error")

参考文献

  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.

参考

| | | | | | |

関連するトピック