Генерация кода с фиксированной точкой для предсказания SVM

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

Этот график потока показывает рабочий процесс генерации кода с фиксированной точкой.

  1. Обучите модель SVM.

  2. Сохраните обученную модель при помощи saveLearnerForCoder.

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

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

  5. (Необязательно) Оптимизируйте типы данных с фиксированной точкой.

  6. Сгенерируйте код C/C + + с фиксированной точкой.

  7. Проверьте сгенерированный код.

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

  1. Запишите минимальное и максимальное значения переменных для предсказания при помощи buildInstrumentedMex (Fixed-Point Designer).

  2. Просмотр результатов инструментирования с помощью showInstrumentationResults (Fixed-Point Designer). Затем настройте типы данных с фиксированной точкой (при необходимости), чтобы предотвратить переполнение и нижнее течение, и улучшить точность кода с фиксированной точкой.

В этом рабочем процессе вы определяете типы данных с фиксированной точкой с помощью функции типа данных, сгенерированной из generateLearnerDataTypeFcn. Отделение типов данных переменных от алгоритма упрощает проверку. Можно программно переключать типы данных между плавающей и фиксированной точками с помощью входного параметра функции типа данных. Кроме того, этот рабочий процесс совместим с рабочим процессом ручного преобразования фиксированной точки (Fixed-Point Designer).

Предварительная обработка данных

Загрузите census1994 набор данных. Этот набор данных состоит из демографических данных Бюро переписи населения США, используемых для прогнозирования того, зарабатывает ли индивидуум более 50 000 долларов в год.

load census1994

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

tbl = adultdata(:,{'age','education_num','capital_gain','capital_loss','hours_per_week'});

Печать сводных данных по таблице.

summary(tbl)
Variables:

    age: 32561×1 double

        Values:

            Min          17   
            Median       37   
            Max          90   

    education_num: 32561×1 double

        Values:

            Min           1   
            Median       10   
            Max          16   

    capital_gain: 32561×1 double

        Values:

            Min            0  
            Median         0  
            Max        99999  

    capital_loss: 32561×1 double

        Values:

            Min            0  
            Median         0  
            Max         4356  

    hours_per_week: 32561×1 double

        Values:

            Min           1   
            Median       40   
            Max          99   

Шкалы переменных несовместимы. В этом случае можно обучить модель с помощью стандартизированного набора данных путем определения 'Standardize' Аргумент пары "имя-значение" из fitcsvm. Однако добавление операций стандартизации к коду с фиксированной точкой может снизить точность и увеличить использование памяти. Вместо этого можно вручную стандартизировать набор данных, как показано в этом примере. Пример также описывает, как проверить использование памяти в конце.

Генерация кода с фиксированной точкой не поддерживает таблицы или категориальные массивы. Итак, задайте данные предиктора X используя числовую матрицу и задавая метки классов Y использование логического вектора. Логический вектор использует память наиболее эффективно в двоичной задаче классификации.

X = table2array(tbl);
Y = adultdata.salary == '<=50K';

Задайте веса наблюдений w.

w = adultdata.fnlwgt;

Использование памяти обученной модели увеличивается, когда количество векторов поддержки в модели увеличивается. Чтобы уменьшить количество векторов поддержки, можно увеличить прямоугольное ограничение при обучении с помощью 'BoxConstraint' аргумент пары "имя-значение" или используйте вложенный репрезентативный набор данных для обучения. Обратите внимание, что увеличение ограничения коробки может привести к увеличению времени обучения, а использование субдискретизированного набора данных может снизить точность обученной модели. В этом примере вы случайным образом дискретизируете 1000 наблюдений из набора данных и используете субдискретизированные данные для обучения.

rng('default') % For reproducibility
[X_sampled,idx] = datasample(X,1000,'Replace',false);
Y_sampled = Y(idx);
w_sampled = w(idx);

Найдите взвешенные средства и стандартные отклонения путем настройки модели с помощью 'Weight' и 'Standardize' Аргументы пары "имя-значение".

tempMdl = fitcsvm(X_sampled,Y_sampled,'Weight',w_sampled,'KernelFunction','gaussian','Standardize',true);
mu = tempMdl.Mu;
sigma = tempMdl.Sigma;

Если вы не используете 'Cost', 'Prior', или 'Weight' Аргументом пары "имя-значение" для обучения, тогда можно найти среднее и стандартные значения отклонения при помощи zscore функция.

