最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

カテゴリカル予測子による SVM 分類器の学習と C/C++ コードの生成

この例では、サポート ベクター マシン (SVM) モデルを使用してデータを分類するためのコードを生成する方法を示します。数値予測子とカテゴリカル予測子を使用してモデルに学習をさせます。

コード生成ではカテゴリカル予測子がサポートされないので、SVM 分類器をあてはめる前に、dummyvar を使用してカテゴリカル予測子を数値ダミー変数に変換します。新しいデータを学習済みモデルに渡す場合、同様の方法でデータを前処理しなければなりません。

データの前処理と SVM 分類器の学習

patients データセットを読み込みます。数値変数 Diastolic および Systolic を使用して table を作成します。table の各行は、異なる患者に対応しています。

load patients
tbl = table(Diastolic,Systolic);
head(tbl)
ans=8×2 table
    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 array
    {'Female'}
    {'Male'  }

dummyGender = dummyvar(categoricalGender);

メモ: 生成される行列 dummyGender はランク落ちになります。学習を行うモデルのタイプによっては、このランク落ちが問題になる可能性があります。たとえば、線形モデルに学習をさせる場合、ダミー変数の 1 列目を削除します。

対応する変数見出しの付いたダミー変数 dummyGender が含まれている table を作成します。この新しい table を tbl と結合します。

tblGender = array2table(dummyGender,'VariableNames',orderGender);
tbl = [tbl tblGender];
head(tbl)
ans=8×4 table
    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 array
    {'Excellent'}
    {'Fair'     }
    {'Good'     }
    {'Poor'     }

dummyHealth = dummyvar(categoricalHealth);

対応する変数見出しで dummyHealth が含まれている table を作成します。この新しい table を tbl と結合します。

tblHealth = array2table(dummyHealth,'VariableNames',orderHealth);
tbl = [tbl tblHealth];
head(tbl)
ans=8×8 table
    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);

C/C++ コードの生成

SVM 分類器を読み込んで、新しい予測子データを入力引数として受け入れてから、新しいデータを分類するコードを生成します。

saveCompactModel を使用して、SVM 分類器をファイルに保存します。

saveCompactModel(Mdl,'SVMClassifier')

saveCompactModel は、現在のフォルダーの SVMClassifier.mat という MATLAB® バイナリ ファイルに構造体配列として分類器を保存します。

新しい予測子データを入力引数として受け入れるエントリポイント関数 mySVMPredict を定義します。この関数では、loadCompactModel を使用して SVM 分類器を読み込んで predict に渡します。

type mySVMPredict.m % Display contents of mySVMPredict.m file
function label = mySVMPredict(X) %#codegen
Mdl = loadCompactModel('SVMClassifier');
label = predict(Mdl,X);
end

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

codegen を使用して mySVMPredict のコードを生成します。生成されるコードが可変サイズの配列を受け入れるようにするため、coder.typeof を使用して新しい予測子データのデータ型と次元を指定します。

codegen mySVMPredict -args {coder.typeof(X,[Inf 8],[1 0])}

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

参考

| | | | | | |

関連するトピック