カテゴリカル予測子用のダミー変数の作成と C/C++ コードの生成
この例では、サポート ベクター マシン (SVM) モデルを使用してデータを分類するためのコードを生成する方法を示します。数値予測子と、符号化されたカテゴリカル予測子を使用してモデルに学習をさせます。SVM 分類器を当てはめる前に、dummyvar を使用してカテゴリカル予測子を数値ダミー変数に変換します。新しいデータを学習済みモデルに渡す場合、同様の方法でデータを前処理しなければなりません。
あるいは、CategoricalPredictors プロパティでカテゴリカル予測子が特定されている場合は、コードを生成するためにダミー変数を手動で作成する必要はありません。カテゴリカル予測子は自動的に処理されます。たとえば、table のデータを分類するためのコードの生成を参照してください。
データの前処理と SVM 分類器の学習
patients データ セットを読み込みます。数値変数 Diastolic および Systolic を使用して table を作成します。table の各行は、異なる患者に対応しています。
load patients
tbl = table(Diastolic,Systolic);
head(tbl) Diastolic Systolic
_________ ________
93 124
77 109
83 125
75 117
80 122
70 121
88 130
82 115
変数 Gender を categorical 変数に変換します。予測子データの列の順序が決まるので、categoricalGender 内のカテゴリの順序は重要です。dummyvar を使用して、カテゴリカル変数を 0 と 1 の行列に変換します。この行列の (i,j) 番目のエントリの値が 1 である場合、i 番目の患者は j 番目のカテゴリに属します。
categoricalGender = categorical(Gender); orderGender = categories(categoricalGender)
orderGender = 2×1 cell
{'Female'}
{'Male' }
dummyGender = dummyvar(categoricalGender);
メモ: 生成される行列 dummyGender はランク落ちになります。学習を行うモデルのタイプによっては、このランク落ちが問題になる可能性があります。たとえば、線形モデルに学習をさせる場合、ダミー変数の 1 列目を削除します。
対応する変数見出しの付いたダミー変数 dummyGender が含まれている table を作成します。この新しい table を tbl と結合します。
tblGender = array2table(dummyGender,'VariableNames',orderGender);
tbl = [tbl tblGender];
head(tbl) Diastolic Systolic Female Male
_________ ________ ______ ____
93 124 0 1
77 109 0 1
83 125 1 0
75 117 1 0
80 122 1 0
70 121 1 0
88 130 1 0
82 115 0 1
変数 SelfAssessedHealthStatus を categorical 変数に変換します。categoricalHealth 内のカテゴリの順序に注意してください。dummyvar を使用して、この変数を数値行列に変換します。
categoricalHealth = categorical(SelfAssessedHealthStatus); orderHealth = categories(categoricalHealth)
orderHealth = 4×1 cell
{'Excellent'}
{'Fair' }
{'Good' }
{'Poor' }
dummyHealth = dummyvar(categoricalHealth);
対応する変数見出しで dummyHealth が含まれている table を作成します。この新しい table を tbl と結合します。
tblHealth = array2table(dummyHealth,'VariableNames',orderHealth);
tbl = [tbl tblHealth];
head(tbl) Diastolic Systolic Female Male Excellent Fair Good Poor
_________ ________ ______ ____ _________ ____ ____ ____
93 124 0 1 1 0 0 0
77 109 0 1 0 1 0 0
83 125 1 0 0 0 1 0
75 117 1 0 0 1 0 0
80 122 1 0 0 0 1 0
70 121 1 0 0 0 1 0
88 130 1 0 0 0 1 0
82 115 0 1 0 0 1 0
たとえば、tbl の 3 行目は、拡張期血圧が 83、収縮期血圧が 125、女性、健康状態の自己評価が良好である患者に対応します。
tbl の値はすべて数値なので、table を行列 X に変換できます。
X = table2array(tbl);
X と自動カーネル スケールのガウス カーネル関数を使用して SVM 分類器に学習させます。応答として変数 Smoker を指定します。
Y = Smoker; Mdl = fitcsvm(X,Y, ... 'KernelFunction','gaussian','KernelScale','auto');
C/C++ コードの生成
SVM 分類器を読み込んで、新しい予測子データを入力引数として受け入れてから、新しいデータを分類するコードを生成します。
saveLearnerForCoder を使用して、SVM 分類器をファイルに保存します。
saveLearnerForCoder(Mdl,'SVMClassifier')saveLearnerForCoder は、現在のフォルダーの SVMClassifier.mat という MATLAB® バイナリ ファイルに構造体配列として分類器を保存します。
新しい予測子データを入力引数として受け入れるエントリポイント関数 mySVMPredict を定義します。この関数では、loadLearnerForCoder を使用して SVM 分類器を読み込んで predict に渡します。
function label = mySVMPredict(X) %#codegen Mdl = loadLearnerForCoder('SVMClassifier'); label = predict(Mdl,X); end
codegen を使用して mySVMPredict のコードを生成します。生成されるコードが可変サイズの配列を受け入れるようにするため、coder.typeof を使用して新しい予測子データのデータ型と次元を指定します。
codegen mySVMPredict -args {coder.typeof(X,[Inf 8],[1 0])}
Code generation successful.
mySVMPredict と MEX ファイルが学習データに対して同じ結果を返すことを確認します。
label = predict(Mdl,X); mylabel = mySVMPredict(X); mylabel_mex = mySVMPredict_mex(X); verifyMEX = isequal(label,mylabel,mylabel_mex)
verifyMEX = logical
1
新しいデータに対するラベルの予測
新しいデータに対してラベルを予測するには、はじめに新しいデータを前処理しなければなりません。生成されたコードを MATLAB 環境で実行する場合、この節で説明されている前処理手順に従うことができます。生成されたコードを MATLAB 環境の外部に展開する場合、前処理手順が異なることがあります。どちらの場合も、新しいデータと学習データ X の列数が同じでなければなりません。
この例では、patients データ セットの 3 番目、4 番目および 5 番目の患者を使用します。これらの患者のデータを前処理して、生成される数値行列を学習データの形式と一致させます。
カテゴリカル変数をダミー変数に変換します。新しい観測値にすべてのカテゴリの値が含まれているとは限らないので、学習時に使用したものと同じカテゴリを同じ順序で指定する必要があります。MATLAB で、対応する学習データの変数 (この例では、性別の値に対する orderGender と、健康状態の自己評価の値に対する orderHealth) に関連付けられているカテゴリ名が順序付けられて格納されている cell 配列を渡します。
newcategoricalGender = categorical(Gender(3:5),orderGender); newdummyGender = dummyvar(newcategoricalGender); newcategoricalHealth = categorical(SelfAssessedHealthStatus(3:5),orderHealth); newdummyHealth = dummyvar(newcategoricalHealth);
すべての新しいデータを結合して数値行列にします。
newX = [Diastolic(3:5) Systolic(3:5) newdummyGender newdummyHealth]
newX = 3×8
83 125 1 0 0 0 1 0
75 117 1 0 0 1 0 0
80 122 1 0 0 0 1 0
newX は行列 X の 3 行目、4 行目 および 5 行目に厳密に対応することに注意してください。
mySVMPredict と MEX ファイルが新しいデータに対して同じ結果を返すことを確認します。
newlabel = predict(Mdl,newX); newmylabel = mySVMPredict(newX); newmylabel_mex = mySVMPredict_mex(newX); newverifyMEX = isequal(newlabel,newmylabel,newmylabel_mex)
newverifyMEX = logical
1
参考
dummyvar | categorical | ClassificationSVM | codegen (MATLAB Coder) | coder.typeof (MATLAB Coder) | loadLearnerForCoder | coder.Constant (MATLAB Coder) | saveLearnerForCoder