# Time Series Prediction in Simulink Using Deep Learning Network

This example shows how to use an LSTM deep learning network inside a Simulink® model to predict the remaining useful life (RUL) of an engine. You include the network inside the Simulink model by using a `Stateful Predict`

block, which predicts the RUL at every simulation step.

This example uses data from the *Turbofan Engine Degradation Simulation Data Set* as described in [1]. The example uses a trained LSTM network to predict the RUL of an engine (predictive maintenance), measured in cycles, given time series data representing various sensors in the engine. The data used to train the network contains simulated time series data for 100 engines. Each sequence has 17 features of varying length and corresponds to a full run to failure (RTF) instance. For more information on how to train the network, see Sequence-to-Sequence Regression Using Deep Learning.

**Download Data**

Download and unzip the Turbofan Engine Degradation Simulation data set.

Each time series of the Turbofan Engine Degradation Simulation data set represents a different engine. Each engine starts with unknown degrees of initial wear and manufacturing variation. The engine is operating normally at the start of each time series, and develops a fault at some point during the series. In the training set, the fault grows in magnitude until system failure.

The data contains a ZIP-compressed text files with 26 columns of numbers, separated by spaces. Each row is a snapshot of data taken during a single operational cycle, and each column is a different variable. The columns correspond to the following:

Column 1 – Unit number

Column 2 – Time in cycles

Columns 3–5 – Operational settings

Columns 6–26 – Sensor measurements 1–21

Create a directory to store the Turbofan Engine Degradation Simulation data set.

dataFolder = "data"; if ~exist(dataFolder,"dir") mkdir(dataFolder); end

Download and extract the Turbofan Engine Degradation Simulation data set.

filename = matlab.internal.examples.downloadSupportFile("nnet","data/TurbofanEngineDegradationSimulationData.zip"); unzip(filename,dataFolder)

**Prepare Data**

Load the data using the `processTurboFanDataTrain`

helper function. The `processTurboFanDataTrain`

function extracts the data from `filenamePredictors`

and returns the cell array `XTrain`

, which contains the training predictor data.

```
filenamePredictors = fullfile(dataFolder,"train_FD001.txt");
[XTrain] = processTurboFanDataTrain(filenamePredictors);
```

**Remove Features with Constant Values**

Since the network was trained with features that do not remain constant for all time steps, features with constant values for all time steps need to be removed for prediction. Find the rows of data that have the same minimum and maximum values, and remove the rows.

m = min([XTrain{:}],[],2); M = max([XTrain{:}],[],2); idxConstant = M == m; for i = 1:numel(XTrain) XTrain{i}(idxConstant,:) = []; end

**Normalize Training Predictors**

Normalize the training predictors to have zero mean and unit variance. To calculate the mean and standard deviation over all observations, concatenate the sequence data horizontally.

mu = mean([XTrain{:}],2); sig = std([XTrain{:}],0,2); for i = 1:numel(XTrain) XTrain{i} = (XTrain{i} - mu) ./ sig; end

#### Extract data for one engine

In the Simulink model, we calculate the RUL for one engine only. In this example, we extract the 9th element of `XTrain`

and store it in a variable named `SensorData. Y`

ou can choose any other engine from the `XTrain`

cell array. `SensorData`

is a double array of size 17-by-201. Every row corresponds to one feature and every column corresponds to the sensor readings at a given cycle.

SensorData = XTrain{9};

Simulink models have an associated simulation time, which in this example needs to be related to the engine cycles. For this reason, we define a timeseries named `EngineData`

, which stores the sensor data as a timeseries object that can be loaded in the Simulink model. As the default simulation time in Simulink is `10.0`

and the engine runs through 201 cycles, the `Time`

field of `EngineData`

needs to be an array of size 201-by-1 with values linearly increasing from 0 to 10.

Time = linspace(0,10,201)'; EngineData = timeseries(SensorData',Time);

The top panel of this figure shows the sensor readings from each sensor at each cycle and the bottom panel shows the RUL of the engine in units of cycles. After 201 cycles, the engine stops operating. Note, if you select another engine from the `XTrain`

data, then you need to adapt the `Time`

field of `EngineData`

accordingly, as each engine operates for a different number of cycles.

### Simulink Model to Predict RUL

Load the Simulink model `RULPredictionLSTM.slx`

.

```
modelName = 'RULPredictionLSTM';
open_system(modelName);
```

`EngineData`

is loaded from the base workspace using a `From Workspace`

block. In this example, the time step in `EngineData`

is `0.05. S`

o, we set the sample time of the `From Workspace`

block to 0.05. Hence, at the first step the block outputs the first row of `EngineData`

, at the second step it outputs the second row - corresponding to the second engine cycle - and so on. If another engine is chosen from `XData`

, then the sample time of the block needs to be updated accordingly.

set_param([modelName,'/From Workspace'],'SampleTime','0.05');

The `Stateful Predict`

block loads the pretrained LSTM network in the `turbofanNet`

MAT-file and returns the RUL at its output port. The `Stateful Predict`

block updates the state of the network with every prediction, improving the prediction of the current RUL.The `Half Gauge`

block shows the value of the calculated RUL (in units of engine cycles) during the simulation.

RUL_sigSpec = Simulink.HMI.SignalSpecification; RUL_sigSpec.BlockPath = Simulink.BlockPath('RULPredictionLSTM/Stateful Predict'); set_param('RULPredictionLSTM/Half Gauge','Binding',RUL_sigSpec)

### Run the Simulation

Because the simulation reads data from a MAT-file, it runs very quickly and can be difficult to follow. To slow down the simulation, set the Simulation Pacing option to 0.5.

set_param(modelName,'EnablePacing','on'); set_param(modelName,'PacingRate',0.5);

To compute the RUL, run the simulation.

sim(modelName);

The figure shows the model while it is running. The gauge shows the estimated RUL, corresponding in this case to 90 cycles. At the end of the simulation, the RUL is returned to the Base Workspace in the form of a single array, containing the values calculated at each simulation iteration.

You could integrate this system within a bigger framework, for example in a system that continuously monitors the status of an engine, and which adopts precautionary measures if the RUL falls below a given user-defined value.

**References**

Saxena, Abhinav, Kai Goebel, Don Simon, and Neil Eklund. "Damage propagation modeling for aircraft engine run-to-failure simulation." In

*Prognostics and Health Management, 2008. PHM 2008. International Conference on*, pp. 1-9. IEEE, 2008.

## See Also

Stateful Predict | Stateful Classify | Predict | Image Classifier