用于预测SVM的固定点代码生成

此示例显示如何为支持向量机(SVM)模型的预测生成定点C / C ++代码。万博1manbetx与通用C / C ++代码生成工作流相比,固定点代码生成需要一个附加步骤,该步骤定义预测所需的变量的定点数据类型。通过使用创建固定点数据类型结构generateLearnerDataTypeFcn,并将该结构用作的输入参数loadlearnerforcoder.在入口点函数中。您还可以在生成代码之前优化定点数据类型。

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

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

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

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

  4. 定义通过使用两者加载模型的入口点函数loadlearnerforcoder.和结构,然后拨打电话预测函数。

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

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

  7. 验证生成的代码。

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

  1. 通过使用记录变量的最小值和最大值以进行预测buildinstrumentedmex.

  2. 使用showinstumastation.cresults..然后,调整固定点数据类型(如有必要)以防止溢出和下溢,并提高定点代码的精度。

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

数据进行预处理

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

负载census1994

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

TBL = AdultData(:,{'年龄''教育_num''资本收益''capital_loss'“hours_per_week”});

打印表格的摘要。

总结(台)
变量:年龄:32561x1双重值:min 17中位数37 max 90教育:32561x1双重值:min 1中位数10 max 16 capital_gain:32561x1双重值:min 0中位0 max 99999 capical_loss:32561x1双值:min 0中位0 max 4356HOUDE_PER_WEEK:32561x1双倍值:MIN 1中位数40 MAX 99

变量的尺度不一致。在这种情况下,您可以使用标准化数据来培训模型来指定标准化的数据“标准化”名称 - 值对参数fitcsvm..但是,将标准化的操作添加到固定点代码可以减少精度并提高内存使用。相反,您可以手动标准化数据集,如本示例所示。该示例还介绍了如何在最后检查内存使用。

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

x = table2Array(TBL);Y = AdultData.Salary =='<= 50k';

定义观察权重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,'骨箱''高斯'“标准化”,真的);mu = tempmdl.mu;sigma = tempmdl.sigma;

如果你不使用'成本''事先的', 要么“重量”用于培训的名称值对参数,然后您可以使用使用的均值和标准偏差值zscore函数。

[standardizedX_sampled、μ、σ]= zscore (X_sampled);

通过使用标准化预测数据Sigma.

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

您可以使用测试数据集来验证经过训练的模型,并测试仪器化的MEX函数。使用指定测试数据集并标准化测试预测器数据Sigma.

xtest = table2array(AdutherTest(:,{'年龄''教育_num''资本收益''capital_loss'“hours_per_week”}));标准化xtest =(xtest-mu)./ sigma;ytest = Aducltiest.Salary =='<= 50k';

火车模型

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

mdl = fitcsvm(标准化x_sampled,y_sampled,“重量”,w_sampled,'骨箱''高斯');

MDL.是一个分类VM.模型。

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

损失(MDL,标准化x_sampled,y_sampled)
ans = 0.1663
损失(MDL,标准化标准,ytest)
ans = 0.1905

支持向量机分类器误分类了大约17%的训练数据和19%的测试数据。

保存模型

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

SavelAlnerForCoder(MDL,'mymdl');

定义定点数据类型

使用generateLearnerDataTypeFcn生成定义预测SVM模型所需的变量的定点数据类型的函数。使用所有可用的预测数据来获取固定点数据类型的真实范围。

generatelearnerdatatypefcn('mymdl',[标准化x;标准化标准])

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

