Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

ベイズ最適化を使用した LSTM の学習構成の選択

R2020b 以降

この例では、ベイズ最適化を使用して、長短期記憶 (LSTM) ネットワーク用の最適なネットワーク ハイパーパラメーターと学習オプションを見つける深層学習実験の作成方法を説明します。この例では、実験マネージャーを使用して、エンジンの残存耐用期間 (RUL) を予測する LSTM ネットワークに学習させます。この実験では、Turbofan Engine Degradation Simulation データ セットを使用します。sequence-to-sequence 回帰用のこのデータ セットの処理に関する詳細については、深層学習を使用した sequence-to-sequence 回帰を参照してください。

ベイズ最適化により、実験においてハイパーパラメーターをスイープするための代替手法が得られます。各ハイパーパラメーターの値の範囲を指定し、最適化するメトリクスを選択します。すると、選択したメトリクスを最適化するハイパーパラメーターの組み合わせを実験マネージャーが検索します。ベイズ最適化には Statistics and Machine Learning Toolbox™ が必要です。詳細については、ベイズ最適化を使用した実験ハイパーパラメーターの調整を参照してください。

RUL は、エンジンが故障する前に行える運転サイクルの回数を取得します。エンジンの故障が近づいてきたときにシーケンス データに着目するために、指定したしきい値で応答をクリップしてデータを前処理します。この前処理の操作によって、ネットワークは RUL 値がこれより高いインスタンスを等価として処理し、故障が近づいたときの予測子データの変動に着目できるようになります。例として、次の図は、最初の応答の観測値、およびそれに対応するしきい値 150 でクリップされた応答を示しています。

深層学習ネットワークに学習させる場合、データの前処理方法、層と隠れユニットの数、およびネットワークの初期学習率が、ネットワークの学習の動作と性能に影響を与える可能性があります。LSTM ネットワークの深さを選択する際は、速度と精度のバランスを考慮します。たとえば、ネットワークを深くすると精度が高まりますが、学習と収束により多くの時間がかかります [2]。

既定では、回帰用に組み込まれている学習実験を実行すると、実験マネージャーによって、実験における各試行の損失および平方根平均二乗誤差 (RMSE) が計算されます。この例では、問題に関するデータ セットに特有のカスタム メトリクスを使用して、各試行のネットワーク性能を比較します。カスタム メトリクス関数の使用の詳細については、メトリクス関数を使用した深層学習実験の評価を参照してください。

実験を開く

まず、例を開きます。実験マネージャーによって、事前構成済みの実験を含むプロジェクトが読み込まれます。実験を開くには、[実験ブラウザー] で、SequenceRegressionExperiment をダブルクリックします。

組み込みの学習実験は、説明、ハイパーパラメーターのテーブル、セットアップ関数、および実験の結果を評価するためのメトリクス関数の集合で構成されます。ベイズ最適化を使用する実験には、実験の期間を制限する追加のオプションが含まれます。詳細については、組み込みの学習実験の構成を参照してください。

[説明] フィールドには、実験を説明するテキストが表示されます。この例の説明は次のようになります。

Sequence-to-sequence regression to predict the remaining useful life (RUL) of engines.
This experiment compares network performance using Bayesian optimization when changing data
thresholding level, LSTM layer depth, the number of hidden units, and the initial learn rate.

[ハイパーパラメーター] セクションでは、実験で使用する手法とハイパーパラメーターのオプションを指定します。各ハイパーパラメーターについて、次のオプションを指定できます。

  • 範囲 — 実数値または整数値のハイパーパラメーターの下限と上限を示す 2 要素のベクトル、または categorical ハイパーパラメーターが取り得る値をリストする string 配列または cell 配列を入力します。

  • — 実数値のハイパーパラメーターの場合は real、整数値のハイパーパラメーターの場合は integer、categorical ハイパーパラメーターの場合は categorical を選択します。

  • 変換 — 変換を使用しない場合は none、対数変換を使用する場合は log を選択します。log を選択する場合、ハイパーパラメーター値は正でなければなりません。この設定では、ベイズ最適化アルゴリズムはハイパーパラメーターを対数スケールでモデル化します。

