Генерация кода для классификации изображений

В этом примере показано, как сгенерировать код С из функции MATLAB ®, которая классифицирует изображения цифр с помощью обученной модели классификации. Этот пример демонстрирует альтернативный рабочий процесс классификации цифр с использованием функций HOG (Computer Vision Toolbox). Однако для поддержки генерации кода в этом примере можно следовать шагам генерации кода в этом примере.

Автоматическая классификация изображений является повсеместным инструментом. Для примера обученный классификатор может быть развернут на дроне, чтобы автоматически идентифицировать аномалии на суше в захваченных кадрах, или на машине, которая сканирует рукописные zip- кодов на буквах. В последнем примере, после того как машина найдет почтовый индекс и хранит отдельные изображения цифр, развернутый классификатор должен угадать, какие цифры находятся в изображениях, чтобы восстановить почтовый код.

В этом примере показано, как обучить и оптимизировать многоклассовую модель классификации выходных кодов с исправлением ошибок (ECOC) для классификации цифр на основе интенсивности пикселей в растровых изображениях. Модель ECOC содержит двоичных машин опорных векторов (SVM) учащихся. Затем в этом примере показано, как сгенерировать код С, который использует обученную модель для классификации новых изображений. Данные являются синтетическими изображениями деформированных цифр различных шрифтов, который имитирует рукописные цифры.

Настройте компилятор C

Чтобы сгенерировать код C/C + +, вы должны иметь доступ к компилятору C/C + +, который настроен правильно. MATLAB Coder™ находит и использует поддерживаемый, установленный компилятор. Можно использовать mex -setup чтобы просмотреть и изменить компилятор по умолчанию. Для получения дополнительной информации см. раздел «Изменение компилятора по умолчанию».

Допущения и ограничения

Чтобы сгенерировать код С, MATLAB Coder:

  • Требуется правильно настроенный компилятор.

  • Требует, чтобы поддерживаемые функции были в заданной вами функции MATLAB. Для получения информации об основном рабочем процессе см. Введение в генерацию кода.

  • Запрещает объекты как входные параметры заданной функции.

Что касается последнего ограничения, то считайте, что:

  • Обученные классификационные модели являются объектами

  • MATLAB Coder поддерживает predict классифицировать наблюдения с помощью обученных моделей, но не поддерживает подбор кривой модели

Чтобы обойти ограничения генерации кода для классификации, обучите классификационную модель с помощью MATLAB, затем передайте полученный объект модели saveLearnerForCoder. The saveLearnerForCoder функция удаляет некоторые свойства, которые не требуются для предсказания, а затем сохраняет обученную модель на диск как массив структур. Как и модель, массив структур содержит информацию, используемую для классификации новых наблюдений.

После сохранения модели на диск загрузите модель в функцию MATLAB при помощи loadLearnerForCoder. The loadLearnerForCoder функция загружает сохраненный массив структур, а затем восстанавливает объект модели. В функции MATLAB, чтобы классифицировать наблюдения, можно передать модель и набор данных предиктора, который может быть входным параметром функции, чтобы predict.

Рабочий процесс генерации кода для классификации

Перед развертыванием классификатора изображений на устройстве:

  1. Получите достаточное количество маркированных изображений.

  2. Решите, какие функции извлекать из изображений.

  3. Обучите и оптимизируйте классификационную модель. Этот шаг включает выбор подходящего алгоритма и настройку гиперпараметров, то есть параметров модели, не подходящих во время обучения.

  4. Сохраните модель на диск при помощи saveLearnerForCoder.

  5. Задайте функцию для классификации новых изображений. Функция должна загрузить модель при помощи loadLearnerForCoder, и может возвращать метки, такие как классификационные оценки.

  6. Настройте компилятор C.

  7. Определите окружение, в которой можно выполнить сгенерированный код.

  8. Сгенерируйте код С для функции.

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

Загрузите digitimages набор данных.

load digitimages

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

Отобразите девять случайных изображений из данных.

figure
for j = 1:9
    subplot(3,3,j)
    selectImage = datasample(images,1,3);
    imshow(selectImage,[])
end

Перешкала данных