[standardizedX_sampled,mu,sigma] = zscore(X_sampled);

Стандартизируйте данные предиктора при помощи mu и sigma.

standardizedX = (X-mu)./sigma;
standardizedX_sampled = standardizedX(idx,:);

Можно использовать набор тестовых данных, чтобы подтвердить обученную модель и протестировать MEX-функцию с инструментами. Задайте набор тестовых данных и стандартизируйте данные предиктора тестирования при помощи mu и sigma.

XTest = table2array(adulttest(:,{'age','education_num','capital_gain','capital_loss','hours_per_week'}));
standardizedXTest = (XTest-mu)./sigma;
YTest = adulttest.salary == '<=50K';

Обучите модель

Обучите двоичную модель классификации SVM.

Mdl = fitcsvm(standardizedX_sampled,Y_sampled,'Weight',w_sampled,'KernelFunction','gaussian');

Mdl является ClassificationSVM модель.

Вычислите ошибку классификации для набора обучающих данных и тестовых данных набора.

loss(Mdl,standardizedX_sampled,Y_sampled) 
ans = 0.1663
loss(Mdl,standardizedXTest,YTest)
ans = 0.1905

Классификатор SVM неправильно классифицирует приблизительно 17% обучающих данных и 19% тестовых данных.

Сохраните модель

Сохраните модель классификации SVM в файл myMdl.mat при помощи saveLearnerForCoder.

saveLearnerForCoder(Mdl,'myMdl');

Задайте типы данных с фиксированной точкой

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

generateLearnerDataTypeFcn('myMdl',[standardizedX; standardizedXTest])

generateLearnerDataTypeFcn генерирует myMdl_datatype функция. Отображение содержимого myMdl_datatype.m при помощи type функция.

type myMdl_datatype.m
function T = myMdl_datatype(dt)
%MYMDL_DATATYPE Define data types for fixed-point code generation
%   
%   T = MYMDL_DATATYPE(DT) returns the data type structure T, which defines
%   data types for the variables required to generate fixed-point C/C++ code
%   for prediction of a machine learning model. Each field of T contains a
%   fixed-point object returned by fi. The input argument dt specifies the
%   DataType property of the fixed-point object. Specify dt as 'Fixed' (default)
%   for fixed-point code generation or specify dt as 'Double' to simulate
%   floating-point behavior of the fixed-point code.
%   
%   Use the output structure T as both an input argument of an entry-point
%   function and the second input argument of loadLearnerForCoder within the
%   entry-point function. For more information, see loadLearnerForCoder.
     
%   File: myMdl_datatype.m
%   Statistics and Machine Learning Toolbox Version 12.0 (Release R2021a)
%   Generated by MATLAB, 02-Oct-2020 14:18:50
     
if nargin < 1
	dt = 'Fixed';
end

% Set fixed-point math settings
fm = fimath('RoundingMethod','Floor', ...
    'OverflowAction','Wrap', ...
    'ProductMode','FullPrecision', ...
    'MaxProductWordLength',128, ...
    'SumMode','FullPrecision', ...
    'MaxSumWordLength',128);

% Data type for predictor data
T.XDataType = fi([],true,16,11,fm,'DataType',dt);

% Data type for output score
T.ScoreDataType = fi([],true,16,14,fm,'DataType',dt);

% Internal variables
% Data type of the squared distance dist = (x-sv)^2 for the Gaussian kernel G(x,sv) = exp(-dist),
% where x is the predictor data for an observation and sv is a support vector
T.InnerProductDataType = fi([],true,16,6,fm,'DataType',dt);


end

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

The myMdl_datatype функция использует размер слова по умолчанию (16) и предлагает максимальную длину дроби, чтобы избежать переполнения, основанную на размере слова по умолчанию (16) и запасе прочности (10%) для каждой переменной.

Создайте структуру T который определяет типы данных с фиксированной точкой при помощи myMdl_datatype.

T = myMdl_datatype('Fixed')
T = struct with fields:
               XDataType: [0×0 embedded.fi]
           ScoreDataType: [0×0 embedded.fi]
    InnerProductDataType: [0×0 embedded.fi]

Структура T включает поля для именованных и внутренних переменных, необходимых для запуска predict функция. Каждое поле содержит объект с фиксированной точкой, возвращаемый fi (Fixed-Point Designer). Для примера отобразите свойства типа данных с фиксированной точкой данных предиктора.

T.XDataType
ans = 

