主要内容

支持向量机预测的定点代码生成

这个例子展示了如何为支持向量机(SVM)模型的预测生成定点C/ c++代码。万博1manbetx与一般的C/ c++代码生成工作流相比,定点代码生成需要一个额外的步骤,该步骤定义预测所需变量的定点数据类型。使用创建定点数据类型结构generateLearnerDataTypeFcn,并使用结构作为的输入参数loadLearnerForCoder在一个入口函数中。您还可以在生成代码之前优化定点数据类型。

这个流程图显示了定点代码生成工作流程。

  1. 训练支持向量机模型。

  2. 使用保存训练的模型saveLearnerForCoder

  3. 使用生成的数据类型函数定义预测所需变量的定点数据类型generateLearnerDataTypeFcn

  4. 定义一个入口点函数,通过使用两者来加载模型loadLearnerForCoder结构,然后调用预测函数。

  5. (可选)优化定点数据类型。

  6. 生成定点C/ c++代码。

  7. 验证生成的代码。

步骤5是一个可选步骤,用于改进生成的定点代码的性能。为此,重复这两个步骤,直到你对代码性能满意为止:

  1. 记录变量的最小值和最大值,以便使用buildInstrumentedMex(定点设计师)

  2. 使用查看检测结果showInstrumentationResults(定点设计师).然后,调优定点数据类型(如果需要)以防止溢出和下溢,并提高定点代码的精度。

在此工作流中,通过使用生成的数据类型函数来定义定点数据类型generateLearnerDataTypeFcn.将变量的数据类型从算法中分离出来可以简化测试。可以使用数据类型函数的输入参数以编程方式在浮点和定点之间切换数据类型。此外,此工作流与手动定点转换工作流(定点设计师)

数据进行预处理

加载census1994数据集。该数据集由美国人口普查局的人口统计数据组成,用于预测一个人的年收入是否超过5万美元。

负载census1994

考虑一个模型,该模型根据员工的年龄、工人阶级、教育水平、资本收益和损失以及每周工作小时数来预测他们的工资类别。提取感兴趣的变量并使用表保存它们。

TBL =成人数据(:,{“年龄”“education_num”“capital_gain”“capital_loss”“hours_per_week”});

打印表的摘要。

总结(台)
变量:age: 32561x1 double值:Min 17 Median 37 Max 90 education_num: 32561x1 double值:Min 1 Median 10 Max 16 capital_gain: 32561x1 double值:Min 0 Median 0 Max 99999 capital_loss: 32561x1 double值:Min 0 Median 0 Max 4356 hours_per_week: 32561x1 double值:Min 1 Median 40 Max 99

变量的尺度不一致。在这种情况下,可以通过指定标准化数据集来训练模型“标准化”的名称-值对参数fitcsvm.但是,将标准化操作添加到定点代码中会降低精度并增加内存使用。相反,您可以手动标准化数据集,如本例所示。该示例还描述了如何在结束时检查内存使用情况。

定点代码生成不支持表或分类数组。万博1manbetx定义预测数据X使用数值矩阵,并定义类标签Y使用逻辑向量。逻辑向量在二进制分类问题中最有效地使用内存。

X = table2array(tbl);Y = adultdata。工资= =“< = 50 k”

定义观察权重w

W = adultdata.fnlwgt;

训练模型的内存使用随着模型中支持向量数量的增加而增加。万博1manbetx为减少支持向量的数量,可以在训练时使用万博1manbetx“BoxConstraint”参数或使用次采样的代表性数据集进行训练。请注意,增加框约束会导致更长的训练时间,并且使用下采样数据集会降低训练模型的准确性。在本例中,您从数据集中随机抽取1000个观测值,并使用次采样数据进行训练。

