Code Generation Workflow Using MATLAB Coder App

This example shows how to generate code for Statistics and Machine Learning Toolbox™ functions involving model objects by using the MATLAB® Coder™ app.

Certain classification and regression model objects have a predict function that supports code generation. Prediction requires a trained classification or regression model object, but the -args option of codegen does not accept these objects. Therefore, you must adjust your workflow slightly to accommodate code generation by using the saveCompactModel and loadCompactModel functions. Save a trained model by using the saveCompactModel function, and load the model by using the loadCompactModel function in the entry-point function. The entry-point function, also known as the top-level or primary function, is a function you define for code generation.

In this example, you train a classification ensemble model using k-nearest-neighbor weak learners. After training and saving the classification model, define the entry-point function and write a script to test the function. Then, use the MATLAB Coder app to generate code.

Train Classification Model

Load the ionosphere data set. This data set has 34 predictors and 351 binary responses for radar returns, either bad ('b') or good ('g').

load ionosphere

Train a classification ensemble model with k-nearest-neighbor weak learners by using the random subspace method. For details of classifications that use a random subspace ensemble, see Random Subspace Classification.

learner = templateKNN('NumNeighbors',2);
Mdl = fitcensemble(X,Y,'Method','Subspace','NPredToSample',5, ...
    'Learners',learner,'NumLearningCycles',13);

Save Model Using saveCompactModel

Save the trained ensemble model to a file named knnEnsemble.mat in your current folder.

saveCompactModel(Mdl,'knnEnsemble')

Define Entry-Point Function

In a new file in your current folder, define an entry-point function named myknnEnsemblePredict that does the following:

  • Accept input data (X), the file name of the saved model (fileName), and valid name-value pair arguments of the predict function (varargin).

  • Load a trained ensemble model by using loadCompactModel.

  • Predict labels and corresponding scores from the loaded model.

type myknnEnsemblePredict.m % Display the contents of myknnEnsemblePredict.m file. 
function [label,score] = myknnEnsemblePredict(X,fileName,varargin) %#codegen
CompactMdl = loadCompactModel(fileName);
[label,score] = predict(CompactMdl,X,varargin{:});
end

Note: If you click the Open Live Script button (located in the upper-right section of this page) and open this example in MATLAB®, then MATLAB® opens the example folder. This folder includes the entry-point function file (myknnEnsemblePredict.m) and the test file (test_myknnEnsemblePredict.m, described later on).

Set Up C Compiler

To generate C code, you must have access to a C compiler, and the compiler must be configured properly. MATLAB Coder locates and uses a supported, installed compiler. You can use mex -setup to view and change the default compiler. For more details, see Set Up Your C Compiler (MATLAB Coder).

mex -setup
MEX configured to use 'gcc' for C language compilation.
Warning: The MATLAB C and Fortran API has changed to support MATLAB
	 variables with more than 2^32-1 elements. You will be required
	 to update your code to utilize the new API.
	 You can find more information about this at:
	 https://www.mathworks.com/help/matlab/matlab_external/upgrading-mex-files-to-use-64-bit-api.html.

To choose a different language, execute one from the following:
 mex -setup C++ 
 mex -setup FORTRAN

Create Test File

Write a test script that calls the myknnEnsemblePredict function. In the test script, specify the input arguments and name-value pair arguments that you use in the generated code. You use this test script to define input types automatically when generating code using the MATLAB Coder app.

In this example, create the test_myknnEnsemblePredict.m file in your current folder, as shown.

type test_myknnEnsemblePredict.m % Display the contents of test_myknnEnsemblePredict.m file. 
%% Load Sample data
load ionosphere

%% Test myknnEnsemblePredict
[label,score] = myknnEnsemblePredict(X,'knnEnsemble','Learners',1:13);

For details, see Automatically Define Input Types by Using the App (MATLAB Coder).

Generate Code Using MATLAB Coder App

The MATLAB Coder app generates C or C++ code from MATLAB® code. The workflow-based user interface steps you through the code generation process. The following steps describe a brief workflow of the MATLAB Code App. For more details, see MATLAB Coder and C Code Generation Using the MATLAB Coder App (MATLAB Coder).

1. Open the MATLAB Code App and Select the Entry-Point Function File.

On the Apps tab, in the Apps section, click the Show more arrow to open the apps gallery. Under Code Generation, click MATLAB Coder. The app opens the Select Source Files page. Enter or select the name of the entry-point function, myknnEnsemblePredict.

Click Next to go to the Define Input Types page.

2. Define Input Types

