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

Обучение модели SVM.
Сохранение обучаемой модели с помощью saveLearnerForCoder.
Определение типов данных с фиксированной точкой для переменных, необходимых для прогнозирования, с помощью функции типа данных, созданной generateLearnerDataTypeFcn.
Определите функцию точки входа, которая загружает модель, используя обе loadLearnerForCoder и структура, а затем вызывает predict функция.
(Необязательно) Оптимизируйте типы данных с фиксированной точкой.
Создание кода C/C + + с фиксированной точкой.
Проверьте созданный код.
Шаг 5 является необязательным шагом для улучшения производительности генерируемого кода с фиксированной точкой. Для этого повторите следующие два шага до тех пор, пока вы не будете удовлетворены производительностью кода:
Запишите минимальное и максимальное значения переменных для прогнозирования с помощью buildInstrumentedMex (Конструктор фиксированных точек).
Просмотр результатов инструментирования с помощью showInstrumentationResults (Конструктор фиксированных точек). Затем настройте типы данных с фиксированной точкой (при необходимости) для предотвращения переполнения и недозаполнения, а также для повышения точности кода с фиксированной точкой.
В этом рабочем процессе типы данных с фиксированной точкой определяются с помощью функции типа данных, созданной из generateLearnerDataTypeFcn. Выделение типов данных переменных из алгоритма упрощает тестирование. Можно программно переключать типы данных между плавающей и фиксированной точками с помощью входного аргумента функции типа данных. Кроме того, этот рабочий процесс совместим с рабочим процессом преобразования фиксированных точек вручную (конструктор фиксированных точек).
Загрузить 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 откроет папку примеров. Эта папка содержит файл функции начального уровня.
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 (Конструктор фиксированных точек). Например, отображение свойств типа данных с фиксированной точкой данных предиктора.
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
Дополнительные сведения о созданной функции и структуре см. в разделе Функция типа данных.
Определение функции точки входа с именем myFixedPointPredict это делает следующее:
Принять данные предиктора X и структура типа данных с фиксированной точкой T.
Загрузка версии с фиксированной точкой обученной модели классификации SVM с использованием обеих loadLearnerForCoder и структура Т.
Прогнозирование меток и оценок с использованием загруженной модели.
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);
Первым входным аргументом являются данные предиктора. XDataType поле структуры T указывает тип данных предиктора с фиксированной точкой. Новообращенный X к типу, указанному в T.XDataType с помощью cast (Конструктор фиксированных точек).
X_fx = cast(standardizedX,'like',T.XDataType);Набор тестовых данных не имеет того же размера, что и набор обучающих данных. Определить ARGS{1} с помощью coder.typeof (Кодер MATLAB), чтобы функция MEX могла принимать входные данные переменного размера.
ARGS{1} = coder.typeof(X_fx,size(standardizedX),[1,0]);Вторым входным аргументом является структура T, которая должна быть константой времени компиляции. Использовать coder.Constant (Кодер MATLAB) для указания T как константа во время генерации кода.
ARGS{2} = coder.Constant(T);Создание инструментальной функции MEX
Создание инструментальной функции MEX с помощью buildInstrumentedMex (Конструктор фиксированных точек).
Укажите типы входных аргументов функции точки входа с помощью -args вариант.
Укажите имя функции MEX с помощью -o вариант.
Вычислите гистограмму с помощью -histogram вариант.
Разрешить полную поддержку генерации кода с помощью -coder вариант.
buildInstrumentedMex myFixedPointPredict -args ARGS -o myFixedPointPredict_instrumented -histogram -coder
Проверка инструментальной функции MEX
Выполните функцию instrumented 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 (Конструктор фиксированных точек), чтобы открыть отчет, содержащий результаты инструментирования. Просмотрите минимальное и максимальное значения моделирования, предлагаемую длину дроби, процент текущего диапазона и состояние целого числа.
showInstrumentationResults('myFixedPointPredict_instrumented')
Предлагаемые длины слов и дроби в X такие же, как в XDataType в структуре T.
Просмотрите гистограмму переменной, щелкнув
вкладку Переменные.

Окно содержит гистограмму и диалоговые панели с информацией о переменной. Для получения информации об этом окне см. NumericTypeScope( Конструктор фиксированных точек).
Очистить результаты с помощью clearInstrumentationResults (Конструктор фиксированных точек).
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
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 (Конструктор фиксированных точек), showInstrumentationResults (Конструктор фиксированных точек), и clearInstrumentationResults (Конструктор фиксированных точек) и пример «Установка типов данных с использованием Min/Max Instrumentation» (Конструктор фиксированных точек).
Создание кода для функции точки входа с помощью 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
На вкладке Сводка отчета о создании кода щелкните Метрики кода. В разделе 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 (Конструктор фиксированных точек) | cast (Конструктор фиксированных точек) | clearInstrumentationResults (Конструктор фиксированных точек) | fi (Конструктор фиксированных точек) | showInstrumentationResults (Конструктор фиксированных точек) | codegen (Кодер MATLAB)