実験を実行すると、実験マネージャーはハイパーパラメーターの最適な組み合わせを検索します。各試行では、前の試行結果に基づいてハイパーパラメーター値の新しい組み合わせが使用されます。この例では、次のハイパーパラメーターを使用します。

  • Threshold は、しきい値を上回る応答データをすべてしきい値と同じ値に設定します。応答データが一定にならないように、しきい値を 150 以上に設定してください。この実験では、許容される一連の値の上限を 150、200、および 250 に設定するため、Threshold を categorical ハイパーパラメーターとしてモデル化します。

  • LSTMDepth は、ネットワークで使用される LSTM 層の数を示します。このハイパーパラメーターを 1 ~ 3 の整数で指定します。

  • NumHiddenUnits は、ネットワークで使用する隠れユニットの数 (タイム ステップごとに保存される情報の量) を決定します。隠れユニットの数を増やすと、データの過適合が発生して学習に時間がかかる可能性があります。隠れユニットの数を減らすと、データの適合不足が発生する可能性があります。このハイパーパラメーターを 50 ~ 300 の整数で指定します。

  • InitialLearnRate は、学習に使用される初期学習率を指定します。学習率が小さすぎる場合、学習に時間がかかります。学習率が大きすぎる場合、学習結果が準最適になったり、発散したりすることがあります。最適な学習率は、学習させるネットワークにも依りますが、データにも左右されます。この実験では、値が数桁の範囲にわたるため (0.001 ~ 0.1)、このハイパーパラメーターを対数スケールでモデル化します。

[ベイズ最適化オプション] では、実行する試行の最大時間 (秒単位) と最大回数を入力することで、実験の期間を指定できます。ベイズ最適化の能力を最大限に活用するには、目的関数の評価を少なくとも 30 回行います。

[セットアップ関数] セクションでは、実験用の学習データ、ネットワーク アーキテクチャ、および学習オプションを構成する関数を指定します。この関数を MATLAB® エディターで開くには、[編集] をクリックします。この関数のコードは、セットアップ関数にも示されています。セットアップ関数への入力は、ハイパーパラメーター テーブルのフィールドをもつ構造体です。この関数は、イメージ回帰問題用のネットワークに学習させるために使用する 4 つの出力を返します。この例のセットアップ関数には、以下のセクションが含まれています。

  • "データの読み込みと前処理" では、Turbofan Engine Degradation Simulation Data Set を https://ti.arc.nasa.gov/tech/dash/groups/pcoe/prognostic-data-repository/ [3] からダウンロードして解凍します。また、セットアップ関数のセクションでは、一定の値の特徴をフィルターで除外し、ゼロ平均と単位分散をもつように予測子データを正規化し、ハイパーパラメーター Threshold の数値を使用して応答データをクリップし、検証に使用する学習サンプルをランダムに選択します。

dataFolder = fullfile(tempdir,"turbofan");

if ~exist(dataFolder,"dir")
    mkdir(dataFolder);
    filename = matlab.internal.examples.downloadSupportFile("nnet", ...
        "data/TurbofanEngineDegradationSimulationData.zip");
    unzip(filename,dataFolder);
end

filenameTrainPredictors = fullfile(dataFolder,"train_FD001.txt");
[XTrain,YTrain] = processTurboFanDataTrain(filenameTrainPredictors);

XTrain = helperFilter(XTrain);
XTrain = helperNormalize(XTrain);

thr = str2double(params.Threshold);
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

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

idx = randperm(numel(XTrain),10);
XValidation = XTrain(idx);
XTrain(idx) = [];
YValidation = YTrain(idx);
YTrain(idx) = [];

  • "ネットワーク アーキテクチャの定義" では、sequence-to-sequence 回帰用の LSTM ネットワークのアーキテクチャを定義します。このネットワークは、まず LSTM 層があり、サイズが 100 の全結合層がそれに続き、ドロップアウトの確率が 0.5 のドロップアウト層がそれに続きます。ハイパーパラメーター LSTMDepth および NumHiddenUnits は、LSTM 層の数、および各層に含まれる隠れユニットの数を指定します。

numResponses = size(YTrain{1},1);
featureDimension = size(XTrain{1},1);
LSTMDepth = params.LSTMDepth;
numHiddenUnits = params.NumHiddenUnits;

layers = sequenceInputLayer(featureDimension);

for i = 1:LSTMDepth
    layers = [layers;lstmLayer(numHiddenUnits,OutputMode="sequence")];
end

