Main Content

コード生成用の可変サイズ引数の指定

この例では、分類または回帰モデル オブジェクトのオブジェクト関数に対してコードを生成するときに可変サイズの入力引数を指定する方法を示します。可変サイズのデータは、実行時にサイズが変化する可能性があるデータです。可変サイズの入力引数の指定は、コンパイル時にサイズが不明であるデータの場合に便利です。この例では、名前と値のペアの引数をエントリポイント関数に含める方法と、コードを生成するときにこれらを指定する方法についても説明します。

コード生成ワークフローの詳細な例については、機械学習モデルの予測をコマンド ラインで行うコードの生成機械学習モデルの予測を MATLAB Coder アプリを使用して行うコードの生成を参照してください。

分類モデルの学習

フィッシャーのアヤメのデータ セットを読み込みます。ラベルを文字行列に変換します。

load fisheriris
species = char(species);

データ セット全体を使用して分類木に学習をさせます。

Mdl = fitctree(meas,species);

MdlClassificationTree モデルです。

saveLearnerForCoder の使用によるモデルの保存

saveLearnerForCoder を使用して、学習済みの分類木を現在のフォルダーの ClassTreeIris.mat という名前のファイルに保存します。

MdlName = 'ClassTreeIris';
saveLearnerForCoder(Mdl,MdlName);

エントリポイント関数の定義

現在のフォルダーで、以下を行う mypredictTree.m という名前のエントリポイント関数を定義します。

  • meas に対応する列をもつ測定値を受け入れ、有効な名前と値のペアの引数を受け入れる。

  • loadLearnerForCoder を使用して、学習済み分類木を読み込む。

  • 読み込んだ分類木から、ラベルおよび対応するスコア、ノード番号、クラス番号を予測する。

入力引数として varargin を指定することにより、オプションの名前と値のペアの引数に対応できます。詳細については、可変長引数リストのコード生成 (MATLAB Coder)を参照してください。

type mypredictTree.m  % Display contents of mypredictTree.m file
function [label,score,node,cnum] = mypredictTree(x,savedmdl,varargin) %#codegen
%MYPREDICTTREE Predict iris species using classification tree
%   MYPREDICTTREE predicts iris species for the n observations in the
%   n-by-4 matrix x using the classification tree stored in the MAT-file
%   whose name is in savedmdl, and then returns the predictions in the
%   array label. Each row of x contains the lengths and widths of the petal
%   and sepal of an iris (see the fisheriris data set). For other output
%   argument descriptions, see the predict reference page.
CompactMdl = loadLearnerForCoder(savedmdl);
[label,score,node,cnum] = predict(CompactMdl,x,varargin{:});
end

メモ: このページの右上にあるボタンをクリックしてこの例を MATLAB® で開くと、MATLAB® で例のフォルダーが開きます。このフォルダーには、エントリポイント関数のファイルが含まれています。

コードの生成

可変サイズ引数の指定

C および C++ は静的な型の言語なので、codegen-args オプションを使用して、エントリポイント関数内のすべての変数のプロパティをコンパイル時に決定しなければなりません。

coder.Constant (MATLAB Coder) を使用して、コンパイル時の定数である入力を指定します。

coder.Constant(v)

coder.Constant(v) は、v と同じ値の定数値をもつ coder.Constant 型の変数をコード生成時に作成します。

coder.typeof (MATLAB Coder) を使用して、可変サイズの入力を指定します。

coder.typeof(example_value, size_vector, variable_dims)

example_valuesize_vectorvariable_dims の値は、生成されるコードが受け入れることができる入力配列のプロパティを指定します。

  • 入力配列は、example_value の例の値と同じデータ型です。

  • 対応する variable_dims の値が false である場合、size_vector は入力配列の配列サイズです。

  • 対応する variable_dims の値が true である場合、size_vector は配列サイズの上限です。

  • variable_dims は、配列の各次元が可変サイズと固定サイズのどちらであるかを指定します。値 true (logical 1) は対応する次元が可変サイズであることを意味します。値 false (logical 0) は対応する次元が固定サイズであることを意味します。

エントリポイント関数 mypredictTree は、予測子データ、学習済みモデル オブジェクトが含まれている MAT ファイルの名前、およびオプションの名前と値のペアの引数を受け入れます。生成するコードでは、予測子データについての可変サイズの配列と、値が可変サイズのベクトルである名前と値のペアの引数 'Subtrees' を受け入れるとします。すると、入力引数は、予測子データ、MAT ファイル名、および名前と値のペアの引数 'Subtrees' の名前と値の 4 つになります。

4 行 1 列の cell 配列を定義し、エントリポイント関数の各入力引数の型を各 cell に割り当てます。

ARGS = cell(4,1);

1 番目の入力について coder.typeof を使用して、予測子データ変数が倍精度であり、モデルの学習に使用した予測子データと同じ列数であることと、観測値の個数 (行数) が任意であることを指定します。

