Main Content

モデルベース デザインを使用した機械学習モデルの検証と妥当性確認

この例では、Simulink® を使用して機械学習モデルの検証と妥当性確認を行う方法を示します。検証済みの機械学習は、数学的に指定された要件に関する正確性の保証が強力で理想的に証明可能なシステムの設計の目標です [1]。機械学習によって多くのタスクで最適な結果が得られるため、機械学習モデルの量産での展開はセーフティ クリティカルな用途にとって重要です。ただし、以下の理由により、これは難しい場合があります。

  • システムの正確性を検証してから、量産でのその妥当性を確認する必要がある。

  • 医療、航空宇宙関連、防衛などの特定の用途の場合、業界が承認した規則に基づいてシステムを認定する必要がある。認証要件の詳細については、業界標準への準拠に関する詳細を参照してください。

機械学習モデルのシステム設計では、この例で示すように、一般的なモデルベース デザイン ワークフローに新しいタスクが追加されます。

  • 機械学習モデルの学習用にデータを準備します。データを使用して機械学習モデルに学習させる前に、そのデータのクリーニングと準備が必要となることがあります。十分なデータを利用できない場合は、シミュレーションによって生成されたデータを使用する必要があります。

  • 機械学習モデルに学習させます。モデルの学習中に、設計の調整や複数の機械学習モデルの学習と比較が必要となることがあります。

  • モデルの検証と妥当性確認を行います。機械学習コンポーネントを大規模で複雑なシステムに統合する場合は、コンポーネントレベルとシステムレベルのシミュレーションおよびテストの実行が必要となることがあります。また、機械学習アルゴリズムのメモリ フットプリントと速度を測定して、組み込み環境におけるその効率性を評価する必要もあります。

データの準備

この例では、環境が発している音に基づいて環境を分類する音響シーン分類 (ASC) タスクのモデルを作成します。ASC は、デバイス、ロボット、その他の用途におけるコンテキスト アウェアネスの基礎となる汎用のマルチクラス分類問題です [2]

データ セットのダウンロード

この例を実行するには、まず、データ セットをダウンロードしなければなりません [2]。このデータ セット全体のサイズは約 15.5 GB です。お使いのマシンとインターネット接続によっては、データのダウンロードに約 4 時間かかることがあります。

tempdir コマンドは一時フォルダーを作成しますが、このフォルダーは自動削除される可能性があります。ダウンロードしたデータ セットを保持するには、一時フォルダー (downloadFolder) をローカル ディレクトリに変更します。

downloadFolder = tempdir; 
dataset_asc = fullfile(downloadFolder,"TUT-acoustic-scenes-2017");

if ~datasetExists(dataset_asc)
    disp("Downloading TUT-acoustic-scenes-2017 (15.5 GB) ...")
    HelperDownload_TUT_acoustic_scenes_2017(dataset_asc);
end
Downloading TUT-acoustic-scenes-2017 (15.5 GB) ...
Downloading development set ... 
	Downloading 1 of 13 ... complete.
	Downloading 2 of 13 ... complete.
	Downloading 3 of 13 ... complete.
	Downloading 4 of 13 ... complete.
	Downloading 5 of 13 ... complete.
	Downloading 6 of 13 ... complete.
	Downloading 7 of 13 ... complete.
	Downloading 8 of 13 ... complete.
	Downloading 9 of 13 ... complete.
	Downloading 10 of 13 ... complete.
	Downloading 11 of 13 ... complete.
	Downloading 12 of 13 ... complete.
	Downloading 13 of 13 ... complete.
Download of development set complete.
Time elapsed:  105 minutes

Downloading evaluation set ... 
	Downloading 1 of 6 ... complete.
	Downloading 2 of 6 ... complete.
	Downloading 3 of 6 ... complete.
	Downloading 4 of 6 ... complete.
	Downloading 5 of 6 ... complete.
	Downloading 6 of 6 ... complete.
Download of evaluation set complete.
Time elapsed:   35 minutes

メタデータの読み込み

学習セットのメタデータから table を作成します。table 変数は FileNameAcousticScene、および SpecificLocation という名前にします。

trainMetaData = readtable(fullfile(dataset_asc,"TUT-acoustic-scenes-2017-development","meta"), ...
    Delimiter={'\t'}, ...
    ReadVariableNames=false);
trainMetaData.Properties.VariableNames = ["FileName","AcousticScene","SpecificLocation"];
head(trainMetaData)
             FileName             AcousticScene    SpecificLocation
    __________________________    _____________    ________________

    {'audio/b020_90_100.wav' }      {'beach'}          {'b020'}    
    {'audio/b020_110_120.wav'}      {'beach'}          {'b020'}    
    {'audio/b020_100_110.wav'}      {'beach'}          {'b020'}    
    {'audio/b020_40_50.wav'  }      {'beach'}          {'b020'}    
    {'audio/b020_50_60.wav'  }      {'beach'}          {'b020'}    
    {'audio/b020_30_40.wav'  }      {'beach'}          {'b020'}    
    {'audio/b020_160_170.wav'}      {'beach'}          {'b020'}    
    {'audio/b020_170_180.wav'}      {'beach'}          {'b020'}    

テスト セットのメタデータから table を特定します。table 変数は FileNameAcousticScene、および SpecificLocation という名前にします。

testMetaData = readtable(fullfile(dataset_asc,"TUT-acoustic-scenes-2017-evaluation","meta"), ...
    Delimiter={'\t'}, ...
    ReadVariableNames=false);
