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

Обучите модель SVM.
Сохраните обученную модель при помощи saveLearnerForCoder.
Определите типы данных с фиксированной точкой переменных, необходимых для предсказания, используя функцию типа данных, сгенерированную generateLearnerDataTypeFcn.
Задайте функцию точки входа, которая загружает модель с помощью обоих loadLearnerForCoder и структуру, а затем вызывает predict функция.
(Необязательно) Оптимизируйте типы данных с фиксированной точкой.
Сгенерируйте код C/C + + с фиксированной точкой.
Проверьте сгенерированный код.
Этап 5 является необязательным шагом для улучшения эффективности сгенерированного кода с фиксированной точкой. Для этого повторите эти два шага, пока вы не будете удовлетворены производительностью кода:
Запишите минимальное и максимальное значения переменных для предсказания при помощи buildInstrumentedMex (Fixed-Point Designer).
Просмотр результатов инструментирования с помощью 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.mfunction 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.mfunction 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
generateLearnerDataTypeFcn | loadLearnerForCoder | saveLearnerForCoder | buildInstrumentedMex (Fixed-Point Designer) | cast (Fixed-Point Designer) | clearInstrumentationResults (Fixed-Point Designer) | fi (Fixed-Point Designer) | showInstrumentationResults (Fixed-Point Designer) | codegen (MATLAB Coder)