p = numel(Mdl.PredictorNames);
ARGS{1} = coder.typeof(0,[Inf,p],[1,0]);

MATLAB の既定の数値データ型は double なので、example_value0 という値はデータ型が double であることを意味します。size_vector[Inf,p] という値と variable_dims[1,0] という値は、1 番目の次元のサイズが可変で制限がなく、2 番目の次元のサイズが p に固定されることを意味します。

2 番目の入力は MAT ファイル名であり、コンパイル時の定数でなければなりません。coder.Constant を使用して、2 番目の入力の型を指定します。

ARGS{2} = coder.Constant(MdlName);

最後の 2 つの入力は、名前と値のペアの引数 'Subtrees' の名前および値です。名前と値のペアの引数の名前は、コンパイル時の定数でなければなりません。

ARGS{3} = coder.Constant('Subtrees');

coder.typeof を使用して、'Subtrees' の値が倍精度行ベクトルであり、行ベクトルのサイズの上限が max(Mdl.PrunedList) であることを指定します。

m = max(Mdl.PruneList);
ARGS{4} = coder.typeof(0,[1,m],[0,1]);

ここでも、MATLAB の既定の数値データ型は double なので、example_value0 という値はデータ型が double であることを意味します。size_vector[1,m] という値と variable_dims[0,1] という値は、1 番目の次元のサイズが 1 に固定され、2 番目の次元のサイズが可変で上限が m であることを意味します。

codegen の使用によるコードの生成

mypredictTree の入力引数の型が含まれている cell 配列 ARGS を使用して、エントリポイント関数 mypredictTree から MEX 関数を生成します。-args オプションを使用して、入力引数の型を指定します。-nargout オプションを使用して、生成されるエントリポイント関数の出力引数の個数を指定します。生成されるコードには、エントリポイント関数の定義に現れる順序で、指定した個数の出力引数が含まれます。

codegen mypredictTree -args ARGS -nargout 2
Code generation successful.

codegen は、プラットフォームに依存する拡張子の MEX 関数 mypredictTree_mex を現在のフォルダーに生成します。

関数 predict は、名前と値のペアの引数 'SubTrees' について単精度値、倍精度値、および 'all' を受け入れます。しかし、ARGS{4} で指定したデータ型が double なので、MEX 関数を予測に使用するときは倍精度値のみを指定できます。

生成されたコードの確認

生成された MEX 関数と枝刈りレベルが 1 の部分木を使用して、学習データから無作為に選択した 15 個の値についてラベルを予測します。MEX 関数によるラベルを predict が予測したラベルと比較します。

rng('default'); % For reproducibility
Xnew = datasample(meas,15);
[labelMEX,scoreMEX] = mypredictTree_mex(Xnew,MdlName,'Subtrees',1);
[labelPREDICT,scorePREDICT] = predict(Mdl,Xnew,'Subtrees',1);
labelPREDICT
labelPREDICT = 15x10 char array
    'virginica '
    'virginica '
    'setosa    '
    'virginica '
    'versicolor'
    'setosa    '
    'setosa    '
    'versicolor'
    'virginica '
    'virginica '
    'setosa    '
    'virginica '
    'virginica '
    'versicolor'
    'virginica '

labelMEX
labelMEX = 15x1 cell
    {'virginica' }
    {'virginica' }
    {'setosa'    }
    {'virginica' }
    {'versicolor'}
    {'setosa'    }
    {'setosa'    }
    {'versicolor'}
    {'virginica' }
    {'virginica' }
    {'setosa'    }
    {'virginica' }
    {'virginica' }
    {'versicolor'}
    {'virginica' }

予測されたラベルは、データ型以外は MEX 関数のラベルと同じです。応答のデータ型が char であり、Subtrees の値がスカラーであることを codegen が確定できない場合、生成されたコードからの出力は文字ベクトルの cell 配列になります。

比較のため、labelsPREDICT を cell 配列に変換して isequal を使用できます。

cell_labelPREDICT = cellstr(labelPREDICT);
verifyLabel = isequal(labelMEX,cell_labelPREDICT)
verifyLabel = logical
   1

isequalは、すべての入力が等しいことを意味する logical 1 (true) を返します。

同じように、2 番目の出力を比較します。scorePREDICT と比較すると、scoreMex には丸めによる差が含まれている場合があります。このような場合は、小さい誤差を許容して scoreMEXscorePREDICT を比較します。

find(abs(scorePREDICT-scoreMEX) > 1e-8)
ans =

  0x1 empty double column vector

scorePREDICTscoreMEX の要素ごとの差の絶対値が指定された許容誤差 1e-8 を超えない場合、find は空のベクトルを返します。この比較により、許容誤差 1e–8 内で scorePREDICTscoreMEX が等しいことを確認します。

参考

(MATLAB Coder) | (MATLAB Coder) | | (MATLAB Coder) | |

関連するトピック