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

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

Этот пример основан на Генерации кода для Классификации Изображений, которая является альтернативным рабочим процессом к Классификации Цифр, использующей Функции ПОЖИРАТЕЛЯ РЕСУРСОВ (Computer Vision Toolbox).

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

Загрузите digitimages.

load digitimages.mat

images 28 28 3 000 массивов uint16 целые числа. Каждая страница является растровым изображением цифры. Каждым элементом является интенсивность пикселей. Соответствующие метки находятся в 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. Исследуйте все комбинации этих значений:

  • Для ECOC, кодирующего проект, используйте один по сравнению с одним и one-all.

  • Для ограничения поля SVM используйте три логарифмически расположенных с интервалами значения от 0,1 до 100 каждый. Для всех моделей сохраните 5-кратные перекрестные подтвержденные misclassification уровни.

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.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

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

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.0121
linIdx = find(cvLossRF == minCVLossRF,1);
[bestI,bestJ] = ind2sub(size(cvLossRF),linIdx);
bestMNS = maxNumSplits(bestI)
bestMNS = 729

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

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

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

Задайте две функции 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

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

Загрузите модель slexClassifyAndDisplayDigitImages.slx Simulink®.

SimMdlName = 'slexClassifyAndDisplayDigitImages';
open_system(SimMdlName);

Фигура отображает модель Simulink®. В начале моделирования блок From Multimedia File загружает видеофайл изображений набора тестов. Для каждого изображения в видео:

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

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

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

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

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

  • Блок To Video Display отображает аннотируемую систему координат.

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

sim(SimMdlName)

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

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

Смотрите также

| | |

Похожие темы