Generate Generic C Code Using The Stateful Predict Block in Simulink
This example shows how to generate generic C code in Simulink® using the Stateful Predict (Deep Learning Toolbox) block and the SIL workflow. You will use a long short-term memory (LSTM) network trained on the Japanese Vowels data set to identify the speaker for a given input sequence. For more information, see Predict and Update Network State in Simulink (Deep Learning Toolbox).
Load Test Data
Load the Japanese Vowels test data. XTest
is a cell array containing 370 sequences of dimension 12 and varying sequence length.
load('JapaneseVowelsTestData.mat')
X = single(XTest{94});
Simulink Model for Predicting Responses
The Simulink model for predicting responses contains a Stateful
Predict
block to predict the scores and a From
Workspace
block to load the input data sequence over the time steps. Create a timetable modelInput
with time-stamped rows to load using the From
Workspace
block.
To reset the state of recurrent neural network to its initial state during simulation, place the Stateful
Predict
block inside a Resettable
Subsystem
and use the Reset
control signal as trigger.
modelInput = timetable(X','TimeStep',seconds(0.2)); modelName = 'StatefulPredictBlockExample'; modelHandle = load_system(modelName); open_system(modelHandle);
Configure Model for Simulation
Set the network file path to the LSTM network 'JapaneseVowelsDlnet.mat'
, which was trained on the Japanese Vowels data set as described in [1] and [2]. The network expects the sequences representing the vowels as input and produces the classification scores for the nine different speakers as output.
The first dimension of the sequences in XTest
is the channel dimension 'C'
, representing the vowels, whereas the second dimension represents the sequence length 'T'
. Therefore, you must set the input data formats to 'CT'
.
statefulPredictBlockHandle = getSimulinkBlockHandle([modelName '/Stateful Predict']); set_param(statefulPredictBlockHandle, 'Network', 'Network from MAT-file'); set_param(statefulPredictBlockHandle, 'NetworkFilePath', 'JapaneseVowelsDlnet.mat'); set_param(statefulPredictBlockHandle, 'InputDataFormats', "{'input', 'CT'}");
The function getProdHWDeviceType
returns the production hardware device type based on the host computer specifications. You can edit the function below if you are running this example on a computer with different specifications.
function prodHWDeviceType = getProdHWDeviceType() if ismac prodHWDeviceType = 'Intel->x86-64 (MAC OS X)'; elseif isunix prodHWDeviceType = 'Intel->x86-64 (Linux 64)'; else prodHWDeviceType = 'Intel->x86-64 (Windows64)'; end end
Set the production hardware device type.
prodHWDeviceType = getProdHWDeviceType();
set_param(modelHandle, 'ProdHWDeviceType', prodHWDeviceType);
Run SIL simulation
To compute the responses using the generated code, use the sim
command along with the software-in-the-loop (sil)
option.
sim(modelHandle, 'SimulationMode', 'software-in-the-loop (sil)');
### Starting build procedure for: StatefulPredictBlockExample ### Successful completion of build procedure for: StatefulPredictBlockExample Build Summary Top model targets: Model Build Reason Status ================================================================================================================ StatefulPredictBlockExample Information cache folder or artifacts were missing. Code generated and compiled. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 40.183s ### Preparing to start SIL simulation ... Building with 'MinGW64 Compiler (C)'. MEX completed successfully. ### Starting SIL simulation for component: StatefulPredictBlockExample ### Application stopped ### Host application produced the following standard output (stdout) messages: ** created StatefulPredictBlockExample.mat ** ### Stopping SIL simulation for component: StatefulPredictBlockExample
Load the model output from file. Squeeze the singleton dimension from the 9-by-1-by-16 output to obtain the classification scores over time as a 2-D array.
outStruct = load('StatefulPredictBlockExample.mat').rt_modelOutput.signals;
scores = squeeze(outStruct.values);
numTimeSteps = size(scores, 2);
Plot the prediction scores. TTest
is a categorical vector of labels "1", "2", ... "9", which correspond to the nine speakers. The plot shows how the prediction scores change between time steps and highlights the prediction scores for the correct class.
classNames = string(categories(TTest)); figure lines = plot(scores'); xlim([1 numTimeSteps]) legend("Class " + classNames,'Location','northwest') xlabel("Time Step") ylabel("Score") title("Prediction Scores Over Time Steps") trueLabel = TTest(94); lines(trueLabel).LineWidth = 3;
Display the final time step prediction in a bar chart.
figure bar(scores(:,end)) title("Final Prediction Scores") xlabel("Class") ylabel("Score")
References
[1] Kudo, Mineichi, Jun Toyama, and Masaru Shimbo. “Multidimensional Curve Classification Using Passing-through Regions.” Pattern Recognition Letters 20, no. 11 (November 1, 1999): 1103–11. https://doi.org/10.1016/S0167-8655(99)00077-X.
[2] Mineichi Kudo, Jun Toyama. “Japanese Vowels.” UCI Machine Learning Repository, 1999. https://doi.org/10.24432/C5NS47.
See Also
Stateful Predict (Deep Learning Toolbox) | Predict (Deep Learning Toolbox)
Related Topics
- Predict and Update Network State in Simulink (Deep Learning Toolbox)