这个例子展示了如何为支持向量机(SVM)模型的预测生成定点C/ c++代码。金宝app与一般的C/ c++代码生成工作流相比,定点代码生成需要一个额外的步骤,定义预测所需的变量的定点数据类型。使用。创建定点数据类型结构generateLearnerDataTypeFcn
,并将该结构用作的输入参数loadLearnerForCoder
在入口点函数中。您还可以在生成代码之前优化定点数据类型。
此流程图显示定点代码生成工作流。
训练支持向量机模型。
使用保存经过训练的模型saveLearnerForCoder
.
通过使用生成的数据类型函数定义预测所需变量的定点数据类型generateLearnerDataTypeFcn
.
定义一个入口点函数,通过使用这两个函数来加载模型loadLearnerForCoder
和结构,然后调用预测
函数。
(可选)优化定点数据类型。
生成定点C/C++代码。
验证生成的代码。
步骤5是提高生成的定点代码性能的可选步骤。为此,重复这两个步骤,直到您对代码性能感到满意:
使用方法记录变量的最小值和最大值,用于预测buildInstrumentedMex
(定点设计师).
使用查看检测结果showInstrumentationResults
(定点设计师).然后,调优定点数据类型(如果必要的话),以防止溢出和下流,并提高定点代码的精度。
在此工作流中,可以使用从生成的数据类型函数定义定点数据类型generateLearnerDataTypeFcn
.将变量的数据类型从算法中分离出来可以使测试更简单。通过使用数据类型函数的输入参数,可以通过编程在浮点和定点之间切换数据类型。此外,这个工作流是兼容的手动定点转换工作流(定点设计师).
加载census1994
数据集。这个数据集由美国人口普查局的人口统计数据组成,用来预测一个人的年收入是否超过5万美元。
负载census1994
考虑一个模型,它根据员工的年龄、工人阶级、教育水平、资本损益和每周工作时间来预测员工的工资类别。提取感兴趣的变量并使用表保存它们。
台= adultdata (:, {“年龄”,“教育数量”,“资本收益”,“capital_loss”,“每周小时数”});
打印表格的摘要。
总结(台)
变量:年龄:32561x1双倍值:最小17中位数37最大90教育人数:32561x1双倍值:最小1中位数10最大16资本收益:32561x1双倍值:最小0中位数0最大9999资本损失:32561x1双倍值:最小0中位数0最大4356小时/周:32561x1双倍值:最小1中位数40最大99
变量的尺度不一致。在这种情况下,可以通过指定“标准化”
的名称-值对参数fitcsvm
.然而,在定点代码中添加标准化操作可能会降低精度并增加内存使用。相反,您可以手动标准化数据集,如本例所示。该示例还描述了如何在最后检查内存使用情况。
定点代码生成不支持表或类别数组。金宝app定义预测数据X
使用数字矩阵,并定义类标签Y
使用逻辑向量。在二进制分类问题中,逻辑向量使用内存的效率最高。
X = table2array(台);Y = adultdata。工资= =“< = 50 k”;
定义观测权值W
.
w = adultdata.fnlwgt;
随着模型中支持向量数量的增加,训练模型的记忆使用也会增加。金宝app为了减少支持向量的数量,可以在训练时通过使用金宝app“BoxConstraint”
命名值对参数或使用次采样的代表性数据集进行训练。请注意,增加框约束会导致更长的训练时间,使用次采样数据集会降低训练模型的准确性。在本例中,您从数据集中随机抽样1000个观察值,并使用次采样数据进行训练.
rng (“默认”)%的再现性[X_sampled,idx]=数据样本(X,1000,“替换”、假);Y_sampled = Y (idx);w_sampled = w (idx);
通过对模型的训练,得到加权平均值和标准差“重量”
和“标准化”
名称-值对参数。
tempMdl = fitcsvm (X_sampled Y_sampled,“重量”w_sampled,“KernelFunction”,“高斯”,“标准化”,真正的);μ= tempMdl.Mu;σ= tempMdl.Sigma;
如果您不使用“成本”
,“之前”
,或“重量”
的名称-值对参数,然后可以通过使用zscore
函数。
[standardizedX_sampled、μ、σ]= zscore (X_sampled);
使用μ
和西格玛
.
standardizedX = (xμ)。/σ;standardizedX_sampled = standardizedX (idx:);
您可以使用测试数据集来验证经过训练的模型,并测试插入指令的MEX函数。指定测试数据集,并使用μ
和西格玛
.
XTest = table2array(成人(:{“年龄”,“教育数量”,“资本收益”,“capital_loss”,“每周小时数”}));standardizedXTest = (XTest-mu)。/σ;欧美=成人。工资= =“< = 50 k”;
训练二值支持向量机分类模型。
Mdl = fitcsvm (standardizedX_sampled Y_sampled,“重量”w_sampled,“KernelFunction”,“高斯”);
Mdl
是一个ClassificationSVM
模型。
计算训练数据集和测试数据集的分类误差。
损失(Mdl standardizedX_sampled Y_sampled)
ans=0.1663
损失(Mdl standardizedXTest、欧美)
ans=0.1905
支持向量机分类器误分类了大约17%的训练数据和19%的测试数据。
将SVM分类模型保存到文件中myMdl.mat
通过使用saveLearnerForCoder
.
saveLearnerForCoder(Mdl,“myMdl”);
使用generateLearnerDataTypeFcn
生成一个函数,定义支持向量机模型预测所需变量的定点数据类型。使用所有可用的预测器数据来获得定点数据类型的真实范围。
generateLearnerDataTypeFcn (“myMdl”,[standardizedX;standardizedXTest])
generateLearnerDataTypeFcn
生成myMdl_数据类型
函数。显示myMdl_数据类型.m
通过使用类型
函数。
类型myMdl_数据类型.m
函数T=myMdl_数据类型(dt)%myMdl_数据类型定义定点代码生成的数据类型%%T=myMdl_数据类型(dt)返回数据类型结构T,该结构为生成用于预测机器学习模型的定点C/C++代码%所需的变量定义%数据类型。T的每个字段都包含fi返回的%定点对象。输入参数dt指定定点对象的%DataType属性。将dt指定为“Fixed”(默认值)%以生成定点代码,或将dt指定为“Double”以模拟定点代码的%浮点行为。%%使用输出结构T作为入口点%函数的输入参数和%entry point函数中loadLearnerForCoder的第二个输入参数。有关更多信息,请参阅loadLearnerForCoder.%文件:myMdl_数据类型.m%统计和机器学习工具箱版本12.2(R2021b版)%由MATLAB生成,2021年9月1日14:32:31,如果nargin<1 dt=‘固定’;结束%Set定点数学设置fm=fimath('RoundingMethod'、'Floor'、…'OverflowAction'、'Wrap'、…'ProductMode'、'FullPrecision'、…'MaxProductWordLength',128、…'SumMode'、'FullPrecision'、…'MaxSumWordLength',128);%预测器数据的数据类型T.XDataType=fi([],真,16,11,fm,'DataType',dt);%输出分数的数据类型T.ScoreDataType=fi([],真,16,14,fm,'DataType',dt);%对于高斯核G(x,sv)=exp(-dist),内部变量%距离平方距离dist=(x-sv)^2的数据类型,%,其中x是观测的预测数据,sv是支持向量T.InnerProductDataType=fi([],真,16,6,fm,'DataType',dt);终止金宝app
注意:如果您点击位于此示例右上角部分的按钮,并在MATLAB®中打开示例,则MATLAB将打开示例文件夹。这个文件夹包括入口点函数文件。
这个myMdl_数据类型
函数使用默认字长(16),并根据每个变量的默认字长(16)和安全裕度(10%)提出最大分数长度以避免溢出。
创建一个结构T
通过使用定义定点数据类型myMdl_数据类型
.
T=myMdl_数据类型(“固定的”)
T=结构体字段:XDataType: [0 x0嵌入。fi] ScoreDataType: [0x0 embedded.fi] InnerProductDataType: [0x0 embedded.fi]
结构T
方法所需的已命名变量和内部变量的字段预测
函数。每个字段包含一个定点对象,由fi
(定点设计师).例如,显示预测器数据的定点数据类型属性。
T.XDataType
ans=[]数据类型模式:固定点:二进制点缩放符号性:符号字长:16分形长度:11舍入方法:楼层溢出操作:换行ProductMode:FullPrecision MaxProductWordLength:128总和模式:FullPrecision MaxSumWordLength:128
有关生成的函数和结构的更多详细信息,请参阅数据类型函数.
定义一个入口点函数名为myFixedPointPredict
它的作用如下:
接受预测数据X
和定点数据类型结构T
.
加载一个定点版本的训练支持向量机分类模型使用两者loadLearnerForCoder
以及结构T。
使用加载的模型预测标签和分数。
函数(标签,分数)= myFixedPointPredict (X, T)% # codegenMdl=loadLearnerForCoder(“myMdl”,“数据类型”T);(标签,分数)=预测(Mdl X);结束
使用以下方法优化定点数据类型buildInstrumentedMex
和showInstrumentationResults
.记录所有命名变量和内部变量的最小值和最大值,以便使用buildInstrumentedMex
.使用查看检测结果showInstrumentationResults
;然后,根据结果调优变量的定点数据类型属性。
指定入口点函数的输入参数类型
的输入参数类型myFixedPointPredict
使用2 × 1单元阵列。
ARGS=单元(2,1);
第一个输入参数是预测器数据XDataType
结构域T
指定预测器数据的定点数据类型。转换X
到中指定的类型T.XDataType
通过使用铸造
(定点设计师)函数。
X_fx =投(standardizedX,“喜欢”, T.XDataType);
测试数据集与训练数据集的大小不相同。指定ARGS{1}
通过使用coder.typeof
(MATLAB编码器)以便MEX函数可以接受大小可变的输入。
ARGS {1} = coder.typeof (X_fx、大小(standardizedX) [1,0]);
第二个输入参数是结构T
,它必须是一个编译时常量。使用编码器。常数
(MATLAB编码器)指定T
作为代码生成期间的常量。
ARGS {2} = coder.Constant (T);
创建插入指令的MEX函数
使用创建插入指令的MEX函数buildInstrumentedMex
(定点设计师).
属性指定入口点函数的输入参数类型-args
选择。
属性指定MEX函数名- o
选择。
使用-直方图
选择。
支持完整的代码生成金宝app编码器
选择。
buildInstrumentedMexmyFixedPointPredict-argsARGS- omyFixedPointPredict\u仪表化-直方图编码器
代码生成成功。
测试仪表MEX功能
运行检测MEX函数以记录检测结果。
[labels_fx1,scores_fx1]=myFixedPointPredict_instrumented(X_fx,T);
可以多次运行插入指令的MEX函数,以记录来自各种测试数据集的结果standardizedXTest
.
Xtest_fx =投(standardizedXTest,“喜欢”, T.XDataType);[labels_fx1_test, scores_fx1_test] = myFixedPointPredict_instrumented (Xtest_fx T);
查看插入指令的MEX函数的结果
调用showInstrumentationResults
(定点设计师)打开包含检测结果的报告。查看模拟最小值和最大值、建议的分数长度、当前范围的百分比以及整数状态。
显示仪器结果(“myFixedPointPredict_instrumented”)
中建议的单词长度和分数长度X
和在?XDataType
在结构中T
.
通过单击查看变量的直方图在变量标签。
该窗口包含直方图和带有变量信息的对话框面板。有关此窗口的信息,请参阅数字打字机
(定点设计师)参考页面。
使用以下命令清除结果:clearInstrumentationResults
(定点设计师).
clearInstrumentationResults (“myFixedPointPredict_instrumented”)
验证插入仪表的MEX功能
比较预测
和myFixedPointPredict\u仪表化
.
[标签,分数]=预测(Mdl,standardizedX);验证标签1=isequal(标签,标签1)
verify_labels1 =必然的0
等质量
返回逻辑1 (true) if标签
和labels_fx1
相等。如果标签不相等,可以按如下方式计算分类错误标签的百分比。
diff_labels1 =总和(比较字符串(字符串(labels_fx1),字符串(标签))= = 0)/长度(labels_fx1) * 100
diff_labels1 = 0.1228
找出分数输出之间相对差异的最大值。
diff_scores1 = max (abs (scores_fx1.double(: 1)分数(:1))。/分数(:1)))
diff_scores1 = 58.6019
调整定点数据类型
如果记录的结果显示溢出或下溢,或者希望提高生成代码的精度,则可以调优定点数据类型。的方法来修改定点数据类型myMdl_数据类型
函数并创建新结构,然后使用新结构生成代码。更新myMdl_数据类型
函数,您可以在函数文件(myMdl_数据类型.m
).或者,您可以使用generateLearnerDataTypeFcn
并指定较长的单词长度,如本例所示。有关详细信息,请参见提示.
生成一个新的数据类型函数。指定单词长度为32和名称myMdl_数据类型2
为生成的函数。
generateLearnerDataTypeFcn (“myMdl”,[standardizedX;standardizedXTest],“字”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 % Statistics and Machine Learning Toolbox Version 12.2 (Release R2021b) % Generated by MATLAB, 01-Sep-2021 14:33:50 if nargin < 1 dt = 'Fixed';fm = fimath('RoundingMethod','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_数据类型2
函数指定字长32,并建议最大分数长度以避免溢出。
创建一个结构T2
通过使用定义定点数据类型myMdl_数据类型2
.
T2=myMdl_数据类型2(“固定的”)
T2=结构体字段:XDataType: [0 x0嵌入。fi] ScoreDataType: [0x0 embedded.fi] InnerProductDataType: [0x0 embedded.fi]
创建一个新的插入指令的MEX函数,记录结果,并使用buildInstrumentedMex
和showInstrumentationResults
.
X_fx2=铸件(标准化X,“喜欢”, T2.XDataType);buildInstrumentedMexmyFixedPointPredict-args{X_fx2,编码器常数(T2)}- omyFixedPointPredict_instrumented2-直方图编码器
代码生成成功。
[labels_fx2,scores_fx2]=myFixedPointPredict_instrumented2(X_fx2,T2);显示仪器结果(“myFixedPointPredict\u instrumented2”)
查看仪器报告,然后清除结果。
clearInstrumentationResults (“myFixedPointPredict\u instrumented2”)
验证myFixedPointPredict_instrumented2
.
验证\u labels2=isequal(标签,标签\u fx2)
verify_labels2 =必然的0
diff_labels2=sum(strcmp(string(labels_fx2),string(labels))=0)/长度(labels_fx2)*100
diff_labels2 = 0.0031
差异分数2=最大值(abs((分数fx2.双(:,1)-分数(:,1))。/分数(:,1)))
diff_scores2 = 2.7971
错误分类标签的百分比diff_labels2
得分值的相对差异差分2
小于使用默认字长(16)生成的上一个MEX函数的值。
有关通过检测MATLAB®代码优化定点数据类型的更多详细信息,请参阅参考页buildInstrumentedMex
(定点设计师),showInstrumentationResults
(定点设计师),clearInstrumentationResults
(定点设计师),以及例子使用Min/Max Instrumentation设置数据类型(定点设计师).
使用为入口点函数生成代码codegen
。使用以下命令指定固定大小的输入,而不是为预测器数据集指定可变大小的输入coder.typeof
. 如果您知道传递给生成代码的预测器数据集的大小,那么为了代码的简单性,最好为固定大小的输入生成代码。
codegenmyFixedPointPredict-args{coder.typeof(X_fx2[1,5],[0,0]),coder.Constant(T2)}
代码生成成功。
codegen
生成MEX函数myFixedPointPredict_mex
与平台相关的扩展。
你可以验证myFixedPointPredict_mex
函数的方法与验证仪表化的MEX函数的方法相同。看到验证插入仪表的MEX功能详情请参阅第节。
[labels_sampled, scores_sampled] =预测(Mdl standardizedX_sampled);n =大小(standardizedX_sampled, 1);labels_fx = true (n, 1);scores_fx = 0 (n, 2);对于i=1:n[labels_fx(i),scores_fx(i,:)]=myFixedPointPredict_mex(X_fx2(idx(i),:),T2);结束验证标签是否相等(标签取样,标签fx)
verify_labels =必然的1.
diff_labels =总和(比较字符串(字符串(labels_fx),字符串(labels_sampled)) = = 0) /长度(labels_fx) * 100
diff_labels = 0
diff_scores = max (abs (scores_fx (: 1) -scores_sampled(: 1))。/ scores_sampled (: 1)))
diff_scores = 0.0642
一个好的做法是在训练模型之前手动标准化预测数据“标准化”
名称-值对参数,然后生成的定点代码包括标准化操作,这可能导致精度损失和内存使用增加。
如果生成静态库,则可以使用代码生成报告查找生成代码的内存使用情况。具体说明-配置:lib
要生成静态库,请使用-报告
选项生成代码生成报告。
codegenmyFixedPointPredict-args{coder.typeof(X_fx2[1,5],[0,0]),coder.Constant(T2)}- omyFixedPointPredict_库-配置:lib-报告
在总结在代码生成报告的选项卡上,单击代码度量.函数信息部分显示累计堆栈大小。
找出训练过的模型的记忆用途“标准化”、“真实”
,您可以运行以下代码。
Mdl = fitcsvm (X_sampled Y_sampled,“重量”w_sampled,“KernelFunction”,“高斯”,“标准化”,对);saveLearnerForCoder(Mdl,“myMdl”);生成学习数据类型FCN(“myMdl”[X;XTest),“字”32岁的“OutputFunctionName”,“myMdl\u标准化\u数据类型”)T3=myMdl\u标准化\u数据类型(“固定的”); X_fx3=铸件(X_取样,“喜欢”, T3.XDataType);codegenmyFixedPointPredict-args{coder.typeof (X_fx3 [1,5], [0]), coder.Constant (T3)}- omyFixedPointPredict\u Standardized\u lib-配置:lib-报告
loadLearnerForCoder
|saveLearnerForCoder
|buildInstrumentedMex
(定点设计师)|showInstrumentationResults
(定点设计师)|clearInstrumentationResults
(定点设计师)|codegen
(MATLAB编码器)|铸造
(定点设计师)|generateLearnerDataTypeFcn
|fi
(定点设计师)