Системные объекты для классификации и генерации кода

В этом примере показано, как сгенерировать код С из системного object™ MATLAB ®, который классифицирует изображения цифр с помощью обученной модели классификации. В этом примере также показано, как использовать системный объект для классификации в Simulink ®. Преимущество использования системных объектов над функцией MATLAB в том, что системные объекты более подходят для обработки больших объемов потоковых данных. Для получения дополнительной информации см. раздел «Что такое системные объекты?».

Этот пример основан на генерации кода для классификации изображений, которая является альтернативным рабочим процессом для классификации цифр с использованием функций HOG (Computer Vision Toolbox).

Загрузка данных

Загрузите digitimages.

load digitimages.mat

images массив uint16 28 на 28 на 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] внутри каждого изображения. В частности, предположим pij - интенсивность пикселей j внутри изображения i. Для изображения i, перерассчитать всю интенсивность его пикселей с помощью этой формулы:

pˆij=pij-minj(pij)maxj(pij)-minj(pij).

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])';

Обучите и оптимизируйте классификационные модели

Перекрестная проверка модели ECOC для двоичных учащихся SVM и случайного леса на основе обучающих наблюдений. Используйте 5-кратную перекрестную валидацию.

Для модели ECOC задайте стандартизацию предиктора и оптимизируйте ошибку классификации по сравнению с проектом кодирования ECOC и ограничением SVM box. Исследуйте все комбинации этих значений:

  • Для проекта кодирования ECOC используйте один от одного и один от всех.

  • Для ограничения блока SVM используйте три логарифмически разнесенных значения от 0,1 до 100 каждый. Для всех моделей сохраните 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

Для случайного леса варьируйте максимальное количество разделений при помощи значений в последовательности {32,33,...,3m}. m таково, что 3m не больше n-1. Чтобы воспроизвести случайные выборки предиктора, задайте 'Reproducible',true.

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),'Reproducible',true);
    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.319167 for model using 9 as the maximum number of splits
cvLossRF = 0.192917 for model using 27 as the maximum number of splits
cvLossRF = 0.066250 for model using 81 as the maximum number of splits
cvLossRF = 0.015000 for model using 243 as the maximum number of splits
cvLossRF = 0.013333 for model using 729 as the maximum number of splits
cvLossRF = 0.009583 for model using 2187 as the maximum number of splits

Для каждого алгоритма определите индексы гиперпараметра, которые дают минимальные скорости неправильной классификации.

minCVLossECOC = min(cvLossECOC(:))
minCVLossECOC = 0.0500
linIdx = find(cvLossECOC == minCVLossECOC,1);
[bestI,bestJ] = ind2sub(size(cvLossECOC),linIdx);
bestCoding = coding{bestI}
bestCoding = 
'onevsone'
bestBoxConstraint = boxconstraint(bestJ)
bestBoxConstraint = 100
minCVLossRF = min(cvLossRF(:))
minCVLossRF = 0.0096
linIdx = find(cvLossRF == minCVLossRF,1);
[bestI,bestJ] = ind2sub(size(cvLossRF),linIdx);
bestMNS = maxNumSplits(bestI)
bestMNS = 2187

Случайный лес достигает меньшей перекрестной проверенной скорости неправильной классификации.

Обучите модель 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);

Сохраните классификационную модель на диск

MdlECOC и MdlRF являются прогнозирующими моделями классификации, но вы должны подготовить их к генерации кода. Сохраните MdlECOC и MdlRF в текущую рабочую папку с помощью saveLearnerForCoder.

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

Создайте системный объект для предсказания

Создайте два системных объектов, один для модели ECOC, а другой для случайного леса, который:

  • Загрузите ранее сохраненную обученную модель при помощи loadLearnerForCoder.

  • Делайте последовательные предсказания step способ.

  • Не вносите никаких изменений в размер входных данных.

  • Обеспечьте двойную точность, скалярный выход.

type ECOCClassifier.m % Display contents of ECOCClassifier.m file
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 = loadLearnerForCoder('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
type RFClassifier.m % Display contents of RFClassifier.m file
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 = loadLearnerForCoder('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

Примечание.Если нажать кнопку, расположенную в правом верхнем разделе этой страницы и открыть этот пример в MATLAB ®, MATLAB ® открывает папку примера. Эта папка включает файлы, используемые в этом примере.

Основные требования к системным объектам см. в разделе Определение основных системных объектов.

Задайте функции предсказания для генерации кода

Задайте две функции MATLAB, называемые predictDigitECOCSO.m и predictDigitRFSO.m. Функции:

  • Включите директиву генерации кода %#codegen.

  • Примите данные изображения, соизмеримые с X.

  • Спрогнозируйте метки с помощью ECOCClassifier и RFClassifier Системные объекты, соответственно.

  • Возврат предсказанных меток.

type predictDigitECOCSO.m % Display contents of predictDigitECOCSO.m file
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
type predictDigitRFSO.m % Display contents of predictDigitRFSO.m file
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

Скомпилируйте функцию MATLAB в файл MEX

Скомпилируйте функцию предсказания, которая достигает лучшей точности тестовой выборки в файл MEX при помощи codegen. Задайте изображения тестового набора при помощи -args аргумент.

if(minCVLossECOC <= minCVLossRF)
    codegen predictDigitECOCSO -args testImages    
else   
    codegen predictDigitRFSO -args testImages
end
Code generation successful.

Проверьте, что сгенерированный файл 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

verifyMEX является 1, что указывает, что предсказания, сделанные сгенерированным файлом MEX и соответствующей функцией MATLAB, совпадают.

Предсказание меток при помощи системных объектов в Simulink

Создайте видео файла, которое отобразит кадр за кадром тестовых изображений.

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);

Задайте функцию, называемую scalePixelIntensities.m который преобразует изображения RGB в полутоновые, а затем масштабирует полученную интенсивность пикселей так, чтобы их значения находились в интервале [0,1].

type scalePixelIntensities.m % Display contents of scalePixelIntensities.m file
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 ®. В начале симуляции блок From Multimedia Файла загружает файл видео тестовых изображений. Для каждого изображения в видео:

  • Блок From Multimedia File преобразует и выводит изображение в матрицу интенсивности пикселей 28 на 28.

  • Блок Process Data масштабирует интенсивность пикселей при помощи scalePixelIntensities.m, и выводит вектор масштабированной интенсивности 1 на 784.

  • Блок Подсистемы Классификации предсказывает метки, учитывая обработанные данные изображения. Блок выбирает Системный объект, который минимизирует ошибку классификации. В этом случае блок выбирает случайный лес. Блок выводит скалярную метку двойной точности.

  • Блок Data Type Conversion преобразует метку в int32 скаляр.

  • Блок Insert Text встраивает предсказанную метку в текущую систему координат.

  • Блок «До отображения видео» отображает аннотированную систему координат.

Симулируйте модель.

sim(SimMdlName)

Модель быстро отображает все 600 тестовых изображений и их предсказание. Последнее изображение остается в отображение видео. Можно сгенерировать предсказания и отобразить их соответствующими изображениями один за другим, нажав кнопку «Шаг вперед».

Если у вас также есть лицензия Coder™ Simulink ®, то можно сгенерировать код С от slexClassifyAndDisplayDigitImages.slx в Simulink ® или из командной строки с помощью slbuild (Simulink). Для получения дополнительной информации см. «Генерация кода С для модели» (Simulink Coder).

См. также

| | |

Похожие темы