В этом примере показано, как сгенерировать фиксированную точку код C/C++ для предсказания модели машины опорных векторов (SVM). По сравнению с общим рабочим процессом генерации кода C/C++ генерация фиксированной точки требует дополнительного шага, который задает типы данных с фиксированной точкой переменных, требуемых для предсказания. Создайте структуру типа данных с фиксированной точкой при помощи generateLearnerDataTypeFcn
, и используйте структуру в качестве входного параметра loadLearnerForCoder
в функции точки входа. Можно также оптимизировать типы данных с фиксированной точкой прежде, чем сгенерировать код.
Эта блок-схема показывает рабочий процесс генерации фиксированной точки.
Обучите модель SVM.
Сохраните обученную модель при помощи saveLearnerForCoder
.
Задайте типы данных с фиксированной точкой переменных, требуемых для предсказания при помощи функции типа данных, сгенерированной generateLearnerDataTypeFcn
.
Задайте функцию точки входа, которая загружает модель при помощи обоих loadLearnerForCoder
и структура, и затем вызывает predict
функция.
(Необязательно) Оптимизируйте типы данных с фиксированной точкой.
Сгенерируйте фиксированную точку код C/C++.
Проверьте сгенерированный код.
Шаг 5 является дополнительным шагом, чтобы улучшать производительность сгенерированной фиксированной точки. Для этого повторите эти два шага, пока вы не будете удовлетворены производительностью кода:
Запишите минимальные и максимальные значения переменных для предсказания при помощи buildInstrumentedMex
.
Просмотрите результаты инструментирования с помощью showInstrumentationResults
. Затем настройте типы данных с фиксированной точкой (при необходимости), чтобы предотвратить переполнение и потерю значимости, и улучшить точность фиксированной точки.
В этом рабочем процессе вы задаете типы данных с фиксированной точкой при помощи функции типа данных, сгенерированной от 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: 32561x1 double Values: Min 17 Median 37 Max 90 education_num: 32561x1 double Values: Min 1 Median 10 Max 16 capital_gain: 32561x1 double Values: Min 0 Median 0 Max 99999 capital_loss: 32561x1 double Values: Min 0 Median 0 Max 4356 hours_per_week: 32561x1 double Values: Min 1 Median 40 Max 99
Шкалы переменных не сопоставимы. В этом случае можно обучить модель с помощью стандартизированного набора данных путем определения 'Standardize'
аргумент пары "имя-значение" fitcsvm
. Однако добавление операций для стандартизации к фиксированной точке может уменьшать точность и увеличить использование памяти. Вместо этого можно вручную стандартизировать набор данных, как показано в этом примере. Пример также описывает, как проверять использование памяти в конце.
Генерация кода не поддерживает таблицы или категориальные массивы. Так, задайте данные о предикторе X
использование числовой матрицы, и задает класс, маркирует Y
использование логического вектора. Логический вектор использует память наиболее эффективно в бинарной проблеме классификации.
X = table2array(tbl);
Y = adultdata.salary == '<=50K';
Задайте веса наблюдения w
.
w = adultdata.fnlwgt;
Использование памяти обученной модели увеличивается как количество векторов поддержки в увеличениях модели. Чтобы сократить количество векторов поддержки, можно увеличить ограничение поля когда обучение при помощи 'BoxConstraint'
аргумент пары "имя-значение" или использование подпроизведенный представительный набор данных для обучения. Обратите внимание на то, что увеличение ограничения поля может привести к более длительным учебным временам, и использование набора подвыборочных данных может уменьшать точность обученной модели. В этом примере, вы случайным образом демонстрационные 1 000 наблюдений от набора данных и использования подвыборочные данные для обучения.
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 11.7 (Release R2020a) % Generated by MATLAB, 30-Jan-2020 00:17:45 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: [0x0 embedded.fi]
ScoreDataType: [0x0 embedded.fi]
InnerProductDataType: [0x0 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
и структура 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);
Первый входной параметр является данными о предикторе. XDataType
поле структуры T
задает тип данных с фиксированной точкой данных о предикторе. Преобразуйте X
к типу, заданному в T.XDataType
при помощи cast
функция.
X_fx = cast(standardizedX,'like',T.XDataType);
Набор тестовых данных не имеет того же размера как обучающий набор данных. Задайте ARGS{1}
при помощи coder.typeof
так, чтобы MEX-функция могла взять входные параметры переменного размера.
ARGS{1} = coder.typeof(X_fx,size(standardizedX),[1,0]);
Второй входной параметр является структурой T
, который должен быть постоянным временем компиляции. Используйте coder.Constant
задавать T
как константа во время генерации кода.
ARGS{2} = coder.Constant(T);
Создайте оснащенную MEX-функцию
Создайте оснащенную MEX-функцию при помощи buildInstrumentedMex
.
Задайте типы входного параметра функции точки входа при помощи -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
открыть отчет, содержащий результаты инструментирования. Просмотрите симуляцию минимальные и максимальные значения, предложил дробную длину, процент текущей области значений и состояние целого числа.
showInstrumentationResults('myFixedPointPredict_instrumented')
Предложенные размеры слова и дробные длины в X
совпадают с теми в XDataType
в структуре T
.
Просмотрите гистограмму для переменной путем нажатия на вкладку Variables.
Окно содержит гистограмму и диалоговые панели с информацией о переменной. Для получения информации об этом окне смотрите 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
возвращает логическую единицу, (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 = 115.9257
Настройте типы данных с фиксированной точкой
Можно настроить типы данных с фиксированной точкой, если записанные результаты показывают переполнение или потерю значимости, или если вы хотите улучшить точность сгенерированного кода. Измените типы данных с фиксированной точкой путем обновления 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 11.7 (Release R2020a) % Generated by MATLAB, 30-Jan-2020 00: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,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: [0x0 embedded.fi]
ScoreDataType: [0x0 embedded.fi]
InnerProductDataType: [0x0 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.3235
Процент неправильно классифицированного маркирует diff_labels2
и относительная разница в значениях баллов diff_scores2
меньше, чем те от предыдущей MEX-функции, сгенерированной с помощью размера слова по умолчанию (16).
Для получения дополнительной информации об оптимизации типов данных с фиксированной точкой путем оснащения кода MATLAB®, смотрите страницы с описанием buildInstrumentedMex
, showInstrumentationResults
, и clearInstrumentationResults
, и Типы данных Набора в качестве примера Используя Инструментирование Min/Max (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-функцию. Смотрите раздел Verify Instrumented MEX Function для деталей.
[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.0645
Хорошая практика должна вручную стандартизировать данные о предикторе перед обучением модель. Если вы используете '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
buildInstrumentedMex
| cast
| clearInstrumentationResults
| codegen
| fi
| generateLearnerDataTypeFcn
| loadLearnerForCoder
| saveLearnerForCoder
| showInstrumentationResults