ドキュメンテーション

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

分類およびコード生成用の System object

この例では、学習済み分類モデルを使用して数字のイメージを分類する MATLAB® System object™ から C コードを生成する方法を示します。また、Simulink® での分類に System object を使用する方法も示します。MATLAB 関数ではなく System object を使用する利点は、System object の方が大量のストリーミング データの処理に適しているということです。詳細は、System object とは (MATLAB)を参照してください。

この例は、HOG 特徴を使用した数字の分類 (Computer Vision Toolbox)の代替ワークフローであるイメージ分類用のコードの生成をベースとしています。

データの読み込み

digitimages を読み込みます。

load digitimages.mat

imagesuint16 整数の 28 x 28 x 3000 の配列です。各ページは数字のラスター イメージです。各要素はピクセル強度です。対応するラベルは 3000 行 1 列の数値ベクトル Y に格納されています。詳細については、コマンド ラインで Description を入力してください。

観測値の数と予測子変数の数を格納します。データの 20% ホールドアウトを指定するデータ分割を作成します。学習セットとテスト セットのインデックスをデータ分割から抽出します。

rng(1); % For reproducibility
n = size(images,3);
p = numel(images(:,:,1));
cvp = cvpartition(n,'Holdout',0.20);
idxTrn = training(cvp);
idxTest = test(cvp);

データの再スケーリング

各イメージ内で範囲が区間 [0,1] になるようにピクセル強度を再スケーリングします。具体的には、 がイメージ 内のピクセル強度 であるとします。イメージ について、次の式を使用してすべてのピクセル強度を再スケーリングします。

X = double(images);

for i = 1:n
    minX = min(min(X(:,:,i)));
    maxX = max(max(X(:,:,i)));
    X(:,:,i) = (X(:,:,i) - minX)/(maxX - minX);
end

データの形状変更

コードを生成する場合、学習用の予測子データは数値変数のテーブルまたは数値行列に格納されていなければなりません。

データの形状を行列に変更して、予測子変数を列に、イメージを行に対応させます。reshape は列単位で要素を処理するので、結果を転置します。

X = reshape(X,[p,n])';

分類モデルの学習と最適化

学習観測値に基づいて、SVM バイナリ学習器による ECOC モデルとランダム フォレストを交差検証します。5 分割交差検証を使用します。

ECOC モデルについて、予測子の標準化を指定し、ECOC の符号化設計と SVM のボックス制約に対して分類誤差を最適化します。次の値の組み合わせをすべて探索します。

  • ECOC の符号化設計については、1 対 1 と 1 対他を使用します。

  • SVM のボックス制約については、0.1 から 100 の範囲にある対数間隔の 3 つの値を使用します。すべてのモデルについて、5 分割の交差検証済み誤分類率を格納します。

coding = {'onevsone' 'onevsall'};
boxconstraint = logspace(-1,2,3);
cvLossECOC = nan(numel(coding),numel(boxconstraint)); % For preallocation

for i = 1:numel(coding)
    for j = 1:numel(boxconstraint)
        t = templateSVM('BoxConstraint',boxconstraint(j),'Standardize',true);
        CVMdl = fitcecoc(X(idxTrn,:),Y(idxTrn),'Learners',t,'KFold',5,...
            'Coding',coding{i});
        cvLossECOC(i,j) = kfoldLoss(CVMdl);
        fprintf('cvLossECOC = %f for model using %s coding and box constraint=%f\n',...
            cvLossECOC(i,j),coding{i},boxconstraint(j))
    end
end
cvLossECOC = 0.058333 for model using onevsone coding and box constraint=0.100000
cvLossECOC = 0.057083 for model using onevsone coding and box constraint=3.162278
cvLossECOC = 0.050000 for model using onevsone coding and box constraint=100.000000
cvLossECOC = 0.120417 for model using onevsall coding and box constraint=0.100000
cvLossECOC = 0.121667 for model using onevsall coding and box constraint=3.162278
cvLossECOC = 0.127917 for model using onevsall coding and box constraint=100.000000

ランダム フォレストについて、 という数列を使用して最大分割数を変化させます。m は、n - 1 を超えない値です。

n = size(X,1);
m = floor(log(n - 1)/log(3));
maxNumSplits = 3.^(2:m);
cvLossRF = nan(numel(maxNumSplits));
for i = 1:numel(maxNumSplits)
    t = templateTree('MaxNumSplits',maxNumSplits(i));
    CVMdl = fitcensemble(X(idxTrn,:),Y(idxTrn),'Method','bag','Learners',t,...
        'KFold',5);
    cvLossRF(i) = kfoldLoss(CVMdl);
    fprintf('cvLossRF = %f for model using %d as the maximum number of splits\n',...
        cvLossRF(i),maxNumSplits(i))
