このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。
Sequence-to-Sequence 深層学習 Simulink モデルの汎用 C/C++ の生成
この例では、深層学習 Simulink® モデルからサードパーティの深層学習ライブラリに依存しない汎用 C/C++ 実行可能ファイルを生成する方法を示します。この例では、ターボファン エンジンの残存耐用期間 (RUL) を予測します。これは、エンジンの各種センサーからのデータを表す入力時系列の各ステップにおいてサイクル単位で測定されます。
この例のビデオによるデモについては、Generate Generic C/C++ Code for Deep Learning Networks in Simulink を参照してください。
この例は、MATLAB® Coder™ の "Generate Generic C/C++ Code for Sequence-to-Sequence Regression That Uses Deep Learning" の例に基づいています。詳細については、Generate Generic C/C++ Code for Sequence-to-Sequence Regression That Uses Deep Learningを参照してください。
前提条件
PIL 検証用に以下が必要になります。
STMicroelectronics STM32F407G-Discovery、STM32F746G-Discovery、または STM32F769I-Discovery ボード
USB type A Mini-B ケーブル
USB TTL-232 ケーブル - TTL-232R 3.3V (STM32F4-Discovery ボードのシリアル通信)
Embedded Coder® Support Package for STMicroelectronics Discovery Boards。このサポート パッケージをインストールするには、MATLAB の [ホーム] タブの [環境] セクションにある [アドオン] メニューを使用します。
事前学習済みの RUL ネットワーク
この例では、事前学習済みの LSTM ネットワークを使用して、サイクル単位で測定されるエンジンの残存耐用期間を予測します。LSTM ネットワークは、200 の隠れユニットをもつ LSTM 層に続き、サイズ 50 の全結合層とドロップアウト確率 0.5 のドロップアウト層で構成されます。このネットワークに [1] に記載された "Turbofan Engine Degradation Simulation Data Set" を使用して学習させてあります。学習データには、100 個のエンジンのシミュレートされた時系列データが含まれています。各シーケンスの長さはさまざまで、故障するまで使用 (RTF) した事例全体に対応します。テスト データには、100 個の部分シーケンスと、各シーケンスの最後における対応する残存耐用期間の値が含まれています。ネットワークの学習の詳細については、深層学習を使用した sequence-to-sequence 回帰 (Deep Learning Toolbox)の例を参照してください。
net = coder.loadDeepLearningNetwork('rulNetwork.mat')
net = SeriesNetwork with properties: Layers: [6×1 nnet.cnn.layer.Layer] InputNames: {'sequenceinput'} OutputNames: {'regressionoutput'}
コード生成でサポートされるネットワーク、層、およびクラスの詳細については、コード生成でサポートされているネットワークとレイヤーを参照してください。
テスト データのダウンロードと準備
このセクションには、例で使用されるテスト データをダウンロードして準備する手順をまとめています。Turbofan Engine Degradation Simulation データ セットと前処理手順の詳細については、例深層学習を使用した sequence-to-sequence 回帰 (Deep Learning Toolbox)を参照してください。
データ セットのダウンロード
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)
学習データの平均と標準偏差の計算
以下の手順では、学習データの平均と標準偏差を使用してテスト予測子を正規化します。このため、まず学習データを使用して以下の正規化パラメーターを計算する必要があります。
学習データを読み込みます。各列に 1 つの観測値、各行に 1 つの特徴があります。定数値をもつ特徴を削除します。
filenamePredictors = fullfile(dataFolder,"train_FD001.txt"); [XTrain] = processTurboFanDataTrain(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);
テスト データの準備
この例に付加されている関数 processTurboFanDataTest
を使用して、テスト データを準備します。関数 processTurboFanDataTest
は filenamePredictors
と filenameResponses
からデータを抽出し、cell 配列 XValidate
と YValidate
を返します。これらの配列にはそれぞれ、テスト予測子と応答シーケンスが含まれます。
filenamePredictors = fullfile(dataFolder,"test_FD001.txt"); filenameResponses = fullfile(dataFolder,"RUL_FD001.txt"); [XValidate,YValidate] = processTurboFanDataTest(filenamePredictors,filenameResponses);
学習データから計算された idxConstant
を使用して、定数値をもつ特徴を削除します。学習データから計算されたパラメーター mu
と sig
を使用して、テスト予測子を正規化します。しきい値 150 でテストの応答をクリップします。ネットワークの学習時には、この同じクリッピングしきい値が学習データに使用されています。
thr = 150; for i = 1:numel(XValidate) XValidate{i}(idxConstant,:) = []; XValidate{i} = (XValidate{i} - mu) ./ sig; YValidate{i}(YValidate{i} > thr) = thr; end
入力検証データが Simulink のコード生成と互換性をもつように、独立した 100 個の各観測値のシーケンス長がゼロでパディングされ、均一なサイズの 17 行 303 列の入力配列が作成されます。
sequenceLengths = cellfun(@length,XValidate,'UniformOutput',true); maxSequenceLen = max(sequenceLengths); padFcn = @(x) [x,zeros(size(x,1),maxSequenceLen-size(x,2))]; XValidatePad = cellfun(padFcn,XValidate,'UniformOutput',false);
その後、パディングされた値が 17×303×100 の数値配列に変換されます。このデータを Simulink モデルにインポートするには、データ値と空の時間ベクトルを含む構造体変数を指定します。シミュレーション時、最初のタイム ステップの入力が配列の最初の 17 行 303 列の要素から読み取られます。次に 2 番目のタイム ステップの値が 2 番目の要素からというように、合計 100 ステップまで読み取られます。
simin.time = []; simin.signals.values = cell2mat(reshape(XValidatePad,1,1,[])); simin.signals.dimensions = size(XValidatePad{1});
予測用の Simulink モデル
ターボファン エンジンの残存耐用期間の予測に使用する Simulink モデルを次に示します。このモデルでは、rulNetwork
MAT ファイルから学習済みネットワークをインポートする Deep Neural Networks
ライブラリの Predict
ブロックを使用しています。さらに、ブロックの Mini-batch size
パラメーターは 1 に設定されています。
model = 'rulPredict';
open_system(model)
シミュレーションの実行
Simulink モデルを検証するには、シミュレーションを実行します。
set_param(model,'SimulationMode','Normal'); sim(model);
Simulink モデルの出力 YPred
にネットワークによる残存耐用期間の予測値が格納されます。この出力は、ゼロでパディングされた値からの結果を削除するために最初に平衡化されてから cell 配列に変換されます。
YPred_cell = squeeze(mat2cell(YPred,1,maxSequenceLen,ones(1,100))); for t = 1:length(sequenceLengths) YPred_cell{t}(:,sequenceLengths(t) + 1:end) = []; end
ランダムに選択された 4 つの観測値について、残存耐用期間 (RUL) の予測値をプロットし、それらを検証データと比較します。
observationIdx = randperm(100,4); rulExamplePlots(observationIdx,YValidate,YPred_cell);
コード生成のためのモデルの構成
サードパーティの深層学習ライブラリに依存しない C/C++ コードを生成して実行可能ファイルをビルドするには、Embedded Coder™ から汎用リアルタイム (ERT) ターゲットを選択します。
cs = getActiveConfigSet(model);
switchTarget(cs,'ert.tlc',[]);
コード生成の固有のパラメーターを構成します。MAT ファイルのログを設定すると、生成コードから MAT ファイルへのシミュレーション データのリダイレクトが有効になります。
set_param(cs,'TargetLang','C'); set_param(cs,'Toolchain','Automatically locate an installed toolchain'); set_param(cs,'ObjectivePriorities','Execution efficiency'); set_param(cs,'DLTargetLibrary','None'); set_param(cs,'GenerateReport','on'); set_param(cs,'CodeInterfacePackaging','Nonreusable function'); set_param(cs,'MatFileLogging', 'on');
Simulink モデルの生成とビルド
slbuild
コマンドを使用して Simulink モデルを生成およびビルドします。コード ジェネレーターは、ファイルを "ビルド フォルダー" に配置します。これは、現在の作業フォルダーの配下にある rulPredict_ert_rtw
という名前のサブフォルダーです。
evalc("slbuild('rulPredict')");
生成された実行可能ファイルの実行
生成された実行可能ファイルを実行します。rulPredict
実行可能ファイルが正常に実行されると、現在の作業フォルダーに rulPredict
MAT ファイルが作成されます。
if ispc status = system('rulPredict.exe'); else status = system('./rulPredict'); end
** created rulPredict.mat **
load('rulPredict.mat')
出力 rt_YPred
にネットワークによる残存耐用期間の予測値が格納されます。この出力は、ゼロでパディングされた値からの結果を削除するために最初に平衡化されてから cell 配列に変換されます。
rt_YPred_cell = squeeze(mat2cell(rt_YPred,1,maxSequenceLen,ones(1,100))); for t = 1:length(sequenceLengths) rt_YPred_cell{t}(:,sequenceLengths(t) + 1:end) = []; end
ランダムに選択された 4 つの観測値について、残存耐用期間 (RUL) の予測値をプロットし、それらを検証データと比較します。
rulExamplePlots(observationIdx,YValidate,rt_YPred_cell);
プロセッサインザループ (PIL) シミュレーションによるコード検証
展開コードの動作が設計と一致することを確認するために、組み込みボードで PIL シミュレーションを実行するように Simulink モデルを構成できます。PIL シミュレーションでは、STMicroelectronics® Discovery などの組み込みボードで生成コードが実行されます。PIL シミュレーションの結果が Simulink に転送され、シミュレーションとコード生成の結果の数値的等価性が検証されます。
この例では、STMicroelectronics Discovery ボードでの "Embedded Coder® Support Package for STMicroelectronics Discovery Boards" を使用した PIL 検証を示します。この例は STM32F746G-Discovery ボードで実行するように事前に構成されています。[モデル コンフィギュレーション パラメーター] の [ハードウェア実行] ペインにある [ハードウェア ボード] で選択することにより、サポートされている他の組み込みボードをこのモデルで使用するように構成できます。
テスト データの準備
PIL シミュレーション用に、この例では観測値をシーケンス長の順に並べ替えて最初の 10 個を選択します。これらの観測値がゼロでパディングされ、均一なサイズの 17 行 54 列の入力配列が作成されます。その後、パディングされた値が 17×54×10 の数値配列に変換されます。このデータを Simulink モデルにインポートするには、データ値と空の時間ベクトルを含む構造体変数を指定します。シミュレーション時、最初のタイム ステップの入力が配列の最初の 17 行 54 列の要素から読み取られます。次に 2 番目のタイム ステップの値が 2 番目の要素からというように、合計 10 ステップまで読み取られます。
[~,idx] = sort(cellfun(@length,XValidate)); XValidatePIL = XValidate(idx(1:10)); YValidatePIL = YValidate(idx(1:10)); sequenceLengths = cellfun(@length,XValidatePIL,'UniformOutput',true); maxSequenceLen = max(sequenceLengths); padFcn = @(x) [x,zeros(size(x,1),maxSequenceLen-size(x,2))]; XValidatePILPad = cellfun(padFcn,XValidatePIL,'UniformOutput',false); simin.time = []; simin.signals.values = cell2mat(reshape(XValidatePILPad,1,1,[])); simin.signals.dimensions = size(XValidatePILPad{1});
最上位モデルの PIL
rulPredict_pil
は、rulPredict
モデルを PIL 検証用に変更したバージョンです。テスト ベクトルを読み込むために、rulPredict_pil
モデルでは From Workspace
ブロックを Inport
ブロックに置き換えてあります。Inport
ブロックは、17 行 54 列の double データ型の配列を受け入れるように構成されています。
pilModel = 'rulPredict_pil';
open_system(pilModel);
rulPredict_pil
モデルを "STM32F467G-Discovery" ターゲット用に構成します。
cs = getActiveConfigSet(pilModel); set_param(cs,'HardwareBoard','STM32F746G-Discovery'); set_param(cs,'Toolchain','GNU Tools for ARM Embedded Processors');
STM32F4-Discovery ボードは、PIL 用に 2 種類の通信インターフェイスをサポートしています。ST-LINK とシリアルです。ST-LINK 通信インターフェイスでは、STM32F4-Discovery ボードをホスト コンピューターに接続するために使用する USB type A Mini-B ケーブルを除き、追加のケーブルやハードウェアを必要としません。シリアル通信インターフェイスでは、USB TTL-232 ケーブルが必要になります。シリアル通信インターフェイスを使用して PIL シミュレーションを実行すると、ST-LINK を使用して PIL シミュレーションを実行するよりもはるかに高速になります。この例はシリアル インターフェイスを使用するように構成されています。
さらに、[コンフィギュレーション パラメーター]、[ハードウェア実行]、[Target Hardware Resources]、[PIL] の [COM ポート] パラメーターを Windows コンピューターのシリアル インターフェイスのポート番号と一致するように設定する必要があります。
PIL シミュレーションの実行
PIL の結果をシミュレーションと比較するには、rulPredict_pil
モデルをノーマル モードで実行してから PIL モードで実行します。
set_param(cs,'LoadExternalInput','on'); set_param(cs, 'ExternalInput','simin'); set_param(pilModel,'SimulationMode','Normal'); sim(pilModel); YPred_ref = YPred_pil; set_param(pilModel,'SimulationMode','Processor-in-the-Loop (PIL)') sim(pilModel);
結果のプロット
出力 YPred_pil
と YPred_ref
にネットワークによる残存耐用期間の予測値が格納されます。この出力は、ゼロでパディングされた値からの結果を削除するために最初に平衡化されてから cell 配列に変換されます。
PIL による残存耐用期間 (RUL) の予測値をプロットし、それらを検証データと比較します。
YPred_ref_cell = squeeze(mat2cell(YPred_ref,1,maxSequenceLen,ones(1,10))); YPred_pil_cell = squeeze(mat2cell(YPred_pil,1,maxSequenceLen,ones(1,10))); for t = 1:length(sequenceLengths) YPred_ref_cell{t}(:,sequenceLengths(t) + 1:end) = []; YPred_pil_cell{t}(:,sequenceLengths(t) + 1:end) = []; end rulExamplePlots([1:10],YValidatePIL,YPred_pil_cell);
PIL シミュレーションによる誤差を計算し、結果をプロットします。
YPred_error = YPred_ref-YPred_pil; figure('Name', 'PIL Error') for i = 1:10 subplot(5,2,i) plot(YPred_error(:,:,i),'.-') maxerror = string(max(YPred_error(:,:,i))); ylim([-1e-4 1e-4]) title("Test Observation " + i) xlabel("Time Step") ylabel("Difference") end legend(["Difference in Simulation Modes"],'Location','southeast')
サポート関数
function rulExamplePlots(observationIdx,YTest,YPred) N = numel(observationIdx); figure for i = 1:N subplot(N/2,2,i) plot(YTest{observationIdx(i)},'--') hold on plot(YPred{observationIdx(i)},'.-') hold off ylim([0 175]) title("Test Observation " + observationIdx(i)) xlabel("Time Step") ylabel("RUL") end legend(["Test Data" "Predicted"],'Location','southeast') end
参考文献
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.