В этом примере показано, как сгенерировать код 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.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
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)