[]

          DataTypeMode: Fixed-point: binary point scaling
            Signedness: Signed
            WordLength: 16
        FractionLength: 11

        RoundingMethod: Floor
        OverflowAction: Wrap
           ProductMode: FullPrecision
  MaxProductWordLength: 128
               SumMode: FullPrecision
      MaxSumWordLength: 128

Для получения дополнительной информации о сгенерированной функции и структуре смотрите Data Type Function.

Задайте функцию точки входа

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

  • Примите данные предиктора X и структуру типа данных с фиксированной точкой T.

  • Загрузка версии обученной модели классификации SVM с фиксированной точкой с помощью обоих loadLearnerForCoder и структуру T.

  • Спрогнозируйте метки и счета, используя загруженную модель.

function [label,score] = myFixedPointPredict(X,T) %#codegen
Mdl = loadLearnerForCoder('myMdl','DataType',T);
[label,score] = predict(Mdl,X);
end

(Необязательно) Оптимизация типов данных с фиксированной точкой

Оптимизируйте типы данных с фиксированной точкой при помощи buildInstrumentedMex и showInstrumentationResults. Запишите минимальные и максимальные значения всех именованных и внутренних переменных для предсказания при помощи buildInstrumentedMex. Просмотр результатов инструментирования с помощью showInstrumentationResults; затем на основе результатов настройте свойства типа данных с фиксированной точкой переменных.

Задайте типы входных параметров функции точки входа

Задайте типы входных параметров myFixedPointPredict использование массива ячеек 2 на 1.

ARGS = cell(2,1);

Первый входной параметр является данными предиктора. The XDataType поле структуры T задает тип данных предиктора с фиксированной точкой. Преобразование X к типу, указанному в T.XDataType при помощи cast (Fixed-Point Designer) функцию.

X_fx = cast(standardizedX,'like',T.XDataType);

Набор тестовых данных не имеет того же размера, что и набор обучающих данных. Задайте ARGS{1} при помощи coder.typeof (MATLAB Coder), чтобы MEX-функция могла принимать входы переменного размера.

ARGS{1} = coder.typeof(X_fx,size(standardizedX),[1,0]);

Вторым входным параметром является структура T, которая должна быть константой времени компиляции. Использование coder.Constant (MATLAB Coder), чтобы задать T как константа во время генерации кода.

ARGS{2} = coder.Constant(T);

Создайте инструментальную MEX-функцию

Создайте инструментальную MEX-функцию при помощи buildInstrumentedMex (Fixed-Point Designer).

  • Задайте типы входных параметров функции точки входа при помощи -args опция.

  • Укажите имя MEX-функции при помощи -o опция.

  • Вычислите гистограмму при помощи -histogram опция.

  • Разрешить полную поддержку генерации кода при помощи -coder опция.

buildInstrumentedMex myFixedPointPredict -args ARGS -o myFixedPointPredict_instrumented -histogram -coder

Тестовые MEX-функции

Запустите инструментальную MEX-функцию, чтобы записать результаты инструментирования.

[labels_fx1,scores_fx1] = myFixedPointPredict_instrumented(X_fx,T);

Можно запустить инструментальную MEX-функцию несколько раз, чтобы записать результаты из различных наборов тестовых данных. Запустите инструментальную MEX-функцию с помощью standardizedXTest.

Xtest_fx = cast(standardizedXTest,'like',T.XDataType);
[labels_fx1_test,scores_fx1_test] = myFixedPointPredict_instrumented(Xtest_fx,T);

Просмотр результатов инструментальной MEX-функции

Функции showInstrumentationResults (Fixed-Point Designer), чтобы открыть отчет, содержащий результаты инструментирования. Просмотрите минимальное и максимальное значения симуляции, предложенную длину дроби, процент текущей области значений и состояние целого числа.

showInstrumentationResults('myFixedPointPredict_instrumented')

Предлагаемые размеры слова и длины дробей в X те же, что и в XDataType в структуре T.

Просмотрите гистограмму переменной, щелкнув на вкладке Переменные.

Окно содержит гистограмму и диалоговые панели с информацией о переменной. Для получения информации об этом окне смотрите NumericTypeScope (Fixed-Point Designer) страницу с описанием.

Очистить результаты можно используя команду clearInstrumentationResults (Fixed-Point Designer).

clearInstrumentationResults('myFixedPointPredict_instrumented')

Проверьте инструментальную MEX-функцию

