主要内容

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

这个例子展示了如何为支持向量机(SVM)模型的预测生成定点C/ c++代码。与一般的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

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

台= adultdata (:, {“年龄”“education_num”“capital_gain”“capital_loss”“hours_per_week”});

打印表格的摘要。

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

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

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

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

定义观察权重w

w = adultdata.fnlwgt;

经过训练的模型的内存使用量随着模型中支持向量数量的增加而增加。方法来减少支持向量的数量,可以在训练时增加框约束“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”“高斯”“标准化”,真正的);μ= tempMdl.Mu;σ= tempMdl.Sigma;

如果不使用“成本”“之前”,或“重量”参数进行训练,然后可以通过使用zscore函数。

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

对预测器数据进行标准化μ而且σ

standardizedX = (xμ)。/σ;standardizedX_sampled = standardizedX (idx:);

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

XTest = table2array(成人(:{“年龄”“education_num”“capital_gain”“capital_loss”“hours_per_week”}));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

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

保存模型

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

saveLearnerForCoder (Mdl“myMdl”);

定义定点数据类型

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

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

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 12.4 (Release R2022b) %由MATLAB生成,如果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,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 sign度:Signed WordLength: 16 FractionLength: 11 RoundingMethod: Floor OverflowAction: Wrap ProductMode: FullPrecision MaxProductWordLength: 128 SumMode: FullPrecision MaxSumWordLength: 128

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

定义入口点函数

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

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

  • 使用两者加载经过训练的SVM分类模型的定点版本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(定点设计师)

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

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

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

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

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

测试仪表MEX功能

运行被检测的MEX函数记录检测结果。

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

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

Xtest_fx =投(standardizedXTest,“喜欢”, 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

(标签、分数)=预测(Mdl standardizedX);labels_fx1 verify_labels1 = isequal(标签)
verify_labels1 =逻辑0

isequal返回逻辑1 (true)标签而且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 = 49.8264

调优定点数据类型

如果记录的结果显示溢出或下溢,或者希望提高生成代码的精度,则可以调优定点数据类型。修改定点数据类型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
函数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.4 (Release R2022b) %由MATLAB生成,如果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_datatype2函数指定字长度32,并提出避免溢出的最大分数长度。

创建一个结构T2它通过使用定义定点数据类型myMdl_datatype2

T2 = myMdl_datatype2 (“固定”
T2 =结构体字段:XDataType: [0 x0嵌入。fi] ScoreDataType: [0x0 embedded.fi] InnerProductDataType: [0x0 embedded.fi]

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

X_fx2 =投(standardizedX,“喜欢”, 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

labels_fx2 verify_labels2 = isequal(标签)
verify_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 = 2.5820

标签分类错误的百分比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] =预测(Mdl standardizedX_sampled);n =大小(standardizedX_sampled, 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 =总和(比较字符串(字符串(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.0635

内存使用

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

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

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_标准化数据类型(“固定”);X_fx3 =投(X_sampled,“喜欢”, T3.XDataType);codegenmyFixedPointPredictarg游戏{coder.typeof (X_fx3 [1,5], [0]), coder.Constant (T3)}- omyFixedPointPredict_standardize_lib配置:自由报告

另请参阅

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

相关的话题

Baidu
map