Because C uses static typing, MATLAB Coder must determine the properties of all variables in the MATLAB files at compile time. Therefore, you need to specify the properties of the entry-point function inputs.

Enter or select the test script test_myknnEnsemblePredict and click Autodefine Input Types.

The MATLAB Coder app recognizes input types of the myknnEnsemblePredict function based on the test script.

Modify the input types:

  • X — The app infers that input X is double(351 x 34). The number of predictors must be fixed to be the same as the number of predictors in the trained model. However, you can have a different number of observations for prediction. If the number of observations is unknown, change double(351 x 34) to double(:351 x 34) or double(:inf x 34). The setting double(:351 x 34) allows the number of observations up to 351, and the setting double(:inf x 34) allows an unbounded number of observations. In this example, specify double(:inf x 34) by clicking 351 and selecting :inf.

  • fileName — Click char, select Define Constant, and type the file name with single quotes, 'knnEnsemble'.

  • varargin{1} — Names in name-value pair arguments must be compile-time constants. Click char, select Define Constant, and type 'Learners'.

  • varargin{2} — To allow user-defined indices up to 13 weak learners in the generated code, change double(1 x 13) to double(1 x :13).

Click Next to go to the Check for Run-Time Issues page. This optional step generates a MEX file, runs the MEX function, and reports issues. Click Next to go to the Generate Code page.

3. Generate C Code

Set Build type to MEX and click Generate. The app generates a MEX function, myknnEnsemblePredict_mex, which you can use to analyze its input and output arguments in MATLAB before deploying the function outside the MATLAB environment. For details on setting a build type, see Configure Build Settings (MATLAB Coder).

Click Next to go to the Finish Workflow page.

4. Review the Finish Workflow Page

The Finish Workflow page indicates that code generation succeeded. This page also provides a project summary and links to generated output.

Generate Code Using Script

You can convert a MATLAB Coder project to the equivalent script of MATLAB commands after you define input types. Then you run the script to generate code. For details, see Convert MATLAB Coder Project to MATLAB Script (MATLAB Coder).

On the MATLAB Coder app toolbar, click the Open action menu button.

Select Convert to script, and then click Save. The app creates the file myknnEnsemblePredict_script.m, which reproduces the project in a configuration object and runs the codegen function.

Display the contents of the file myknnEnsemblePredict_script.m.

type myknnEnsemblePredict_script.m
% MYKNNENSEMBLEPREDICT_SCRIPT   Generate MEX-function myknnEnsemblePredict_mex
%  from myknnEnsemblePredict.
% 
% Script generated from project 'myknnEnsemblePredict.prj' on 17-Nov-2017.
% 
% See also CODER, CODER.CONFIG, CODER.TYPEOF, CODEGEN.

%% Create configuration object of class 'coder.MexCodeConfig'.
cfg = coder.config('mex');
cfg.GenerateReport = true;
cfg.ReportPotentialDifferences = false;

%% Define argument types for entry-point 'myknnEnsemblePredict'.
ARGS = cell(1,1);
ARGS{1} = cell(4,1);
ARGS{1}{1} = coder.typeof(0,[Inf  34],[1 0]);
ARGS{1}{2} = coder.Constant('knnEnsemble');
ARGS{1}{3} = coder.Constant('Learners');
ARGS{1}{4} = coder.typeof(0,[1 13],[0 1]);

%% Invoke MATLAB Coder.
codegen -config cfg myknnEnsemblePredict -args ARGS{1} -nargout 2

Run the script.

myknnEnsemblePredict_script
Code generation successful: To view the report, open('codegen/mex/myknnEnsemblePredict/html/report.mldatx').

Verify Generated Code

Verify that myknnEnsemblePredict and the MEX function return the expected results.

[label1,score1] = predict(Mdl,X,'Learners',1:10);
[label2,score2] = myknnEnsemblePredict(X,'knnEnsemble','Learners',1:10);
[label3,score3] = myknnEnsemblePredict_mex(X,'knnEnsemble','Learners',1:10);
verifyMEX_label = isequal(label1,label2,label3)
verifyMEX_label = logical
   1

verifyMEX_score = isequal(score1,score2,score3)
verifyMEX_score = logical
   1

isequal returns logical 1 (true) if all the inputs are equal.

The score3 output from the MEX function might include round-off differences compared with the output from the predict function. In this case, you can compare score1 and score3, allowing a small tolerance.

find(abs(score1-score3) > 1e-12)
ans =

  0x1 empty double column vector

The comparisons confirm that myknnEnsemblePredict and the MEX function return the expected results.

See Also

| |

Related Topics

Was this topic helpful?