testMetaData.Properties.VariableNames = ["FileName","AcousticScene","SpecificLocation"];
head(testMetaData)
         FileName         AcousticScene    SpecificLocation
    __________________    _____________    ________________

    {'audio/1245.wav'}      {'beach'}          {'b174'}    
    {'audio/1456.wav'}      {'beach'}          {'b174'}    
    {'audio/1318.wav'}      {'beach'}          {'b174'}    
    {'audio/967.wav' }      {'beach'}          {'b174'}    
    {'audio/203.wav' }      {'beach'}          {'b174'}    
    {'audio/777.wav' }      {'beach'}          {'b174'}    
    {'audio/231.wav' }      {'beach'}          {'b174'}    
    {'audio/768.wav' }      {'beach'}          {'b174'}    

学習セットとテスト セットに共通する録音位置があるかどうかを確認します。

sharedRecordingLocations = intersect(testMetaData.SpecificLocation,trainMetaData.SpecificLocation);
disp("Number of specific recording locations in both training and test sets = " + numel(sharedRecordingLocations))
Number of specific recording locations in both training and test sets = 0

テスト セット内の特定の録音位置は、学習セット内の特定の録音位置と交差しません。この設定により、学習済みのモデルを実世界のシナリオに一般化できるかどうかを検証しやすくなります。

各メタデータ table の最初の変数には、データのファイル名が含まれています。ファイル名とファイル パスを連結します。

trainFilePaths = fullfile(dataset_asc,"TUT-acoustic-scenes-2017-development",trainMetaData.FileName);
testFilePaths = fullfile(dataset_asc,"TUT-acoustic-scenes-2017-evaluation",testMetaData.FileName);

オーディオ データストアの作成

メタデータにはデータ セットに含まれていないファイルが格納されている場合があります。存在しないファイルに対応するファイル パスと音響シーン ラベルを削除します。

ads = audioDatastore(dataset_asc,IncludeSubfolders=true);
allFiles = ads.Files;

trainIdxToRemove = ~ismember(trainFilePaths,allFiles);
trainFilePaths(trainIdxToRemove) = [];
trainLabels = categorical(trainMetaData.AcousticScene);
trainLabels(trainIdxToRemove) = [];

testIdxToRemove = ~ismember(testFilePaths,allFiles);
testFilePaths(testIdxToRemove) = [];
testLabels = categorical(testMetaData.AcousticScene);
testLabels(testIdxToRemove) = [];

学習セットとテスト セットのためのオーディオ データストアを作成します。audioDatastore (Audio Toolbox)Labels プロパティを音響シーンに設定します。countEachLabel (Audio Toolbox)を呼び出して、学習セットとテスト セット両方のラベルが均等に分布していることを確認します。

adsTrain = audioDatastore(trainFilePaths, ...
    Labels=trainLabels, ...
    IncludeSubfolders=true);
display(countEachLabel(adsTrain))
  15×2 table

         Label          Count
    ________________    _____

    beach                312 
    bus                  312 
    cafe/restaurant      312 
    car                  312 
    city_center          312 
    forest_path          312 
    grocery_store        312 
    home                 312 
    library              312 
    metro_station        312 
    office               312 
    park                 312 
    residential_area     312 
    train                312 
    tram                 312 
adsTest = audioDatastore(testFilePaths, ...
    Labels=categorical(testMetaData.AcousticScene), ...
    IncludeSubfolders=true);
display(countEachLabel(adsTest))
  15×2 table

         Label          Count
    ________________    _____

    beach                108 
    bus                  108 
    cafe/restaurant      108 
    car                  108 
    city_center          108 
    forest_path          108 
    grocery_store        108 
    home                 108 
    library              108 
    metro_station        108 
    office               108 
    park                 108 
    residential_area     108 
    train                108 
    tram                 108 

データ セットのサイズを小さくすると、実行時間を短縮できますが、精度に影響する可能性があります。一般に、開発とデバッグではデータ セットのサイズを小さくすることをお勧めします。データ セットのサイズを小さくするには、speedupExampletrue に設定します。この例ではデータ セット全体を使用します。

speedupExample = false;
if speedupExample
    adsTrain = splitEachLabel(adsTrain,20);
    adsTest = splitEachLabel(adsTest,10);
end

特徴量の抽出

オーディオ データから特徴量を抽出し、Statistics and Machine Learning Toolbox™ の近似関数を使用して機械学習モデルに学習させる必要があります。この例では、ウェーブレット散乱を使用して特徴量を抽出します。[5] に示すように、ウェーブレット散乱は音響シーンの表現に優れています。

read (Audio Toolbox)を呼び出して、学習セットからオーディオ ファイルのデータとサンプル レートを取得します。データ セットに含まれる各オーディオ ファイルは、一貫したサンプル レートと再生時間 (10 秒) をもちます。オーディオを正規化して再生します。対応するラベルを表示します。

[data,adsInfo] = read(adsTrain);
data = data./max(data,[],"all");

fs = adsInfo.SampleRate;
sound(data,fs)

disp("Acoustic scene = " + string(adsTrain.Labels(1)))
Acoustic scene = beach

reset (Audio Toolbox)を呼び出して、データストアを初期状態に戻します。

reset(adsTrain)

waveletScattering (Wavelet Toolbox)オブジェクトを定義します。不変スケールと品質係数は、試行錯誤によって決定されています。

sf = waveletScattering(SignalLength=size(data,1), ...
    SamplingFrequency=fs,InvarianceScale=0.75,QualityFactors=[4 1]);

オーディオ信号をモノラルに変換します。次にfeatureMatrix (Wavelet Toolbox)を呼び出して、散乱分解フレームワーク sf の散乱係数を返します。