Сравните выходы predict и myFixedPointPredict_instrumented.

[labels,scores] = predict(Mdl,standardizedX);
verify_labels1 = isequal(labels,labels_fx1)
verify_labels1 = logical
   0

isequal возвращает логический 1 (true), если labels и labels_fx1 равны. Если метки не равны, можно вычислить процент неправильно классифицированных меток следующим образом.

diff_labels1 = sum(strcmp(string(labels_fx1),string(labels))==0)/length(labels_fx1)*100
diff_labels1 = 0.1228

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

diff_scores1 = max(abs((scores_fx1.double(:,1)-scores(:,1))./scores(:,1)))
diff_scores1 = 52.5890

Настройка типов данных с фиксированной точкой

Можно настроить типы данных с фиксированной точкой, если записанные результаты показывают переполнение или нижнее течение, или если вы хотите улучшить точность сгенерированного кода. Измените типы данных с фиксированной точкой путем обновления myMdl_datatype функция и создание новой структуры, а затем сгенерируйте код с помощью новой структуры. Как обновить myMdl_datatype функция, можно вручную изменить типы данных с фиксированной точкой в файле функции (myMdl_datatype.m). Или можно сгенерировать функцию при помощи generateLearnerDataTypeFcn и указание большего размера слова, как показано в этом примере. Для получения дополнительной информации см. советы».

Сгенерируйте новую функцию типа данных. Задайте размер слова 32 и имя myMdl_datatype2 для сгенерированной функции.

generateLearnerDataTypeFcn('myMdl',[standardizedX; standardizedXTest],'WordLength',32,'OutputFunctionName','myMdl_datatype2')

Отображение содержимого myMdl_datatype2.m.

type myMdl_datatype2.m
function T = myMdl_datatype2(dt)
%MYMDL_DATATYPE2 Define data types for fixed-point code generation
%   
%   T = MYMDL_DATATYPE2(DT) returns the data type structure T, which defines
%   data types for the variables required to generate fixed-point C/C++ code
%   for prediction of a machine learning model. Each field of T contains a
%   fixed-point object returned by fi. The input argument dt specifies the
%   DataType property of the fixed-point object. Specify dt as 'Fixed' (default)
%   for fixed-point code generation or specify dt as 'Double' to simulate
%   floating-point behavior of the fixed-point code.
%   
%   Use the output structure T as both an input argument of an entry-point
%   function and the second input argument of loadLearnerForCoder within the
%   entry-point function. For more information, see loadLearnerForCoder.
     
%   File: myMdl_datatype2.m
%   Statistics and Machine Learning Toolbox Version 12.0 (Release R2021a)
%   Generated by MATLAB, 02-Oct-2020 14:19:31
     
if nargin < 1
	dt = 'Fixed';
end

% Set fixed-point math settings
fm = fimath('RoundingMethod','Floor', ...
    'OverflowAction','Wrap', ...
    'ProductMode','FullPrecision', ...
    'MaxProductWordLength',128, ...
    'SumMode','FullPrecision', ...
    'MaxSumWordLength',128);

% Data type for predictor data
T.XDataType = fi([],true,32,27,fm,'DataType',dt);

% Data type for output score
T.ScoreDataType = fi([],true,32,30,fm,'DataType',dt);

% Internal variables
% Data type of the squared distance dist = (x-sv)^2 for the Gaussian kernel G(x,sv) = exp(-dist),
% where x is the predictor data for an observation and sv is a support vector
T.InnerProductDataType = fi([],true,32,22,fm,'DataType',dt);


end

The myMdl_datatype2 функция задает размер слова 32 и предлагает максимальную длину дроби, чтобы избежать переполнения.

Создайте структуру T2 который определяет типы данных с фиксированной точкой при помощи myMdl_datatype2.

T2 = myMdl_datatype2('Fixed')
T2 = struct with fields:
               XDataType: [0×0 embedded.fi]
           ScoreDataType: [0×0 embedded.fi]
    InnerProductDataType: [0×0 embedded.fi]

Создайте новую инструментальную MEX-функцию, запишите результаты и просмотрите результаты при помощи buildInstrumentedMex и showInstrumentationResults.

X_fx2 = cast(standardizedX,'like',T2.XDataType);
buildInstrumentedMex myFixedPointPredict -args {X_fx2,coder.Constant(T2)} -o myFixedPointPredict_instrumented2 -histogram -coder
[labels_fx2,scores_fx2] = myFixedPointPredict_instrumented2(X_fx2,T2);
showInstrumentationResults('myFixedPointPredict_instrumented2')

