メインコンテンツ

深層学習を使用した 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);

応答のクリップ

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

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

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

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

ネットワーク アーキテクチャを定義します。

  • 手動で計算された正規化統計を使用して Z スコア正規化を適用するシーケンス入力層を指定します。

  • LSTM 層には、200 個の隠れユニットを指定します。

  • 出力サイズが 50 の全結合層を含め、その後にドロップアウトの確率が 0.5 のドロップアウト層を配置します。

  • 回帰の場合、応答の数と一致する出力サイズをもつ全結合層を含めます。

  • この例では、学習プロセスで NormalizeTargets 学習オプション (R2026a で導入) を使用し、学習ターゲットを自動的に正規化します。正規化されたターゲットを使用することで、学習が安定し、正規化されたターゲットにほぼ一致する学習予測が得られます。予測時にのみ、正規化されていない値の空間でニューラル ネットワークの出力予測を行うには、逆対称再スケーリング演算を適用する逆正規化層 (R2026a で導入) を含めます。R2026a より前: 学習を安定させるために、ニューラル ネットワークに学習させる前にターゲットを手動で正規化します。

numHiddenUnits = 200;
fcOutputSize = 50;
dropoutProbability = 0.5;

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

layers = [ ...
    sequenceInputLayer(numFeatures,Normalization="zscore",Mean=mu',StandardDeviation=sig')
    lstmLayer(numHiddenUnits,OutputMode="sequence")
    fullyConnectedLayer(fcOutputSize)
    dropoutLayer(dropoutProbability)
    fullyConnectedLayer(numResponses)
    inverseNormalizationLayer(Normalization="rescale-symmetric")];

ターゲットの下限は 0 で上限はクリッピングしきい値であるため、ゼロパディングによって導入されたターゲット値が、再スケーリングに使用されるターゲット正規化統計に影響を与えることはありません。

学習オプションの指定

学習オプションを指定します。オプションの中から選択するには、経験的解析が必要です。実験を実行してさまざまな学習オプションの構成を調べるには、実験マネージャーアプリを使用できます。

  • Adam ソルバーを使用して学習させます。

  • NormalizeTargets 引数 (R2026a で導入) を使用して、学習ターゲットを自動的に正規化します。R2026a より前: 学習を安定させるために、ニューラル ネットワークに学習させる前にターゲットを手動で正規化します。

  • 入力層の正規化統計量はリセットしません。

  • シーケンスを左パディングします。

  • サイズ 20 のミニバッチで 80 エポック学習させます。

  • 勾配の発散を防ぐために、勾配しきい値を 1 に設定します。

  • すべてのエポックでシーケンスをシャッフルします。

  • 学習の進行状況をプロットに表示し、平方根平均二乗誤差 (RMSE) メトリクスを監視します。

  • 詳細出力を無効にします。

maxEpochs = 80;
miniBatchSize = 20;

options = trainingOptions("adam", ...
    NormalizeTargets=true, ...
    ResetInputNormalization=false, ...
    SequencePaddingDirection="left", ...
    MaxEpochs=maxEpochs, ...
    MiniBatchSize=miniBatchSize, ...
    GradientThreshold=1, ...
    Shuffle="every-epoch", ...
    Plots="training-progress", ...
    Metrics="rmse", ...
    Verbose=false);

ニューラル ネットワークの学習

関数trainnetを使用してニューラル ネットワークに学習させます。回帰の場合は、平均二乗誤差 (MSE) 損失を使用します。既定では、関数 trainnet は利用可能な GPU がある場合にそれを使用します。GPU を使用するには、Parallel Computing Toolbox™ ライセンスとサポートされている GPU デバイスが必要です。サポートされているデバイスの詳細については、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。そうでない場合、関数は 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) = [];
    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
err = sqrt(mean((YTestLast - TTestLast).^2))
err = single

24.9944
histogram(YTestLast - TTestLast)
title("RMSE = " + err)
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.

参考

| | | | | | | |

参考

トピック