layers = [layers
    fullyConnectedLayer(100)
    reluLayer()
    dropoutLayer(0.5)
    fullyConnectedLayer(numResponses)
    regressionLayer];

  • "学習オプションの指定" では、実験の学習オプションを定義します。ネットワークが深いほど収束に時間がかかるため、あらゆる深さのネットワークが確実に収束できるように、エポック数を 300 に設定します。この例では、30 回反復するごとにネットワークを検証します。初期学習率はハイパーパラメーター テーブルから取得した InitialLearnRate の値と等しく、15 エポックごとに 0.2 の係数で減少します。学習オプション ExecutionEnvironment"auto" に設定されていて、GPU が利用できる場合、実験は GPU で実行されます。そうでない場合、実験マネージャーは CPU を使用します。この例では、ネットワークの深さを比較し、多くのエポックで学習を行うため、GPU を使用すると学習時間を大幅に短縮できます。GPU を使用するには、Parallel Computing Toolbox™ とサポートされている GPU デバイスが必要です。詳細については、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。

maxEpochs = 300;
miniBatchSize = 20;

options = trainingOptions("adam", ...
    ExecutionEnvironment="auto", ...
    MaxEpochs=maxEpochs, ...
    MiniBatchSize=miniBatchSize, ...
    ValidationData={XValidation,YValidation}, ...
    ValidationFrequency=30, ...
    InitialLearnRate=params.InitialLearnRate, ...
    LearnRateDropFactor=0.2, ...
    LearnRateDropPeriod=15, ...
    GradientThreshold=1, ...
    Shuffle="never", ...
    Verbose=false);

[メトリクス] セクションは、実験結果を評価するオプションの関数を指定します。ネットワークの学習が完了するたびに、実験マネージャーによってこれらの関数が評価されます。この例では、メトリクス関数 MeanMaxAbsoluteError を使用し、RUL を過小予測または過大予測するネットワークを特定します。予測によって RUL が過少に見積もられると、エンジンのメンテナンスが必要よりも早い時期にスケジュールされる可能性があります。予測によって RUL が過大に見積もられると、運転中にエンジンが故障する可能性があり、その結果、高額なコストや安全性の懸念が生じる可能性があります。MeanMaxAbsoluteError メトリクスでは、このようなシナリオが発生する可能性を減らすために、最大絶対誤差を計算し、学習セット全体で平均化します。このメトリクスは、関数predictを呼び出し、学習セットから RUL 予測のシーケンスを作成します。その後、このメトリクス関数は、学習用の各応答シーケンスと予測された各応答シーケンスとの間の最大絶対誤差を計算してから、すべての最大絶対誤差の平均値を計算し、実際の応答と予測された応答との間の最大偏差を特定します。この関数を MATLAB エディターで開くには、メトリクス関数の名前を選択して [編集] をクリックします。この関数のコードは、最大絶対誤差の平均値の計算にも示されています。

実験の実行

実験を実行すると、実験マネージャーは、選択されたメトリクスについて、ハイパーパラメーターの最適な組み合わせを検索します。実験の各試行では、前の試行の結果に基づいてハイパーパラメーター値の新しい組み合わせが使用されます。

学習に時間がかかる場合があります。実験の期間を制限するには、[ベイズ最適化オプション] で試行の最大時間または最大回数を減らします。ただし、試行回数が 30 回未満の場合、ベイズ最適化アルゴリズムが最適なハイパーパラメーターのセットに収束しない可能性があることに注意してください。

既定では、実験マネージャーは一度に 1 つの試行を実行します。Parallel Computing Toolbox™ を使用している場合は、複数の試行を同時に実行したり、クラスター内のバッチ ジョブとして実験をオフロードしたりできます。

  • 一度に 1 つの実験を実行するには、"実験マネージャー" ツールストリップの [モード][Sequential] を選択し、[実行] をクリックします。

  • 複数の試行を同時に実行するには、[モード][Simultaneous] を選択し、[実行] をクリックします。現在の並列プールがない場合、実験マネージャーは既定のクラスター プロファイルを使用して並列プールを起動します。その後、実験マネージャーは、並列プールにあるワーカーと同じ数の同時試行を実行します。最良の結果を得るには、実験を実行する前に、GPU と同じ数のワーカーで並列プールを起動します。詳細については、実験マネージャーを使用したネットワークの並列学習GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。

  • 実験をバッチ ジョブとしてオフロードするには、[モード][Batch Sequential] または [Batch Simultaneous] を選択し、[クラスター][Pool Size] を指定して、[実行] をクリックします。詳細については、Offload Deep Learning Experiments as Batch Jobs to a Clusterを参照してください。