end
cvLossRF = 0.323750 for model using 9 as the maximum number of splits
cvLossRF = 0.198333 for model using 27 as the maximum number of splits
cvLossRF = 0.075417 for model using 81 as the maximum number of splits
cvLossRF = 0.017083 for model using 243 as the maximum number of splits
cvLossRF = 0.012083 for model using 729 as the maximum number of splits
cvLossRF = 0.012083 for model using 2187 as the maximum number of splits

各アルゴリズムについて、誤分類率が最小になるハイパーパラメーターのインデックスを決定します。

minCVLossECOC = min(cvLossECOC(:))
linIdx = find(cvLossECOC == minCVLossECOC,1);
[bestI,bestJ] = ind2sub(size(cvLossECOC),linIdx);
bestCoding = coding{bestI}
bestBoxConstraint = boxconstraint(bestJ)

minCVLossRF = min(cvLossRF(:))
linIdx = find(cvLossRF == minCVLossRF,1);
[bestI,bestJ] = ind2sub(size(cvLossRF),linIdx);
bestMNS = maxNumSplits(bestI)
minCVLossECOC =

    0.0500


bestCoding =

    'onevsone'


bestBoxConstraint =

   100


minCVLossRF =

    0.0121


bestMNS =

   729

ランダム フォレストの方が、交差検証された誤分類率が小さくなります。

学習データを使用して ECOC モデルとランダム フォレストに学習をさせます。最適なハイパーパラメーターの組み合わせを与えます。

t = templateSVM('BoxConstraint',bestBoxConstraint,'Standardize',true);
MdlECOC = fitcecoc(X(idxTrn,:),Y(idxTrn),'Learners',t,'Coding',bestCoding);
t = templateTree('MaxNumSplits',bestMNS);
MdlRF = fitcensemble(X(idxTrn,:),Y(idxTrn),'Method','bag','Learners',t);

検定標本イメージ用の変数を作成し、学習済みモデルを使用して検定標本のラベルを予測します。

testImages = X(idxTest,:);
testLabelsECOC = predict(MdlECOC,testImages);
testLabelsRF = predict(MdlRF,testImages);

ディスクへの分類モデルの保存

MdlECOCMdlRF は予測分類モデルですが、これらをコード生成用に準備する必要があります。saveCompactModel を使用して MdlECOCMdlRF を現在の作業ディレクトリに保存します。

saveCompactModel(MdlECOC,'DigitImagesECOC');
saveCompactModel(MdlRF,'DigitImagesRF');

予測用 System object の作成

ECOC モデル用とランダム フォレスト用に 1 つずつ、以下を行う 2 つの System object を作成します。

  • loadCompactModel を使用した、以前に保存された学習済みモデルの読み込み

  • step メソッドによる逐次予測

  • 入力データのサイズ変更抑止

  • 倍精度のスカラー出力の強制

classdef ECOCClassifier < matlab.System
    % ECOCCLASSIFIER Predict image labels from trained ECOC model
    %
    % ECOCCLASSIFIER loads the trained ECOC model from
    % |'DigitImagesECOC.mat'|, and predicts labels for new observations
    % based on the trained model.  The ECOC model in
    % |'DigitImagesECOC.mat'| was cross-validated using the training data
    % in the sample data |digitimages.mat|.

    properties(Access = private)
        CompactMdl % The compacted, trained ECOC model
    end
        
    methods(Access = protected)
        
        function setupImpl(obj)
            % Load ECOC model from file
            obj.CompactMdl = loadCompactModel('DigitImagesECOC');
        end
        
        function y = stepImpl(obj,u)
            y = predict(obj.CompactMdl,u);
        end
        
        function flag = isInputSizeMutableImpl(obj,index)
            % Return false if input size is not allowed to change while
            % system is running
            flag = false;
        end
        
        function dataout = getOutputDataTypeImpl(~)
            dataout = 'double';
        end
        
        function sizeout = getOutputSizeImpl(~)
            sizeout = [1 1];
        end
    end
end

classdef RFClassifier < matlab.System
    % RFCLASSIFIER Predict image labels from trained random forest
    %
    % RFCLASSIFIER loads the trained random forest from
    % |'DigitImagesRF.mat'|, and predicts labels for new observations based
    % on the trained model.  The random forest in |'DigitImagesRF.mat'|
    % was cross-validated using the training data in the sample data
    % |digitimages.mat|.

    properties(Access = private)
        CompactMdl % The compacted, trained random forest
    end
        
    methods(Access = protected)
        
        function setupImpl(obj)
            % Load random forest from file
            obj.CompactMdl = loadCompactModel('DigitImagesRF');
        end
        
        function y = stepImpl(obj,u)
            y = predict(obj.CompactMdl,u);
        end
        
        function flag = isInputSizeMutableImpl(obj,index)
            % Return false if input size is not allowed to change while
            % system is running
            flag = false;
        end
        
        function dataout = getOutputDataTypeImpl(~)
            dataout = 'double';
        end
        
        function sizeout = getOutputSizeImpl(~)
            sizeout = [1 1];
        end
    end
end

System object の基本的な要件については、基本的な System object の定義 (MATLAB)を参照してください。

コード生成用の予測関数の定義