Проверьте отчет инструментирования, а затем очистите результаты.

clearInstrumentationResults('myFixedPointPredict_instrumented2')

Проверьте myFixedPointPredict_instrumented2.

verify_labels2 = isequal(labels,labels_fx2)
verify_labels2 = logical
   0

diff_labels2 = sum(strcmp(string(labels_fx2),string(labels))==0)/length(labels_fx2)*100
diff_labels2 = 0.0031
diff_scores2 = max(abs((scores_fx2.double(:,1)-scores(:,1))./scores(:,1)))
diff_scores2 = 2.2793

Процент неправильно классифицированных меток diff_labels2 и относительное различие значений баллов diff_scores2 меньше, чем от предыдущей MEX-функции, сгенерированной с использованием размера слова по умолчанию (16).

Для получения дополнительной информации об оптимизации типов данных с фиксированной точкой с помощью инструментария кода MATLAB ®, смотрите страницы с описанием buildInstrumentedMex (Fixed-Point Designer), showInstrumentationResults (Fixed-Point Designer), и clearInstrumentationResults (Fixed-Point Designer) и пример Задать типы данных Используя Min/Max Instrumentation (Fixed-Point Designer).

Сгенерируйте код

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

codegen myFixedPointPredict -args {coder.typeof(X_fx2,[1,5],[0,0]),coder.Constant(T2)}

codegen генерирует MEX-функцию myFixedPointPredict_mex с зависящим от платформы внутренним абонентом.

Проверьте сгенерированный код

Можно проверить myFixedPointPredict_mex Функция выполняется таким же образом, как и MEX-функция с инструментами. Для получения дополнительной информации см. раздел «Проверка инструментальных MEX-функций».

[labels_sampled,scores_sampled] = predict(Mdl,standardizedX_sampled);
n = size(standardizedX_sampled,1);
labels_fx = true(n,1);
scores_fx = zeros(n,2);
for i = 1:n
    [labels_fx(i),scores_fx(i,:)] = myFixedPointPredict_mex(X_fx2(idx(i),:),T2);
end
verify_labels = isequal(labels_sampled,labels_fx)
verify_labels = logical
   1

diff_labels = sum(strcmp(string(labels_fx),string(labels_sampled))==0)/length(labels_fx)*100
diff_labels = 0
diff_scores = max(abs((scores_fx(:,1)-scores_sampled(:,1))./scores_sampled(:,1)))
diff_scores = 0.0642

Использование памяти

Хорошей практикой является ручная стандартизация данных предиктора перед обучением модели. Если вы используете 'Standardize' вместо этого аргумент пары "имя-значение", затем сгенерированный код с фиксированной точкой включает операции стандартизации, которые могут вызвать потерю точности и увеличение использования памяти.

Если вы генерируете статическую библиотеку, можно найти использование памяти сгенерированного кода с помощью отчета генерации кода. Задайте -config:lib чтобы сгенерировать статическую библиотеку и использовать -report опция для генерации отчета генерации кода.

codegen myFixedPointPredict -args {coder.typeof(X_fx2,[1,5],[0,0]),coder.Constant(T2)} -o myFixedPointPredict_lib -config:lib -report

На вкладке Summary отчета генерации кода нажмите Code Metrics. В разделе Function Information показан накопленный размер стека.

Чтобы найти использование памяти модели, обученной с 'Standardized','true'можно запустить следующий код.

Mdl = fitcsvm(X_sampled,Y_sampled,'Weight',w_sampled,'KernelFunction','gaussian','Standardize',true);
saveLearnerForCoder(Mdl,'myMdl');
generateLearnerDataTypeFcn('myMdl',[X; XTest],'WordLength',32,'OutputFunctionName','myMdl_standardize_datatype')
T3 = myMdl_standardize_datatype('Fixed');
X_fx3 = cast(X_sampled,'like',T3.XDataType);
codegen myFixedPointPredict -args {coder.typeof(X_fx3,[1,5],[0,0]),coder.Constant(T3)} -o myFixedPointPredict_standardize_lib -config:lib -report

См. также

| | | (Fixed-Point Designer) | (Fixed-Point Designer) | (Fixed-Point Designer) | (Fixed-Point Designer) | (Fixed-Point Designer) | (MATLAB Coder)

Похожие темы