結果テーブルに、各試行のメトリクス関数の値が表示されます。実験マネージャーは、選択されたメトリクスが最適値である試行を強調表示します。たとえば、この実験では、23 番目の試行で最大絶対誤差が最小になっています。

実験の実行中に学習プロットを表示して各試行の進行状況を追跡するには、[結果の確認][学習プロット] をクリックします。ネットワークが深くなるにつれて、学習完了までに要する試行時間が長くなります。

結果の評価

結果テーブルに記載されている [MeanMaxAbsoluteError] の値は、ネットワークが RUL をどの程度、過小予測または過大予測したかを定量的に示しています。[検証 RMSE] の値は、未知のデータに対してネットワークがどの程度適切に汎化を行ったかを定量的に示しています。実験で得られた最良の結果を見つけるには、結果テーブルを並べ替え、[MeanMaxAbsoluteError][検証 RMSE] の値が最も小さい試行を選択します。

  1. [MeanMaxAbsoluteError] 列を選択します。

  2. 三角形のアイコンをクリックします。

  3. [昇順に並べ替え] を選択します。

同様に、検証 RMSE が最も小さい試行を見つけるには、[検証 RMSE] 列のドロップダウン メニューを開いて [昇順に並べ替え] を選択します。

両方の値が最小となる試行が 1 つもない場合は、両方のメトリクスに対する順位が良い試行を選択してください。たとえば、この結果を見ると、23 番目の試行は、平均最大絶対誤差が最小で、検証 RMSE は 7 番目に小さい値になっています。検証 RMSE がそれより低い試行を見ると、29 番目の試行のみが、同程度の平均最大絶対誤差になっています。どちらの試行が望ましいかは、平均最大絶対誤差と検証 RMSE のどちらの小さい値を重視するかによって決まります。

実験結果に関する観測結果を記録するには、注釈を追加します。

  1. 結果テーブルで、最適な結果が得られた試行の [MeanMaxAbsoluteError] セルを右クリックします。

  2. [注釈の追加] を選択します。

  3. [注釈] ペインで、テキスト ボックスに観測結果を入力します。

  4. [検証 RMSE] セルについても上記の手順を繰り返します。

実験の最適な試行をテストするには、学習済みのネットワークをエクスポートし、ランダムに選択した各テスト シーケンスについて、予測された応答シーケンスを表示します。

  1. 実験の最適な試行を選択します。

  2. [実験マネージャー] ツールストリップで、[エクスポート][学習済みネットワーク] をクリックします。

  3. ダイアログ ウィンドウで、エクスポートしたネットワークのワークスペース変数の名前を入力します。既定の名前は trainedNetwork です。

  4. エクスポートしたネットワーク、およびネットワークの Threshold の値を、補助関数 plotSequences への入力として使用します。この関数のコードを見るには、予知保全シーケンスのプロットを参照してください。たとえば、MATLAB コマンド ウィンドウで次のように入力します。

plotSequences(trainedNetwork,200)

この関数は、未知のテスト データに対する実際の応答および予測された応答のシーケンスをプロットします。

実験を閉じる

[実験ブラウザー] でプロジェクトの名前を右クリックし、[プロジェクトを閉じる] を選択します。実験マネージャーによって、プロジェクトに含まれるすべての実験と結果が閉じられます。

セットアップ関数

この関数は、実験用の学習データ、ネットワーク アーキテクチャ、および学習オプションを構成します。この関数への入力は、ハイパーパラメーター テーブルのフィールドをもつ構造体です。この関数は、イメージ回帰問題用のネットワークに学習させるために使用する 4 つの出力を返します。

function [XTrain,YTrain,layers,options] = SequenceRegressionExperiment_setup(params)

データの読み込みと前処理

dataFolder = fullfile(tempdir,"turbofan");

if ~exist(dataFolder,"dir")
    mkdir(dataFolder);
    filename = matlab.internal.examples.downloadSupportFile("nnet", ...
        "data/TurbofanEngineDegradationSimulationData.zip");
    unzip(filename,dataFolder);
end

filenameTrainPredictors = fullfile(dataFolder,"train_FD001.txt");
[XTrain,YTrain] = processTurboFanDataTrain(filenameTrainPredictors);

XTrain = helperFilter(XTrain);
XTrain = helperNormalize(XTrain);

thr = str2double(params.Threshold);
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

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

idx = randperm(numel(XTrain),10);
XValidation = XTrain(idx);
XTrain(idx) = [];
YValidation = YTrain(idx);
YTrain(idx) = [];

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

