Main Content

カテゴリカル予測子用のダミー変数の作成と 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   

変数 Gendercategorical 変数に変換します。予測子データの列の順序が決まるので、categoricalGender 内のカテゴリの順序は重要です。dummyvar を使用して、カテゴリカル変数を 0 と 1 の行列に変換します。この行列の (i,j) 番目のエントリの値が 1 である場合、i 番目の患者は j 番目のカテゴリに属します。

categoricalGender = categorical(Gender);
orderGender = categories(categoricalGender)
orderGender = 2x1 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  

変数 SelfAssessedHealthStatuscategorical 変数に変換します。categoricalHealth 内のカテゴリの順序に注意してください。dummyvar を使用して、この変数を数値行列に変換します。

categoricalHealth = categorical(SelfAssessedHealthStatus);
orderHealth = categories(categoricalHealth)
orderHealth = 4x1 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

参考

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

関連するトピック