predictDigitECOCSO.m および predictDigitRFSO.m という名前の 2 つの MATLAB 関数を定義します。これらの関数は以下を行う必要があります。

  • コード生成命令 %#codegen を含める。

  • X に相応するイメージ データを受け入れる。

  • System object ECOCClassifier および RFClassifier をそれぞれ使用してラベルを予測する。

  • 予測したラベルを返す。

function label = predictDigitECOCSO(X) %#codegen
%PREDICTDIGITECOCSO Classify digit in image using ECOC Model System object
%   PREDICTDIGITECOCSO classifies the 28-by-28 images in the rows of X
%   using the compact ECOC model in the System object ECOCClassifier, and
%   then returns class labels in label.
classifier = ECOCClassifier;
label = step(classifier,X); 
end

function label = predictDigitRFSO(X) %#codegen
%PREDICTDIGITRFSO Classify digit in image using RF Model System object
%   PREDICTDIGITRFSO classifies the 28-by-28 images in the rows of X
%   using the compact random forest in the System object RFClassifier, and
%   then returns class labels in label.
classifier = RFClassifier;
label = step(classifier,X); 
end

MEX ファイルへの MATLAB 関数のコンパイル

codegen を使用して、検定標本精度が優れている予測関数をコンパイルして MEX ファイルにします。引数 -args を使用して検定セットのイメージを指定します。

if(minCVLossECOC <= minCVLossRF)
    codegen predictDigitECOCSO -args testImages
else
    codegen predictDigitRFSO -args testImages
end

生成された MEX ファイルが MATLAB 関数と同じ予測を行うことを確認します。

if(minCVLossECOC <= minCVLossRF)
    mexLabels = predictDigitECOCSO_mex(testImages);
    verifyMEX = sum(mexLabels == testLabelsECOC) == numel(testLabelsECOC)
else
    mexLabels = predictDigitRFSO_mex(testImages);
    verifyMEX = sum(mexLabels == testLabelsRF) == numel(testLabelsRF)
end
verifyMEX =

  logical

   1

verifyMEX1 です。これは、生成された MEX ファイルおよび対応する MATLAB 関数で予測が同じであることを示します。

Simulink で System object を使用したラベルの予測

検定セットのイメージをフレーム単位で表示するビデオ ファイルを作成します。

v = VideoWriter('testImages.avi','Uncompressed AVI');
v.FrameRate = 1;
open(v);
dim = sqrt(p)*[1 1];
for j = 1:size(testImages,1)
    writeVideo(v,reshape(testImages(j,:),dim));
end
close(v);

RGB イメージをグレースケールに変換してから、生成されたピクセル強度を値が区間 [0,1] に収まるようにスケーリングする、scalePixelIntensities.m という名前の関数を定義します。

function x = scalePixelIntensities(imdat)
%SCALEPIXELINTENSITIES Scales image pixel intensities
%   SCALEPIXELINTENSITIES scales the pixel intensities of the image such
%   that the result x is a row vector of values in the interval [0,1].

imdat = rgb2gray(imdat);

minimdat = min(min(imdat));
maximdat = max(max(imdat));
x = (imdat - minimdat)/(maximdat - minimdat);

end


Simulink® モデル slexClassifyAndDisplayDigitImages.slx を読み込みます。

SimMdlName = 'slexClassifyAndDisplayDigitImages';
open_system(SimMdlName);

Simulink® モデルが Figure に表示されます。シミュレーションの最初に、From Multimedia File ブロックで検定セットのイメージのビデオ ファイルが読み込まれます。ビデオの各イメージについて以下を行います。

  1. From Multimedia File ブロックで、イメージを変換して 28 行 28 列のピクセル強度の行列を出力します。

  2. Process Data ブロックで、scalePixelIntensities.m を使用してピクセル強度をスケーリングし、1 行 784 列のスケーリングされた強度のベクトルを出力します。

  3. Classification Subsystem ブロックで、与えられた処理済みイメージ データからラベルを予測します。このブロックでは、分類誤差が最小になる System object を選択します。この場合、ランダム フォレストが選択されます。このブロックでは、倍精度スカラーのラベルを出力します。

  4. Data Type Conversion ブロックで、ラベルを int32 スカラーに変換します。

  5. Insert Text ブロックで、予測されたラベルを現在のフレームに埋め込みます。

  6. To Video Display ブロックで、注釈付きのフレームを表示します。

モデルをシミュレートします。

sim(SimMdlName)

600 個の検定セットのイメージおよびその予測が素早く表示されます。最後のイメージがビデオ表示に残ります。代わりに [1 ステップ進む] ボタンを押すと、1 つずつ予測を生成して対応するイメージと共に表示できます。

Simulink® Coder™ のライセンスもある場合、Simulink® の slexClassifyAndDisplayDigitImages.slx またはコマンド ラインから rtwbuild を使用して C コードを生成できます。詳細は、モデル用 C コードの生成 (Simulink Coder)を参照してください。

参考

| | |

関連するトピック