Поскольку интенсивность необработанных пикселей сильно изменяется, необходимо нормализовать их значения перед обучением классификационной модели. Измените интенсивность пикселей так, чтобы они варьировались в интервале [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

Кроме того, если у вас есть лицензия Image Processing Toolbox™, то можно эффективно изменить интенсивность изображений в пикселях на [0,1] при помощи mat2gray. Для получения дополнительной информации смотрите mat2gray (Image Processing Toolbox).

Изменение формы данных

Для генерации кода данные предиктора для обучения должны быть в таблице числовых переменных или числовой матрице.

Измените форму данных на матрицу таким образом, чтобы переменные предиктора (интенсивность пикселей) соответствовали столбцам, а изображения (наблюдения) - строкам. Потому что reshape принимает элементы столбцово, необходимо транспонировать его результат.

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

Чтобы гарантировать, что предварительная обработка данных поддерживает изображение, постройте первое наблюдение в X.

figure
imshow(reshape(X(1,:),sqrt(p)*[1 1]),[],'InitialMagnification','fit')

Извлечение функций

Computer Vision Toolbox™ предлагает несколько методов редукции данных. Одним из таких методов является экстракция гистограммы ориентированного градиента (HOG) функций. Чтобы узнать, как обучить модель ECOC с помощью функций HOG, смотрите Классификацию цифр с использованием функций HOG (Computer Vision Toolbox). Для получения дополнительной информации о других поддерживаемых методах смотрите Локальный признак Detection and Extraction (Computer Vision Toolbox). Этот пример использует скорректированную интенсивность пикселей в качестве переменных.

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

Линейные модели SVM часто применяются к наборам данных изображения для классификации. Однако SVM являются двоичными классификаторами, и в наборе данных есть 10 возможных классов.

Можно создать многоклассовую модель из нескольких двоичных учащихся SVM с помощью fitcecoc. fitcecoc объединяет несколько двоичных учащихся с помощью проекта кодирования. По умолчанию fitcecoc применяет проект «один от одного», который задает обучение двоичных учащихся на основе наблюдений от всех комбинаций пар классов. Например, в задаче с 10 классами fitcecoc необходимо обучить 45 двоичных моделей SVM.

В целом, когда вы обучаете классификационную модель, вы должны настроить гиперпараметры, пока вы не достигнете удовлетворительной ошибки обобщения. То есть следует провести перекрестную проверку моделей для конкретных наборов гиперпараметров, а затем сравнить несовпадающие скорости классификации.

Можно выбрать свои собственные наборы значений гиперзначений параметров, или можно задать, чтобы реализовать байесовскую оптимизацию. (Общие сведения о байесовской оптимизации см. в разделе Рабочий процесс байесовской оптимизации.) Этот пример выполняет перекрестную валидацию по выбранной сетке значений.

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

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

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

Для всех моделей сохраните 5-кратные перекрестные проверенные коэффициенты неправильной классификации.

coding = {'onevsone' 'onevsall'};
boxconstraint = logspace(-1,2,3);
cvLoss = 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});
        cvLoss(i,j) = kfoldLoss(CVMdl);
        fprintf('cvLoss = %f for model using %s coding and box constraint=%f\n',...
            cvLoss(i,j),coding{i},boxconstraint(j))
    end
end
cvLoss = 0.052083 for model using onevsone coding and box constraint=0.100000
cvLoss = 0.055000 for model using onevsone coding and box constraint=3.162278
cvLoss = 0.050000 for model using onevsone coding and box constraint=100.000000
cvLoss = 0.116667 for model using onevsall coding and box constraint=0.100000
cvLoss = 0.123750 for model using onevsall coding and box constraint=3.162278
cvLoss = 0.125000 for model using onevsall coding and box constraint=100.000000

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

minCVLoss = min(cvLoss(:))
minCVLoss = 0.0500
linIdx = find(cvLoss == minCVLoss);
[bestI,bestJ] = ind2sub(size(cvLoss),linIdx);
bestCoding = coding{bestI}
bestCoding = 
'onevsone'
bestBoxConstraint = boxconstraint(bestJ)
bestBoxConstraint = 100
t = templateSVM('BoxConstraint',bestBoxConstraint,'Standardize',true);
Mdl = fitcecoc(X(idxTrn,:),Y(idxTrn),'Learners',t,'Coding',bestCoding);

Создайте матрицу неточностей для тестовых изображений.

testImages = X(idxTest,:);
testLabels = predict(Mdl,testImages);
confusionMatrix = confusionchart(Y(idxTest),testLabels);

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