类型myMdl_datatype.m
函数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 11.7 (Release R2020a) % Generated by MATLAB, 29-Feb-2020 02:15:40 if nargin < 1 dt = 'Fixed';END%SET定点数学设置FM = FIMATH('roundingMethod','floor',...'overflowation','wrap',...'productmode','fullprecision',...'maxproductwordlength',128,...'summode','fourprecision',...'maxsumwordlength',128);%预估数据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(“固定”
T =结构体字段:XDataType: [0 x0嵌入。FI.] ScoreDataType: [0x0 embedded.fi] InnerProductDataType: [0x0 embedded.fi]

结构T.方法所需的已命名变量和内部变量的字段预测函数。每个字段都包含一个固定点对象,返回FI..例如,显示预测器数据的固定点数据类型属性。

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

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

定义入口点函数

定义一个入口点函数名为myFixedPointPredict它的作用如下:

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

  • 加载一个定点版本的训练支持向量机分类模型使用两者loadlearnerforcoder.和结构T.

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

功能[标签,得分] = myfixedpointpredict(x,t)%#codegen.mdl = loadlearnerforcoder('mymdl''数据类型',t);[标签,得分] =预测(MDL,x);结尾

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

使用以下方法优化定点数据类型buildinstrumentedmex.showinstumastation.cresults..使用方法记录所有命名变量和内部变量的最小值和最大值buildinstrumentedmex..使用showinstumastation.cresults.;然后,根据结果,调整变量的定点数据类型属性。

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

指定输入参数类型myFixedPointPredict使用2 × 1单元阵列。

args = cell(2,1);

第一个输入参数是预测器数据。这xdatatype.结构场T.指定预测器数据的定点数据类型。转换X到指定的类型T.XDataType通过使用函数。

X_fx =投(standardizedX,“喜欢”,t.xdatatype);

测试数据集与训练数据集的大小不相同。指定args {1}通过使用coder.typeof因此MEX功能可以采用可变大小的输入。

args {1} = coder.typeof(x_fx,size(标准化x),[1,0]);

第二个输入参数是结构T.,这必须是编译时间常数。使用编码器。常数指定T.在代码生成期间作为常量。

args {2} =编码器.Constant(t);

Create Instrumented MEX函数

使用buildinstrumentedmex.

  • 属性指定入口点函数的输入参数类型- args.选项。

  • 通过使用使用的MEX函数名称-O选项。

  • 计算直方图使用- 犹太图选项。

  • 支持完整的代码生成万博1manbetx- 探讨选项。

buildinstrumentedmex.myFixedPointPredict-  args.args.-Omyfixedpointpredict_instumented.- 犹太图- 探讨

测试仪表MEX功能

运行仪表MEX功能,记录仪表结果。

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

可以多次运行检测到的MEX函数,以记录来自各种测试数据集的结果。使用以下命令运行检测到的MEX函数standardizedXTest

xtest_fx = cast(标准化名称,“喜欢”,t.xdatatype);[labels_fx1_test,scores_fx1_test] = myfixedpointpredict_instrumented(xtest_fx,t);

查看仪器MEX功能的结果

称呼showinstumastation.cresults.打开包含测量结果的报告。查看模拟的最小值和最大值,建议的分数长度,当前范围的百分比,和整数状态。

showinstrumentationresults(“myFixedPointPredict_instrumented”

所提出的单词长度和分数长度X与那些相同xdatatype.在结构中T.

通过单击查看变量的直方图变量选项卡。

该窗口包含直方图和带有变量信息的对话框面板。有关此窗口的信息,请参阅NumericTypeScope参考页面。

通过使用清除结果clearInstrumentationResults

clearInstrumentationResults (“myFixedPointPredict_instrumented”

验证仪表MEX功能

比较输出预测myfixedpointpredict_instumented.

[标签,分数] =预测(MDL,标准化x);验证_labels1 = isequal(标签,标签_fx1)
验证_labels1 =逻辑0.

是平等的如果返回逻辑1(true)如果标签labels_fx1.是平等的。如果标签不等于,则可以根据以下计算错误分类标签的百分比。

diff_labels1 =总和(比较字符串(字符串(labels_fx1),字符串(标签))= = 0)/长度(labels_fx1) * 100
diff_labels1 = 0.1228

找出分数输出之间的最大相对差异。

diff_scores1 = max(abs((scors_fx1.double(:,1)-scores(:,1))./ scores(:1))))
diff_scores1 = 74.2445

调谐定点数据类型

如果录制的结果显示溢出或下溢,或者您想提高生成的代码的精度,则可以调整固定点数据类型。通过更新来修改固定点数据类型mymdl_datatype.函数并创建新结构,然后使用新结构生成代码。更新mymdl_datatype.功能,您可以手动修改函数文件中的固定点数据类型(myMdl_datatype.m)。或者,您可以通过使用来生成功能generateLearnerDataTypeFcn并指定更长的单词长度,如本示例所示。有关更多详细信息,请参阅提示

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

generatelearnerdatatypefcn('mymdl',[标准化x;标准化标准,'wordlength',32,“OutputFunctionName”'mymdl_datatype2'

显示mymdl_datatype2.m.

类型mymdl_datatype2.m.
函数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%统计和机器学习工具箱版本11.7(发布R2020A)%由Matlab生成,29-Feb-2020 02:16:50如果nargin <1 dt ='固定';END%SET定点数学设置FM = FIMATH('roundingMethod','floor',...'overflowation','wrap',...'productmode','fullprecision',...'maxproductwordlength',128,...'summode','fourprecision',...'maxsumwordlength',128);预测器数据的%数据类型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: [0 x0嵌入。FI.] ScoreDataType: [0x0 embedded.fi] InnerProductDataType: [0x0 embedded.fi]

创建一个新的测量MEX函数,记录结果,并使用buildinstrumentedmex.showinstumastation.cresults.

x_fx2 =施放(标准化x,“喜欢”,t2.xdatatype);buildinstrumentedmex.myFixedPointPredict-  args.{X_fx2, coder.Constant (T2)}-Omyfixedpointpredict_instrumented2- 犹太图- 探讨[labels_fx2, scores_fx2] = myFixedPointPredict_instrumented2 (X_fx2, T2);showinstrumentationresults('myfixedpointpredict_instrumented2'

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

clearInstrumentationResults ('myfixedpointpredict_instrumented2'

核实myfixedpointpredict_instrumented2

验证_labels2 = isequal(标签,labels_fx2)
验证_labels2 =逻辑0.
diff_labels2 =总和(比较字符串(字符串(labels_fx2),字符串(标签))= = 0)/长度(labels_fx2) * 100
diff_labels2 = 0.0031.
diff_scores2 = max (abs (scores_fx2.double(: 1)分数(:1))。/分数(:1)))
diff_scores2 = 1.7332

错误分类标签的百分比diff_labels2分数值的相对差异diff_scores2小于使用默认字长(16)生成的前一个MEX函数的值。

有关通过仪器仪表仪器策略优化固定点数据类型的详细信息,请参阅参考页面buildinstrumentedmex.showinstumastation.cresults., 和clearInstrumentationResults和这个例子使用min / max仪器设置数据类型(定点设计师)。

生成代码

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

Codegen.myFixedPointPredict-  args.{coder.typeof(x_fx2,[1,5],[0,0]),编码器.Constant(T2)}

Codegen.生成MEX函数myfixedpointpredict_mex.具有平台依赖的扩展。

验证生成的代码

你可以验证myfixedpointpredict_mex.以与您验证所录制的MEX功能的方式相同。看看验证仪表MEX功能部分细节。

[Labels_Sampled,scores_sampled] =预测(MDL,标准化x_sampled);n =大小(标准化x_sampled,1);labels_fx = true(n,1);scors_fx = zeros(n,2);为了i = 1:n [labels_fx(i),scors_fx(i,:)] = myfixedpointpredict_mex(x_fx2(idx(i),:),t2);结尾验证_labels = isequal(Labels_sampled,labels_fx)
verify_labels =逻辑1
diff_labels =总和(比较字符串(字符串(labels_fx),字符串(labels_sampled)) = = 0) /长度(labels_fx) * 100
diff_labels = 0.
diff_scores = max(abs((scors_fx(:,1)-scores_sampled(:,1))./ scors_sampled(:,1))))
diff_scores = 0.0654

内存使用

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

如果生成静态库,则可以使用代码生成报告找到生成的代码的内存使用。指定配置:自由要生成静态库,请使用报告选择代码生成报告的选项。

Codegen.myFixedPointPredict-  args.{coder.typeof(x_fx2,[1,5],[0,0]),编码器.Constant(T2)}-OmyFixedPointPredict_lib配置:自由报告

在这一点概括代码生成报告的选项卡,单击代码度量.函数信息部分显示了累积的堆栈大小。

找到模型培训的内存使用“标准化”,“真正的”,您可以运行以下代码。

mdl = fitcsvm(x_sampled,y_sampled,“重量”,w_sampled,'骨箱''高斯'“标准化”,真的);SavelAlnerForCoder(MDL,'mymdl');generatelearnerdatatypefcn('mymdl',[X;xtest],'wordlength',32,“OutputFunctionName”“myMdl_standardize_datatype”)t3 = mymdl_standardize_datatype(“固定”);x_fx3 = cast(x_sampled,“喜欢”,t3.xdatatype);Codegen.myFixedPointPredict-  args.{coder.typeof(x_fx3,[1,5],[0,0]),编码器.Constant(T3)}-OmyFixedPointPredict_standardize_lib配置:自由报告

也可以看看

||||||||

相关话题