rng (“默认”%用于再现性[X_sampled,idx] = datasample(X,1000,“替换”、假);Y_sampled = Y(idx);W_sampled = w(idx);

找到加权均值和标准差通过训练模型使用“重量”而且“标准化”名称-值对参数。

tempMdl = fitcsvm(X_sampled,Y_sampled,“重量”w_sampled,“KernelFunction”“高斯”“标准化”,真正的);mu = tempmll . mu;sigma = tempMdl.Sigma;

如果您不使用“成本”“之前”,或“重量”参数的名称-值对参数进行训练,则可以使用zscore函数。

[standarzedx_sampled,mu,sigma] = zscore(X_sampled);

通过使用使预测器数据标准化μ而且σ

标准化x = (X-mu)./sigma;标准化x_sampled =标准化x (idx,:);

您可以使用测试数据集来验证训练过的模型并测试已检测的MEX函数。指定测试数据集,并通过使用将测试预测器数据标准化μ而且σ

XTest = table2array(adulttest(:,{“年龄”“education_num”“capital_gain”“capital_loss”“hours_per_week”}));标准化xtest = (XTest-mu)./sigma;YTest =成人测试。工资= =“< = 50 k”

火车模型

训练二叉支持向量机分类模型。

Mdl = fitcsvm(standarzedx_sampled,Y_sampled,“重量”w_sampled,“KernelFunction”“高斯”);

Mdl是一个ClassificationSVM模型。

计算训练数据集和测试数据集的分类误差。

损失(Mdl standardizedX_sampled Y_sampled)
Ans = 0.1663
损失(Mdl standardizedXTest、欧美)
Ans = 0.1905

SVM分类器错误分类了大约17%的训练数据和19%的测试数据。

保存模型

将SVM分类模型保存到文件中myMdl.mat通过使用saveLearnerForCoder

saveLearnerForCoder (Mdl“myMdl”);

定义定点数据类型

使用generateLearnerDataTypeFcn生成一个函数,该函数定义预测支持向量机模型所需变量的定点数据类型。使用所有可用的预测器数据来获得定点数据类型的实际范围。

generateLearnerDataTypeFcn (“myMdl”, (standardizedX;standardizedXTest])

generateLearnerDataTypeFcn生成myMdl_datatype函数。显示的内容myMdl_datatype.m通过使用类型函数。

类型myMdl_datatype.m
function T = myMdl_datatype(dt) % myMdl_datatype为定点代码生成定义数据类型% % T = myMdl_datatype(dt)返回数据类型结构T,它为生成用于机器学习模型预测的定点C/ c++代码%所需的变量定义%数据类型。T的每个字段包含fi返回的%定点对象。输入参数dt指定定点对象的% DataType属性。指定dt为'Fixed'(默认)%用于生成定点代码,或指定dt为'Double'以模拟%定点代码的浮点行为。使用输出结构T作为入口点函数的输入参数和入口点函数中loadLearnerForCoder的第二个输入参数。有关更多信息,请参阅loadLearnerForCoder。%文件:myMdl_datatype。m % Statistics and Machine Learning Toolbox Version 12.5 (Release R2023a) %由MATLAB生成,03-Mar-2023 10:47:22 if nargin < 1 dt = 'Fixed';end %设置定点数学设置fm = fimath(' round method ','Floor',…‘OverflowAction’,‘包装’,…… '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

myMdl_datatype函数使用默认单词长度(16),并根据每个变量的默认单词长度(16)和安全裕度(10%)提出避免溢出的最大分数长度。

创建一个结构T通过使用定义定点数据类型myMdl_datatype

T = myMdl_datatype(“固定”
T =带字段的结构:XDataType: [0x0嵌入式。fi] ScoreDataType: [0x0 embedded.fi] InnerProductDataType: [0x0 embedded.fi]

结构T控件所需的命名变量和内部变量的字段预测函数。每个字段包含一个定点对象,由返回fi(定点设计师).例如,显示预测器数据的定点数据类型属性。

T.XDataType
ans = [] DataTypeMode: Fixed-point: binary point scaling signdness: Signed WordLength: 16 FractionLength: 11 RoundingMethod: Floor OverflowAction: Wrap ProductMode: FullPrecision MaxProductWordLength: 128 SumMode: FullPrecision MaxSumWordLength: 128

如果使用非默认的分数转换函数,例如doublelogit分对数,或symmetriclogit-对于训练过的分类器,可以更新结构T包含一个近似于分数转换函数的查找表。有关示例,请参见使用查找表近似分数转换

有关生成的函数和结构的详细信息,请参见数据类型

定义入口点函数

定义名为myFixedPointPredict它的作用如下:

  • 接受预测数据X和定点数据类型结构T

  • 使用两者加载训练好的SVM分类模型的定点版本loadLearnerForCoder结构T。

  • 使用加载的模型预测标签和分数。

函数[label,score] = myFixedPointPredict(X,T)% # codegenMdl = loadLearnerForCoder(“myMdl”“数据类型”T);[label,score] = predict(Mdl,X);结束

注意:如果单击位于本示例右上方部分的按钮并在MATLAB®中打开示例,则MATLAB将打开示例文件夹。此文件夹包括入口点函数文件。

(可选)优化定点数据类型

通过使用优化定点数据类型buildInstrumentedMex而且showInstrumentationResults.记录所有命名变量和内部变量的最小值和最大值,以便使用buildInstrumentedMex.使用查看检测结果showInstrumentationResults;然后,根据结果调优变量的定点数据类型属性。

指定入口点函数的输入参数类型

的输入参数类型myFixedPointPredict使用2 × 1单元格数组。

ARGS = cell(2,1);

第一个输入参数是预测器数据。的XDataType结构场T指定预测器数据的定点数据类型。转换X中指定的类型T.XDataType通过使用(定点设计师)函数。

X_fx = cast(standarzedx,“喜欢”, T.XDataType);

测试数据集与训练数据集的大小不同。指定ARGS {1}通过使用coder.typeof(MATLAB编码器)这样,MEX函数就可以接受可变大小的输入。

ARGS{1} = code .typeof(X_fx,size(standarzedx),[1,0]);

第二个输入参数是结构T,它必须是一个编译时常数。使用编码器。常数(MATLAB编码器)指定T作为代码生成期间的常量。

ARGS{2} = code . constant (T);

创建仪表MEX功能

通过使用创建一个仪表MEX函数buildInstrumentedMex(定点设计师)

  • 方法指定入口点函数的输入参数类型arg游戏选择。

  • 指定MEX函数名- o选择。

  • 方法计算直方图柱状图选择。

  • 方法允许完整的代码生成支持万博1manbetx编码器选择。

buildInstrumentedMexmyFixedPointPredictarg游戏arg游戏- omyFixedPointPredict_instrumented柱状图编码器
代码生成成功。

测试仪表MEX功能

运行instrumented MEX函数记录仪器检测结果。

[labels_fx1,scores_fx1] = myFixedPointPredict_instrumented(X_fx,T);

您可以多次运行仪表MEX函数,以记录来自各种测试数据集的结果。使用standardizedXTest

Xtest_fx = cast(standarzedxtest,“喜欢”, T.XDataType);[labels_fx1_test,scores_fx1_test] = myFixedPointPredict_instrumented(Xtest_fx,T);

查看仪表MEX功能的结果

调用showInstrumentationResults(定点设计师)打开包含检测结果的报告。查看模拟的最小值和最大值、建议的分数长度、当前范围的百分比和整数状态。

showInstrumentationResults (“myFixedPointPredict_instrumented”

中提出的字长和分数长度X和里面的一样吗XDataType在结构上T

单击,查看变量的柱状图变量选项卡。

该窗口包含直方图、关于潜在溢出和下溢出的信息以及变量的数据类型。

使用清除结果clearInstrumentationResults(定点设计师)

clearInstrumentationResults (“myFixedPointPredict_instrumented”

验证仪表MEX功能

比较下面的输出预测而且myFixedPointPredict_instrumented

[labels,scores] = predict(Mdl, standarzedx);Verify_labels1 = isequal(标签,labels_fx1)
verify_labels1 =逻辑0

isequal如果返回逻辑1 (true)标签而且labels_fx1是相等的。如果标签不相等,计算两者之间标签不匹配的百分比标签而且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(: 1)分数(:1))。/分数(:1)))
Diff_scores1 = 54.6741

调优定点数据类型

如果记录的结果显示溢出或下溢,或者希望提高生成代码的精度,则可以调优定点数据类型。类来修改定点数据类型myMdl_datatype函数并创建一个新结构,然后使用新结构生成代码。要更新myMdl_datatype函数时,可以手动修改函数文件中的定点数据类型(myMdl_datatype.m).或者,您可以使用generateLearnerDataTypeFcn并指定更长的单词长度,如本例所示。详情请参见提示

生成一个新的数据类型函数。指定单词长度32和名称myMdl_datatype2对于生成的函数。

generateLearnerDataTypeFcn (“myMdl”, (standardizedX;standardizedXTest),“字”32岁的“OutputFunctionName”“myMdl_datatype2”

显示的内容myMdl_datatype2.m

类型myMdl_datatype2.m
function T = myMdl_datatype2(dt) % myMdl_datatype2定义用于定点代码生成的数据类型% % T = myMdl_datatype2(dt)返回数据类型结构T,它为生成用于机器学习模型预测的定点C/ c++代码%所需的变量定义%数据类型。T的每个字段包含fi返回的%定点对象。输入参数dt指定定点对象的% DataType属性。指定dt为'Fixed'(默认)%用于生成定点代码,或指定dt为'Double'以模拟%定点代码的浮点行为。使用输出结构T作为入口点函数的输入参数和入口点函数中loadLearnerForCoder的第二个输入参数。有关更多信息,请参阅loadLearnerForCoder。%文件:myMdl_datatype2。m % Statistics and Machine Learning Toolbox Version 12.5 (Release R2023a) %由MATLAB生成,03-Mar-2023 10:48:40 if nargin < 1 dt = 'Fixed';end %设置定点数学设置fm = fimath(' round method ','Floor',…‘OverflowAction’,‘包装’,…… '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(“固定”
T2 =带字段的结构:XDataType: [0x0嵌入式。fi] ScoreDataType: [0x0 embedded.fi] InnerProductDataType: [0x0 embedded.fi]

创建一个新的仪表MEX函数,记录结果,并通过使用查看结果buildInstrumentedMex而且showInstrumentationResults

X_fx2 = cast(standarzedx,“喜欢”, T2.XDataType);buildInstrumentedMexmyFixedPointPredictarg游戏{X_fx2, coder.Constant (T2)}- omyFixedPointPredict_instrumented2柱状图编码器
代码生成成功。
[labels_fx2,scores_fx2] = myFixedPointPredict_instrumented2(X_fx2,T2);showInstrumentationResults (“myFixedPointPredict_instrumented2”

检查仪器报告,然后清除结果。

clearInstrumentationResults (“myFixedPointPredict_instrumented2”

验证myFixedPointPredict_instrumented2

Verify_labels2 = isequal(标签,labels_fx2)
verify_labels2 =逻辑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(: 1)分数(:1))。/分数(:1)))
Diff_scores2 = 2.2859

不匹配标签的百分比diff_labels2以及分数值的相对差异diff_scores2比之前使用默认字长(16)生成的MEX函数的值要小。

有关通过测试MATLAB®代码优化定点数据类型的更多详细信息,请参阅参考页面buildInstrumentedMex(定点设计师)showInstrumentationResults(定点设计师),clearInstrumentationResults(定点设计师),以及例子使用最小/最大检测设置数据类型(定点设计师)

生成代码

生成入口点函数的代码codegen.不是为预测器数据集指定变量大小的输入,而是通过使用指定固定大小的输入coder.typeof.如果您知道传递给生成代码的预测器数据集的大小,那么为固定大小的输入生成代码对于代码的简单性更可取。

codegenmyFixedPointPredictarg游戏{coder.typeof (X_fx2 [1,5], [0]), coder.Constant (T2)}
代码生成成功。

codegen生成MEX函数myFixedPointPredict_mex使用依赖于平台的扩展。

验证生成的代码

您可以验证myFixedPointPredict_mex功能,以相同的方式验证仪表的MEX功能。看到验证仪表MEX功能部分的详细信息。

[labels_sampled,scores_sampled] = predict(Mdl, standarzedx_sampled);n = size(standarzedx_sampling,1);Labels_fx = true(n,1);Scores_fx = 0 (n,2);i = 1: n [labels_fx(我),scores_fx(我,:)]= myFixedPointPredict_mex (X_fx2 (idx(我):),T2);结束Verify_labels = isequal(labels_sampled,labels_fx)
verify_labels =逻辑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.0644

内存使用

一个好的做法是在训练模型之前手动标准化预测器数据。如果你使用“标准化”而不是名称-值对参数,则生成的定点代码包括标准化操作,这可能导致精度损失和内存使用增加。

如果生成静态库,则可以使用代码生成报告来查找生成代码的内存使用情况。指定配置:自由方法生成静态库,并使用报告选项以生成代码生成报告。

codegenmyFixedPointPredictarg游戏{coder.typeof (X_fx2 [1,5], [0]), coder.Constant (T2)}- omyFixedPointPredict_lib配置:自由报告

总结页签的代码生成报告,单击代码度量.函数信息部分显示了累积的堆栈大小。

找出训练过的模型的内存使用情况“标准化”,“真正的”,您可以运行以下代码。

Mdl = fitcsvm(X_sampled,Y_sampled,“重量”w_sampled,“KernelFunction”“高斯”“标准化”,真正的);saveLearnerForCoder (Mdl“myMdl”);generateLearnerDataTypeFcn (“myMdl”[X;XTest),“字”32岁的“OutputFunctionName”“myMdl_standardize_datatype”T3 = mymdl_standarze_datatype (“固定”);X_fx3 = cast(x_sampling,“喜欢”, T3.XDataType);codegenmyFixedPointPredictarg游戏{coder.typeof (X_fx3 [1,5], [0]), coder.Constant (T3)}- omyFixedPointPredict_standardize_lib配置:自由报告

另请参阅

||(定点设计师)|(定点设计师)|(定点设计师)|(MATLAB编码器)|(定点设计师)||(定点设计师)

相关的话题