numResponses = size(YTrain{1},1);
featureDimension = size(XTrain{1},1);
LSTMDepth = params.LSTMDepth;
numHiddenUnits = params.NumHiddenUnits;

layers = sequenceInputLayer(featureDimension);

for i = 1:LSTMDepth
    layers = [layers;lstmLayer(numHiddenUnits,OutputMode="sequence")];
end

layers = [layers
    fullyConnectedLayer(100)
    reluLayer()
    dropoutLayer(0.5)
    fullyConnectedLayer(numResponses)
    regressionLayer];

学習オプションの指定

maxEpochs = 300;
miniBatchSize = 20;

options = trainingOptions("adam", ...
    ExecutionEnvironment="auto", ...
    MaxEpochs=maxEpochs, ...
    MiniBatchSize=miniBatchSize, ...
    ValidationData={XValidation,YValidation}, ...
    ValidationFrequency=30, ...
    InitialLearnRate=params.InitialLearnRate, ...
    LearnRateDropFactor=0.2, ...
    LearnRateDropPeriod=15, ...
    GradientThreshold=1, ...
    Shuffle="never", ...
    Verbose=false);

end

予知保全データのフィルターと正規化

補助関数 helperFilter は、定数値をもつ特徴を除去してデータをフィルターします。すべてのタイム ステップで一定のままである特徴は、学習に悪影響を与える可能性があります。

function [XTrain,XTest] = helperFilter(XTrain,XTest)

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

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

補助関数 helperNormalize は、ゼロ平均と単位分散をもつように、学習用およびテスト用の予測子を正規化します。

function [XTrain,XTest] = helperNormalize(XTrain,XTest)

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

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

最大絶対誤差の平均値の計算

このメトリクス関数は、学習済みネットワークの最大絶対誤差を計算し、学習セット全体で平均化します。

function metricOutput = MeanMaxAbsoluteError(trialInfo)

net = trialInfo.trainedNetwork;
thr = str2double(trialInfo.parameters.Threshold);

filenamePredictors = fullfile(tempdir,"turbofan","train_FD001.txt");
[XTrain,YTrain] = processTurboFanDataTrain(filenamePredictors);
XTrain = helperFilter(XTrain);
XTrain = helperNormalize(XTrain);

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

YPred = predict(net,XTrain,MiniBatchSize=1);
maxAbsErrors = zeros(1,numel(YTrain));
for i=1:numel(YTrain)
    absError = abs(YTrain{i}-YPred{i});
    maxAbsErrors(i) = max(absError);
end

metricOutput = mean(maxAbsErrors);
end

予知保全シーケンスのプロット

この関数は、実際の応答および予測された応答のシーケンスをプロットします。これにより、学習済みネットワークの性能を評価できます。この関数は、補助関数 helperFilterhelperNormalize を使用します。これらの関数のコードを見るには、予知保全データのフィルターと正規化を参照してください。

function plotSequences(net,threshold)

filenameTrainPredictors = fullfile(tempdir,"turbofan","train_FD001.txt");
filenameTestPredictors = fullfile(tempdir,"turbofan","test_FD001.txt");
filenameTestResponses = fullfile(tempdir,"turbofan","RUL_FD001.txt");

[XTrain,YTrain] = processTurboFanDataTrain(filenameTrainPredictors);
[XTest,YTest] = processTurboFanDataTest(filenameTestPredictors,filenameTestResponses);
[XTrain,XTest] = helperFilter(XTrain,XTest);
[~,XTest] = helperNormalize(XTrain,XTest);

for i = 1:numel(YTrain)
  YTrain{i}(YTrain{i} > threshold) = threshold;
  YTest{i}(YTest{i} > threshold) = threshold;
end

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

idx = randperm(100,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 threshold+25])
    title("Test Observation " + idx(i))
    xlabel("Time Step")
    ylabel("RUL")
end
legend(["Test Data" "Predicted"],Location="southwest")
end

参照

[1] Saxena, Abhinav, Kai Goebel, Don Simon, and Neil Eklund. "Damage Propagation Modeling for Aircraft Engine Run-to-Failure Simulation." 2008 International Conference on Prognostics and Health Management (2008): 1–9.

[2] Jozefowicz, Rafal, Wojciech Zaremba, and Ilya Sutskever. "An Empirical Exploration of Recurrent Network Architectures." Proceedings of the 32nd International Conference on Machine Learning (2015): 2342–2350.

参考

アプリ

関数

関連するトピック