dataMono = mean(data,2);
scatteringCoeffients = featureMatrix(sf,dataMono,Transform="log");

10 秒間のオーディオ クリップにわたる散乱係数を平均化します。

featureVector = mean(scatteringCoeffients,2);
disp("Number of wavelet features per 10-second clip = " + numel(featureVector));
Number of wavelet features per 10-second clip = 286

補助関数 HelperWaveletFeatureVector は、これらの手順を単一のオーディオ クリップに対して実行します。cellfunHelperWaveletFeatureVectortall配列を使用して、すべてのデータに対して特徴抽出手順を並列処理します。

tall 配列に対する計算を実行する場合、MATLAB® は並列プール (Parallel Computing Toolbox™ がある場合は既定) またはローカルの MATLAB セッションを使用します。この例では並列プールを使用します。ローカルの MATLAB セッションを使用して例を実行するには、関数mapreducerを使用してグローバルな実行環境を変更します。

学習セットとテスト セット内のすべてのデータのウェーブレット特徴ベクトルを抽出します。

train_set_tall = tall(adsTrain);
Starting parallel pool (parpool) using the 'Processes' profile ...
17-Jan-2024 12:03:54: Job Queued. Waiting for parallel pool job with ID 2 to start ...
Connected to parallel pool with 6 workers.
scatteringTrain = cellfun(@(x)HelperWaveletFeatureVector(x,sf),train_set_tall,UniformOutput=false);
xTrain = gather(scatteringTrain);
Evaluating tall expression using the Parallel Pool 'Processes':
- Pass 1 of 1: Completed in 21 min 31 sec
Evaluation completed in 21 min 31 sec
xTrain = cell2mat(xTrain')';
test_set_tall = tall(adsTest);
scatteringTest = cellfun(@(x)HelperWaveletFeatureVector(x,sf),test_set_tall,UniformOutput=false);
xTest = gather(scatteringTest);
Evaluating tall expression using the Parallel Pool 'Processes':
- Pass 1 of 1: Completed in 7 min 29 sec
Evaluation completed in 7 min 29 sec
xTest = cell2mat(xTest')';

機械学習モデルの学習

機械学習モデルの学習時には、複数のモデルに学習させてから、テスト データに対する精度に基づいて最適なモデルを選択できます。ただし、ターゲット環境が組み込みシステムである場合、またはリソース (メモリやハードウェアの速度など) が限られている場合は、複数のモデルを保持し、モデルベース デザイン ツールを使用してさらに比較することをお勧めします。検証と妥当性確認を実行して選択肢を絞り込み、許容できる精度が得られてターゲット環境に最適な、特定用途向けの要件を満たすモデルを選択できます。

この例では、次の 7 つのモデル タイプに学習させます。

  • 2 層ニューラル ネットワーク (NN)

  • 線形判別

  • 判別分析学習器をもつランダム部分空間アンサンブル

  • bag of trees (アンサンブル)

  • 線形サポート ベクター マシン (SVM)

  • ロジスティック回帰

  • 決定木

7 つのモデルに学習させて cell 配列 multiMdls に保存します。

MdlNames = ["Bilayered NN","Linear Discriminant","Subspace Discriminant", ...
    "Bag of Trees","Linear SVM","Logistic Regression","Decision Tree"]';
yTrain = grp2idx(adsTrain.Labels);
yTest = grp2idx(adsTest.Labels);

rng("default") % For reproducibility
multiMdls = cell(7,1);

% Bilayered NN
multiMdls{1} = fitcnet(xTrain,yTrain,LayerSizes=25,Standardize=true);

% Linear Discriminant
multiMdls{2} = fitcdiscr(xTrain,yTrain);

% Subspace Discriminant
multiMdls{3} = fitcensemble(xTrain,yTrain, ...
    Method="Subspace",Learners="discriminant", ...
    NumLearningCycles=30,NPredToSample=25);

% Bag of Trees
multiMdls{4} = fitcensemble(xTrain,yTrain, ...
    Method="Bag",Learners="tree", ...
    NumLearningCycles=50);

% Linear SVM
multiMdls{5} = fitcecoc(xTrain,yTrain);

% Logistic Regression
tLinear = templateLinear(Learner="logistic");
multiMdls{6} = fitcecoc(xTrain,yTrain,Learners=tLinear);

% Decision Tree
multiMdls{7} = fitctree(xTrain,yTrain);

モデルの精度とサイズの測定

補助関数 HelperMdlMetrics を使用して、テスト データでモデルをテストします。この関数は、モデルの精度 (パーセント) とモデルのサイズ (KB) を含むモデル メトリクスの table を返します。

tbl = HelperMdlMetrics(multiMdls,xTest,yTest);
tbl.Properties.RowNames = MdlNames;

出力の表示形式を bank と指定し、table tbl の値を表示するときに数値が整列して表示されるようにします。

format("bank")

モデルの精度とモデルのサイズを表示します。

disp(tbl)
                             Accuracy    Model Size
                             ________    __________

    Bilayered NN              57.72       10617.50 
    Linear Discriminant       74.69       12519.41 
    Subspace Discriminant     69.20       22065.51 
    Bag of Trees              50.37       37593.81 
    Linear SVM                58.40       11452.87 
    Logistic Regression       21.23        1934.52 
    Decision Tree             40.56       10728.95 

既定の表示形式に戻します。

format("default")

予測のための Simulink へのモデルのインポート

精度とモデルのサイズのメトリクスを使用して、Simulink での展開に最適な機械学習モデルを選択できます。Simulink で複数の学習済みモデルを使用することで、速度やメモリ フットプリントなどの追加のメトリクスを使用してモデルのパフォーマンスを比較し、選択肢をさらに絞り込むことができます。

この例では、multiMdls 内にあるすべての学習済み機械学習モデル用の予測ブロックを含む Simulink モデル slexVandVPredictExample.slx が用意されています。

データの準備

Simulink モデルの配列の形式で入力信号 (input) を作成します。配列の最初の列には、観測値がモデルに入力された時点を含む timeVector 変数が格納されます。他の列にはウェーブレット特徴ベクトルが格納されます。

timeVector = (0:length(xTest)-1)';
input = [timeVector,xTest];

MATLAB Function ブロック用のモデルの保存

Statistics and Machine Learning Toolbox には、ニューラル ネットワーク、線形判別、アンサンブル (bag of trees)、SVM、ロジスティック回帰、および決定木モデル用の予測ブロックが用意されています。

部分空間判別モデルの場合は、MATLAB Function ブロックを使用してモデルの予測機能を実装する必要があります。関数 saveLearnerForCoder を使用してモデルを MATLAB 形式のバイナリ ファイル (MAT ファイル) に保存し、関数 loadLearnerForCoder を使用してこのファイルを MATLAB Function ブロックに読み込みます。

saveLearnerForCoder(multiMdls{3},"subDiscMdl.mat")

Simulink モデルのシミュレート

Simulink モデル slexVandVPredictExample.slx を開きます。

open_system("slexVandVPredictExample.slx")

モデルをシミュレートし、シミュレーション出力をワークスペースにエクスポートします。

simOut = sim("slexVandVPredictExample.slx");

モデルを閉じます。

close_system("slexVandVPredictExample.slx")

Simulink プロファイラーと SIL/PIL マネージャーを使用したパフォーマンスの確認

Simulink モデルと生成コードの両方の実行時間を使用してモデルのパフォーマンスを確認できます。

Simulink プロファイラーを使用した Simulink での時間プロファイルの実行

[Simulink プロファイラー] では、モデルとブロックの実行を調べ、シミュレーションのパフォーマンスを低下させている可能性のある問題を特定できます。このプロセスは、学習済み機械学習モデル用の予測ブロックをシミュレーション速度の観点で比較するのに役立ちます。

Simulink モデル slexVandVPredictExample.slx を開きます。

open_system("slexVandVPredictExample.slx")

[Simulink プロファイラー] を起動します。

  1. [デバッグ] タブで、[パフォーマンス アドバイザー][Simulink プロファイラー] を選択します。

  2. [プロファイラー] タブで、[プロファイル] をクリックします。

シミュレーションが完了したら、[プロファイラー レポート] ペインが開き、モデルのシミュレーション プロファイルが表示されます。[パス] 列で、Prediction サブシステムを展開します。ペインに、予測ブロックのパフォーマンス時間が最も低速なものから最も高速なものへの降順で表示されます。

この例では、Bag of Trees モデルが最も低速で、Neural Network モデルが最も高速です。その後に Decision Tree モデル、Subspace Discriminant モデルと続きます。

SIL/PIL マネージャーを使用した生成コードでの時間プロファイルの実行

シミュレーション中、MATLAB Function ブロックを使用する予測ブロックは通常、マスク サブシステムの実装を使用するブロックよりも短時間で実行されます。この相違は、MATLAB Function ブロックはシミュレーション用に実行される前に C コードに変換され、そのコードが MEX ファイルにコンパイルされるために生じます。組み込みアプリケーション用のブロックのパフォーマンス比較に関心があるとします。ソフトウェアインザループ (SIL) プロファイリングを有効にした後、すべてのブロックからコードを生成し、SIL シミュレーションを使用してパフォーマンスを比較できます。

SIL モード シミュレーションのコード実行プロファイリングを構成するには、次を行います。

  1. [コンフィギュレーション パラメーター] ダイアログ ボックスを開く。Simulink エディターの [モデル化] タブで、[モデル設定] をクリックします。

  2. [コード生成][検証] ペインの [コード実行時間プロファイリング] で、[タスク実行時間を計測する] チェック ボックスをオンにします。

  3. 関数の実行時間について、[関数の実行時間を計測する] リストから [概略 (参照モデルおよびサブシステムのみ)] を選択します。このオプションを使用すると、メイン モデル コンポーネントに対して生成された関数コードを解析できます。

  4. [ワークスペース変数] フィールドで、変数名を「executionProfile」と指定します。シミュレーションを実行すると、この名前の変数が MATLAB ベース ワークスペースに生成されます。タイプ coder.profile.ExecutionTime のオブジェクトであるこの変数には、実行時間計測値が格納されます。[データのインポート/エクスポート] ペインの [ワークスペースまたはファイルに保存][単一のシミュレーション出力] チェック ボックスをオンにし、変数名を「out」と指定します。変数 executionProfile が変数 out (Simulink.SimulationOutput オブジェクト) にも作成されます。

  5. [コード生成][検証] ペインの [コード実行時間プロファイリング] で、Save options (Embedded Coder)リストから [メトリクスのみ] を選択します。このオプションは、Simulink とターゲット アプリケーションの間の通信チャネルで使用される帯域幅の削減に役立ちます。

  6. [ハードウェア実行] ペインで、モデルによって表されるシステムの実装に使用するハードウェアのタイプを選択します。この例では既定値 x86–64 (Windows64) を使用します。

  7. [OK] をクリックします。

詳細については、Create Execution-Time Profile for Generated Code (Embedded Coder)を参照してください。

関数の実行データを生成するには、生成コードに測定プローブを挿入する必要があります。[関数のパッケージ化] フィールド ([ブロック パラメーター] ダイアログ ボックスの [コード生成] タブにある) を [再利用できない関数] または [再利用可能な関数] に設定した場合にのみ、ソフトウェアでは Atomic サブシステムの測定プローブを挿入できます。各予測ブロックに対して詳細な実行プロファイリングを有効にするには、予測ブロックをサブシステム内に配置します。MATLAB Function ブロックではない予測ブロックごとに、次を行います。

  1. ブロックを右クリックし、[サブシステムとモデル参照][選択からサブシステムを作成] を選択します。

  2. サブシステムの名前を予測ブロックと同じ名前に変更します。

MATLAB Function ブロック (部分空間判別モデル) はサブシステム内に配置する必要はありません。Subsystem ブロックと MATLAB Function ブロックごとに、次を行います。

  1. [ブロック パラメーター] ダイアログ ボックスを開きます。ブロックを右クリックし、[ブロック パラメーター (Subsystem)] を選択します。

  2. [メイン] タブで、[Atomic サブシステムとして扱う] チェック ボックスをオンにします。

  3. [コード生成] タブで、[関数のパッケージ化][再利用できない関数] に変更します。次に、[OK] をクリックします。

MATLAB Function ブロックを使用する予測の実装では、コード生成用に可変信号のサポートを有効にする必要があります。コード生成のサポートを有効にするには、次を行います。

  1. [コンフィギュレーション パラメーター] ダイアログ ボックスを開く。Simulink エディターの [モデル化] タブで、[モデル設定] をクリックします。

  2. [コード生成][インターフェイス] ペインの [ソフトウェア環境] で、[可変サイズの信号] チェック ボックスをオンにします。

モデルを閉じます。

close_system("slexVandVPredictExample.slx")

この例では、SIL プロファイリング用に構成された Simulink モデル slexVandVPredictSILProfilingExample.slx が用意されています。Simulink モデルを開きます。

open_system("slexVandVPredictSILProfilingExample.slx")

モデルを SIL モードで実行してプロファイリング情報を収集します。[アプリ] タブの [コードの検証とテスト] グループで、[SIL/PIL マネージャー] アプリを開きます。[SIL/PIL] タブで、[準備] セクションの [SIL/PIL モード] オプションが [ソフトウェアインザループ (SIL)] に設定されていることを確認します。[SIL/PIL] タブで、[検証の実行] をクリックしてシミュレーションを実行し、プロファイリング メトリクスをログに記録します。

SIL 検証が完了したら、[SIL/PIL] タブの [結果] セクションで、[実行の比較] をクリックして [コード プロファイル アナライザー] を選択します。[コード プロファイル アナライザー] ウィンドウの [解析] セクションで、[関数の実行] を選択します。ブロックのリストの末尾に移動して予測ブロックを見つけ、それらの実行時間を比較します。

結果テーブルに示すように、Bag of Trees モデルは最も低速な実装ではなく、これは Simulink プロファイラーの結果とは異なります。今回、最も高速な実装は Decision Tree で、その後に Neural Network が続きます。Linear Discriminant と Subspace Discriminant が最も低速となりました。

各ブロックの合計実行時間を表示します。この例では、予測ブロックは modelTimeProfile.mat に格納されているコード実行プロファイリング オブジェクト内のセクション 9 ~ 15 です。

load("modelTimeProfile.mat")
executionProfileLog = out.executionProfile;
ep = executionProfileLog.Sections(9:end);
blockNames = {ep.Name}'
blockNames = 7×1 cell
    {'Neural Network'       }
    {'Bag of Trees'         }
    {'Linear SVM'           }
    {'Logistic Regression'  }
    {'Decision Tree'        }
    {'Linear Discriminant'  }
    {'Subspace Discriminant'}

totalExeTimes = [ep.TotalExecutionTimeInTicks]
totalExeTimes = 1×7 uint64 row vector

      9431774     47950926    113617869    111311067      1326041   1074698585    367090280

[totalExeTimesSorted,blockIndSorted] = sort(totalExeTimes);
exeTimeTable = table(blockNames(blockIndSorted),totalExeTimesSorted');
disp(exeTimeTable)
              Var1                  Var2   
    _________________________    __________

    {'Decision Tree'        }       1326041
    {'Neural Network'       }       9431774
    {'Bag of Trees'         }      47950926
    {'Logistic Regression'  }     111311067
    {'Linear SVM'           }     113617869
    {'Subspace Discriminant'}     367090280
    {'Linear Discriminant'  }    1074698585

モデルを閉じます。

close_system("slexVandVPredictSILProfilingExample.slx")

静的コード メトリクス レポートを使用したランタイム メモリ使用量の測定

低電力ハードウェアに展開する組み込みアプリケーションにとって重要なもう 1 つの測定は、ターゲット ハードウェアでのアプリケーションの実行に必要なランタイム メモリの量です。Embedded Coder® には、組み込み C/C++ コードの生成時にアプリケーションのランタイム メモリ フットプリントをメトリクス レポートの形式で測定するための機能が用意されています。

コード ジェネレーターは、生成された C/C++ コードの静的解析を実行し、HTML コード生成レポートの [静的コード メトリクス レポート] セクションにメトリクスを示します。このメトリクスを Prediction サブシステム内の各予測ブロックに対して有効にするには、SIL/PIL マネージャーを使用した生成コードでの時間プロファイルの実行の説明に従って、各予測ブロックを Atomic サブシステム内に配置し、[関数のパッケージ化][再利用できない関数] に変更する必要があります。生成コードのプロファイリング用に構成された Simulink モデル slexVandVPredictSILProfilingExample.slx を使用します。Simulink モデルを開きます。

open_system("slexVandVPredictSILProfilingExample.slx")

静的コード メトリクス レポートを生成するには、次を行います。

  1. [コンフィギュレーション パラメーター] ダイアログ ボックスを開く。Simulink エディターの [モデル化] タブで、[モデル設定] をクリックします。

  2. [コード生成] ペインの [ターゲットの選択] で、システム ターゲット ファイルを ert.tlc として指定します。

  3. [コード生成][レポート] ペインで、[静的コード メトリクスの生成] チェック ボックスをオンにします。

  4. Prediction サブシステムを右クリックし、[C/C++ コード][このサブシステムをビルド] を選択します。

コードが生成されると、コード生成レポートが開きます。[Content] セクションで、[静的コード メトリクス レポート] に移動します。レポートの最後にある [関数情報] セクションに移動し、テーブルの [累積スタック サイズ] 列を検査します。スタック サイズは、既定では降順で並べ替えられています。

スタック メモリの使用量が最も多いのは Neural Network ブロックで、その後に Linear SVM ブロック、Subspace Discriminant ブロックと続きます。スタック メモリの使用量が最も少ないのは Decision Tree ブロックで、その後に僅差で Bag of Trees ブロックが続きます。

静的コード メトリクスによって報告されるスタック メモリは、アプリケーションが実行中に使用するメモリの量です。アプリケーションには、実行時に変更されない機械学習モデル パラメーターなどの追加データが含まれている場合があります。このタイプのデータは通常、フラッシュ メモリや ROM などの読み取り専用メモリに保存され、レポートには含まれません。

一般的な組み込みシステムでは、読み取り専用メモリは通常、ランタイム メモリよりも豊富で安価です。機械学習モデルに大規模な配列をもつパラメーターが多数含まれている場合は、アプリケーションの展開が問題となる可能性があります。アプリケーションがハードウェアに適合できるかどうかを調べる最適な方法は、アプリケーションをコンパイルしてビルドし、組み込みシステムに展開することです。読み取り専用アプリケーション データは、通常、コード生成レポートで接尾辞 "_data.c" が付いているソース ファイルで定義されています。このデータには、[データ ファイル] のレポートの [コード] セクションでアクセスできます。

機械学習モデルでのデータ メモリ使用量を間接的に比較するには、機械学習モデル パラメーターのサイズを測定します。この例のモデルのサイズについては、モデルの精度とサイズの測定を参照してください。モデルをサイズの昇順に並べ替えます。

sortrows(tbl,"Model Size")
ans=7×2 table
                             Accuracy    Model Size
                             ________    __________

    Logistic Regression       21.235       1934.5  
    Bilayered NN              57.716        10618  
    Decision Tree             40.556        10729  
    Linear SVM                58.395        11453  
    Linear Discriminant       74.691        12519  
    Subspace Discriminant     69.198        22066  
    Bag of Trees               50.37        37594  

Logistic Regression モデルが最小で、Bag of Trees モデルが最大です。メモリ使用量について判定を行う際は、スタック メモリと読み取り専用メモリの両方のフットプリントを確認します。また、最大限の情報を得たうえで判定を行うには、ターゲット ハードウェアで使用可能な RAM (スタックの場合) と ROM (フラッシュまたは読み取り専用メモリ) の量を検討します。

モデルを閉じます。

close_system("slexVandVPredictSILProfilingExample.slx")

単精度データ型の使用によるメモリ使用量の最適化

この例の Simulink モデルでは、既定では倍精度を使用しています。マスク サブシステムの実装で予測ブロックを使用するときは、さまざまなデータ型オプションを選択できます。単精度データ型を使用すると、モデルのメモリ フットプリントを大幅に削減できます。多くの ARM ベースのプロセッサは単精度の用途向けに最適化されているため、単精度に変換すると実行速度も向上します。

予測アルゴリズムで機械学習モデルのパラメーターや演算に単精度データ型を使用するには、ブロック ダイアログ ボックスにあるデータ型オプションを single に変更します。この例では 1 から 15 までの範囲の数値をクラス ラベルとして使用しているため、ラベル データに整数データ型を選択するとメモリ使用量をさらに削減できます。

データ型を調整するには、各予測ブロックのブロック ダイアログ ボックスを開きます。次に、ラベルのデータ型を uint8 に設定し、他のすべてのデータ型を single に設定します。Linear SVM、Logistic Regression、および Decision Tree の各ブロックで、出力 score を有効にし、score のデータ型を single に設定します。これにより、ブロック内のすべての演算で必ず単精度が使用されるようになります。

この例では、SIL プロファイリング用に構成された、単精度を使用する Simulink モデル slexVandVPredictSILProfilingSingleExample.slx が用意されています。Simulink モデルを開きます。

open_system("slexVandVPredictSILProfilingSingleExample.slx")

このモデルは、既に静的コード メトリクス レポートの生成用に構成されています。レポートを生成するには、Prediction サブシステムを右クリックし、[C/C++ コード][このサブシステムをビルド] を選択します。

ほとんどの予測ブロックで、スタック メモリの使用量が倍精度を使用した場合の半分になります。

モデルを閉じます。

close_system("slexVandVPredictSILProfilingSingleExample.slx")

Simulink Coverage を使用したコード カバレッジ解析の実行

Simulink® Coverage™ はモデルおよびコードのカバレッジ解析を実行し、モデルと生成されたコードのテストの完全性を測定します。Simulink Coverage を使用して、シミュレーション時にモデルのどの部分が実行されるかを詳しく理解して、モデルのバグやテストのギャップを見つけます。

カバレッジの有効化とメトリクスの選択

Simulink モデル slexVandVPredictExample.slx を開きます。

open_system("slexVandVPredictExample.slx")

モデルのカバレッジ結果を解析する前に、カバレッジを有効にして、確認するカバレッジ メトリクスを選択する必要があります。

  1. [アプリ] タブで [カバレッジ アナライザー] を選択します。

  2. [カバレッジ] タブで、[設定] をクリックして [コンフィギュレーション パラメーター] ウィンドウを開きます。

  3. 左側のペインで、[カバレッジ] をクリックします。[カバレッジ解析を有効にする] を選択します。

  4. 既定では、カバレッジ解析のスコープは [システム全体] に設定されています。スコープを [サブシステム] に変更します。次に、[サブシステムの選択] ボタンをクリックし、Prediction サブシステムを選択します。

  5. [カバレッジ メトリクス] セクションで、[構造カバレッジ レベル][ブロックの実行] に変更します。このオプションでは、各ブロックがシミュレーション時に実行されたかどうかをチェックします。

カバレッジの解析と結果の表示

次に、モデルをシミュレートしてカバレッジ結果を収集する必要があります。まず、[カバレッジ] タブで [カバレッジの解析] ボタンをクリックしてモデルをシミュレートします。シミュレーションが完了すると、カバレッジの完全性に基づいてモデル オブジェクトが強調表示されます。

緑色で強調表示されたブロックは、シミュレーション時に実行されています。ブロックがサブシステムまたはマスク サブシステムの場合、緑色の強調表示は、サブシステム内のすべてのブロックが実行されていることを意味します。この場合、7 つのブロックのうち 5 つがフル カバレッジとなっています。

赤色で強調表示されたマスク サブシステムは部分的に実行されています。つまり、マスク内の一部のブロックは実行されていません。この場合、Decision Tree ブロックが部分的に実行されています。

Subspace Discriminant MATLAB Function ブロックではカバレッジ情報を利用できません。

サブシステムが赤色で強調表示されている場合は、そのサブシステムに移動して、実行されていない特定のブロックを見つけることができます。予測アルゴリズムのどの部分が実行されていないかを調べるには、Decision Tree ブロックの左下にある矢印をクリックしてブロック マスクの内部ブロックを表示します。

この場合、findnode サブシステムに実行されていない条件があります。この条件は、Decision Tree ブロックが枝刈りされている場合に実行されますが、この決定木モデルには当てはまりません。したがって、予測アルゴリズムの残りの部分は実行されているため、赤色のフラグは無視できます。

Simulink Coverage は、コード カバレッジを測定し、設計のテストされていない要素を示すことができます。サポートされるモデル要素内の C/C++ コード、MATLAB Function ブロック、SIL モードまたはプロセッサインザループ (PIL) モードのモデルから生成されたコードのカバレッジを収集できます。詳細については、ソフトウェアインザループ (SIL) モードおよびプロセッサインザループ (PIL) モードのモデルのコード カバレッジ (Simulink Coverage)を参照してください。

モデルを閉じます。

close_system("slexVandVPredictExample.slx")

Simulink Test を使用した back-to-back テストの実行

Simulink® Test™ には、モデル、生成コード、およびシミュレートされたハードウェア、または物理的ハードウェアのシミュレーションベースのテストを体系的に作成、管理、および実行するためのツールが用意されています。Simulink Test には、SIL、PIL、およびリアルタイム ハードウェアインザループ (HIL) モードを使用して機能テスト、ユニット テスト、回帰テスト、back-to-back テストを実行できるシミュレーション、ベースライン、および等価性テスト テンプレートが含まれています。

モデルと生成コードの間で結果を比較するには、モデル シミュレーションと SIL、PIL、または HIL の実行などの異なる環境で等価性テストを実行します。等価性テストは back-to-back テストと呼ばれることもあります。

コンポーネントのテスト ウィザードを使用して、テスト ケースとテスト ハーネスを自動的に作成します。

  1. 現在の作業フォルダーを書き込み可能なフォルダーに設定します。

  2. slexVandVPredictSILProfilingExample.slx モデルを開きます。

  3. [コンフィギュレーション パラメーター] ダイアログ ボックスを開く。Simulink エディターの [モデル化] タブで、[モデル設定] をクリックします。

  4. [コード生成] ペインの [ビルド プロセス] で、[コード生成のみ] オプションを選択解除します。

  5. Prediction サブシステムに移動し、Neural Network サブシステムを選択します。

  6. [アプリ] タブの [モデルの検証とテスト] セクションで、[Simulink Test] をクリックします。

  7. [テスト] タブで、[Simulink テスト マネージャー] をクリックします。

  8. [新規][モデル コンポーネントのテスト] を選択します。[モデル コンポーネントのテストの作成] ウィザードが開きます。

  9. モデルで選択した Neural Network サブシステムを追加するには、[現在選択されているコンポーネントを使用] をクリックします。[選択したコンポーネント] ペインに、Prediction サブシステムと Neural Network サブシステムが表示されます。[選択したコンポーネント] のリストから Prediction サブシステムを削除します。

  10. [次へ] をクリックして、テスト ハーネスの入力の取得方法を指定します。[最上位モデルからのコンポーネント入力をテスト入力として使用] を選択します。このオプションでは、選択したモデル コンポーネントへの入力を使用してモデルを実行し、テスト ハーネスの入力を作成します。

  11. [次へ] をクリックしてテスト方法を選択します。[back-to-back テストを実行する] をクリックします。[シミュレーション 1] には、[Normal] を使用します。[シミュレーション 2] には、[Software-in-the-Loop (SIL)] を使用します。

  12. [次へ] をクリックして、テスト ハーネスの入力ソース、形式、テスト データと生成されたテストの保存場所を指定します。[ファイル形式を指定] で、[MAT] を選択します。[テスト データを保存する場所を指定][テスト ファイルの場所] には、既定の場所を使用します。

  13. [完了] をクリックします。テスト ハーネスとテスト ケースが作成され、ウィザードが閉じます。

  14. [実行] をクリックして back-to-back テストを実行します。

[結果とアーティファクト] パネルで [結果] 階層を展開します。[等価性基準の結果] の下にある [label:1] を選択します。上のプロットは出力信号が整列していることを示し、下のプロットは出力信号間に差がないことを示します。

業界標準への準拠に関する詳細

IEC Certification Kit にはツール検定アーティファクト、証明書、テスト スイートが用意されており、トレーサビリティ マトリクスが生成されます。このキットを使用すると、ISO® 26262、IEC 61508、EN 50128、ISO 25119、および関連機能安全規格 (IEC 62304 や EN 50657 など) について、MathWorks® のコード生成ツールと検証ツールを検定したり、組み込みシステムの認定を効率化したりできます。

IEC 62304 (医療機器ソフトウェア – ソフトウェア ライフ サイクル プロセス) は、医療機器ソフトウェアに必要なソフトウェア開発および保守プロセスを定めた国際規格です。たとえば、補聴器ソフトウェアの FDA 承認が必要な場合は、IEC Certification Kit を使用して設計の妥当性を確認できます。

FDA 承認を得るには、医療機器メーカーは医療機器の開発に使用するソフトウェア ツールの妥当性を確認する必要があり、そのためには、誤った出力があった場合でも危害を及ぼすリスクが許容範囲内であることを証明する必要があります。IEC Certification Kit を使用すると、関連する検証と妥当性確認のタスクを実行し、結果をドキュメント化できます。詳細については、FDA ソフトウェア妥当性確認を参照してください。

IEC Certification Kit の使用方法の詳細については、Get Started (IEC Certification Kit)を参照してください。

補助関数

HelperWaveletFeatureExtractor

function features = HelperWaveletFeatureVector(x,sf)
% Copyright 2019-2023 The MathWorks, Inc.
x = mean(x,2);
features = featureMatrix(sf,x,Transform="log");
features = mean(features,2);
end

HelperMdlMetrics

関数 HelperMdlMetrics は、学習済みモデル (Mdls) とテスト データ セット (X および Y) の cell 配列を受け取り、モデルの精度 (パーセント) とモデルのサイズ (KB) を含むモデル メトリクスの table を返します。この補助関数は、モデルのサイズの推定に関数 whos を使用します。ただし、関数 whos で返されるサイズは、生成コード内の展開に必要な実際のモデルのサイズよりも大きくなることがあります。たとえば、予測に必要がない情報は生成コードに含まれません。ロジスティック回帰学習器を使用する CompactClassificationECOC モデルについて考えてみます。MATLAB ワークスペース内の CompactClassificationECOC モデル オブジェクトのバイナリ学習器には ModelParameters プロパティがあります。ただし、このプロパティは生成コード内の展開用に準備されたモデルには含まれません。

function tbl = HelperMdlMetrics(Mdls,X,Y)
numMdl = length(Mdls);
metrics = NaN(numMdl,2);
for i = 1 : numMdl
    Mdl = Mdls{i};
    MdlInfo = whos("Mdl");
    metrics(i,:) = [(1-loss(Mdl,X,Y))*100 MdlInfo.bytes/1024];
end
tbl = array2table(metrics, ...
    VariableNames=["Accuracy","Model Size"]);
end

参考文献

[1] Seshia, Sanjit A., et al. "Toward Verified Artificial Intelligence." "Communications of the ACM", Vol. 65, No. 7, July 2022, pp. 46–55.

[2] A. Mesaros, T. Heittola, and T. Virtanen. "Acoustic Scene Classification: an Overview of DCASE 2017 Challenge Entries."In proc. International Workshop on Acoustic Signal Enhancement, 2018.

[3] Huszar, Ferenc. "Mixup: Data-Dependent Data Augmentation." InFERENCe. November 03, 2017. Accessed January 15, 2019. https://www.inference.vc/mixup-data-dependent-data-augmentation/.

[4] Han, Yoonchang, Jeongsoo Park, and Kyogu Lee. "Convolutional neural networks with binaural representations and background subtraction for acoustic scene classification." "The Detection and Classification of Acoustic Scenes and Events (DCASE)" (2017): pp. 1–5.

[5] Lostanlen, Vincent, and Joakim Anden. "Binaural scene classification with wavelet scattering." Technical Report, DCASE2016 Challenge, 2016.

[6] A. J. Eronen, V. T. Peltonen, J. T. Tuomi, A. P. Klapuri, S. Fagerlund, T. Sorsa, G. Lorho, and J. Huopaniemi, "Audio-based context recognition." "IEEE Trans. on Audio, Speech, and Language Processing", Vol 14, No. 1, Jan. 2006, pp. 321–329.

[7] TUT Acoustic scenes 2017, Development dataset

[8] TUT Acoustic scenes 2017, Evaluation dataset

関連するトピック