Генерация фиксированной точки для прогноза 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.

  2. Просмотрите результаты инструментирования с помощью 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 that 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.6 (Release R2019b)
%   Generated by MATLAB, 23-Dec-2019 15:17:14
     
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.

  • Предскажите метки и баллы с помощью загруженной модели.

type myFixedPointPredict.mlx % Display contents of myFixedPointPredict.mlx file
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 that 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.6 (Release R2019b)
%   Generated by MATLAB, 23-Dec-2019 15:18:14
     
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

Смотрите также

| | | | | | | |

Похожие темы