Если вы удовлетворены эффективностью Mdl, затем можно продолжить, чтобы сгенерировать код для предсказания. В противном случае можно продолжить настройку гиперпараметров. Например, можно попробовать обучить учащихся SVM с помощью различных функций ядра.

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

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

saveLearnerForCoder(Mdl,'DigitImagesECOC')

saveLearnerForCoder уплотняет Mdl, преобразует его в массив структур и сохраняет в MAT-файле DigitImagesECOC.mat.

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

Задайте функцию точки входа с именем predictDigitECOC.m что делает следующее:

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

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

  • Загрузка DigitImagesECOC.mat использование loadLearnerForCoder.

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

type predictDigitECOC.m % Display contents of predictDigitECOC.m file
function label = predictDigitECOC(X) %#codegen
%PREDICTDIGITECOC Classify digit in image using ECOC Model 
%   PREDICTDIGITECOC classifies the 28-by-28 images in the rows of X using
%   the compact ECOC model in the file DigitImagesECOC.mat, and then
%   returns class labels in label.
CompactMdl = loadLearnerForCoder('DigitImagesECOC.mat');
label = predict(CompactMdl,X); 
end

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

Проверьте, что функция предсказания возвращает те же метки тестового набора, что и predict.

pfLabels = predictDigitECOC(testImages);
verifyPF = isequal(pfLabels,testLabels)
verifyPF = logical
   1

isequal возвращает логический 1 (true), что означает, что все входы равны. The predictDigitECOC приводит к ожидаемым результатам.

Решите, какое окружение выполнять сгенерированный код

Сгенерированный код может выполняться:

  • Внутри окружения MATLAB в виде файла MEX на C

  • За пределами MATLAB окружения как независимого исполняемого файла

  • Вне окружения MATLAB как общая утилита, связанная с другим независимым исполняемым файлом

Этот пример генерирует файл MEX, который будет запускаться в среде MATLAB. Генерация такого файла MEX позволяет вам протестировать сгенерированный код с помощью средств MATLAB перед развертыванием функции вне окружения MATLAB. В MEX-функцию можно включить код для верификации, но не для генерации кода, объявив команды внешними, используя coder.extrinsic (MATLAB Coder). Внешние команды могут включать функции, которые не имеют поддержки генерации кода. Все внешние команды в MEX-функция выполняются в MATLAB, но codegen не генерирует код для них.

Если вы планируете развернуть код вне окружения MATLAB, то необходимо сгенерировать независимый исполняемый файл. Один из способов задать выбор компилятора - это использовать -config опция codegen. Для примера, чтобы сгенерировать статический исполняемый файл C, задайте -config:exe когда вы звоните codegen. Для получения дополнительной информации об установке опций генерации кода смотрите -config опция codegen (MATLAB Coder).

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

Скомпилируйте predictDigitECOC.m в файл MEX с использованием codegen. Задайте следующие опции:

  • -report - Генерирует отчет компиляции, который идентифицирует оригинальный код MATLAB и связанные файлы, которые codegen создает во время генерации кода.

  • -args - MATLAB Coder требует, чтобы вы задали свойства всех входных аргументов функции. Один из способов сделать это - обеспечить codegen с примером входа значений. Следовательно, MATLAB Coder выводит свойства из значений примера. Задайте изображения тестового набора, сопоставимые с X.

codegen predictDigitECOC -report -args {testImages}
Code generation successful: View report

codegen успешно сгенерирован код для функции предсказания. Просмотреть отчет можно нажав на View report ссылка или путем ввода open('codegen/mex/predictDigitECOC/html/report.mldatx') в Командном окне. Если генерация кода неудачна, то отчет может помочь вам отладить.

codegen создает директорию pwd/codegen/mex/predictDigitECOC, где pwd - ваша текущая рабочая директория. В дочерней директории codegen генерирует, помимо прочего, файл MEX predictDigitECOC_mex.mexw64.

Проверьте, что файл MEX возвращает те же метки, что и predict.

mexLabels = predictDigitECOC_mex(testImages);
verifyMEX = isequal(mexLabels,testLabels)
verifyMEX = logical
   1

isequal возвращает логический 1 (true), что означает, что файл MEX дает ожидаемые результаты.

См. также

| | | (MATLAB CODER)

Похожие темы