Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to construct input data to LSTM for time series multi-step horizon with external features?

I'm trying to use LSTM to do store sales forecast. Here is how my raw data look like:

|     Date   | StoreID | Sales | Temperature |  Open   | StoreType |
|------------|---------|-------|-------------|---------|-----------|
| 01/01/2016 |   1     |   0   |      36     |    0    |     1     |
| 01/02/2016 |   1     | 10100 |      42     |    1    |     1     |
| ...
| 12/31/2016 |   1     | 14300 |      39     |    1    |     1     |
| 01/01/2016 |   2     | 25000 |      46     |    1    |     3     |
| 01/02/2016 |   2     | 23700 |      43     |    1    |     3     |
| ...
| 12/31/2016 |   2     | 20600 |      37     |    1    |     3     |
| ...
| 12/31/2016 |   10    | 19800 |      52     |    1    |     2     |

I need to forecast for the next 10 days' sales. In this example, I will need to forecast the store sales from 01-01-2017 to 01-10-2017. I know how to use other time series model or regression model to solve this problem, but I want to know if RNN-LSTM is a good candidate for it.

I started by taking only storeID=1 data to test the LSTM. If my data only have Date and Sales. I will construct my trainX and trainY in this way (please correct me if I'm wrong):

Window = 20
Horizon = 10

|         trainX                  |          trainY              |
| [Yt-10, Yt-11, Yt-12,...,Yt-29] | [Yt, Yt-1, Yt-2,...,Yt-9]    |
| [Yt-11, Yt-12, Yt-13,...,Yt-30] | [Yt-2, Yt-3, Yt-4,...,Yt-10] |
| [Yt-12, Yt-13, Yt-14,...,Yt-31] | [Yt-3, Yt-4, Yt-5,...,Yt-11] |
...

After reshaping the two

trainX.shape
(300, 1, 20)
trainY.shape
(300, 10)

Question1: In this case, [samples, time steps, features] = [300, 1, 20]. Is this right? Or should I construct the sample as [300, 20, 1] ?

Question2: I do want to use other information in the raw data like Temperature, StoreType, etc. How should I construct my input data for LSTM?

Question3: So far we only discussed 1 store forecast, if I want to forecast for all the stores, how should I construct my input data then?

Currently I'm flowing examples from here, but it seems not sufficient to cover the scenario that I have. I really appreciate for your help!

like image 739
Yijing Chen Avatar asked Mar 03 '17 17:03

Yijing Chen


People also ask

Can LSTM be used for multivariate forecasting?

Long Short-Term Memory (LSTM) has proven to be a reliable model for forecasting the incidence of diseases [22, 23]. The unique forget gate structure may make the model perform well in the long-term prediction. Using a multivariate multistep LSTM model may obtain better prediction results.

How does LSTM take input?

The input of the LSTM is always is a 3D array. (batch_size, time_steps, seq_len) . The output of the LSTM could be a 2D array or 3D array depending upon the return_sequences argument.

How does LSTM model handle time series data?

LSTM stands for Long short-term memory. LSTM cells are used in recurrent neural networks that learn to predict the future from sequences of variable lengths. Note that recurrent neural networks work with any kind of sequential data and, unlike ARIMA and Prophet, are not restricted to time series.


Video Answer


1 Answers

I was recently solving similiar problem. In your case:

  1. Input should have shape (300, 20, 1) - because you have time sequences of length 20 with 1 feature.

  2. You may do it like this:

    sequential_input = Input(shape=(20, 1))
    feature_input = Input(shape=(feature_nb,))
    lstm_layer = LSTM(lstm_units_1st_layer, return_sequences=True)(sequential_input)
    lstm_layer = LSTM(lstm_units_2nd_layer, return_sequences=True)(lstm_layer)
    ...
    lstm_layer = LSTM(lstm_units_nth_layer, return_sequences=False)(lstm_layer)
    merged = merge([lstm_layer, feature_input], mode='concat')
    blend = Dense(blending_units_1st_layer, activation='relu')(merged)
    blend = Dense(blending_units_2nd_layer, activation='relu')(blend)
    ...
    output = Dense(10)(blend)
    
  3. This is the hardest part. I do not advise you to predict multiple shops by feeding them to a network as one feature vector. You may under simply skip this part and try to predict different shops using one model or postprocess output using e.g. some kind of graphical models or PCA on matrix where rows are day sales.

UPDATE:

In order to deal with multiple sequential features you could do the following thing:

    sequential_input = Input(shape=(20, nb_of_sequental_features))
    feature_input = Input(shape=(feature_nb,))
    lstm_layer = LSTM(lstm_units_1st_layer, return_sequences=True)(sequential_input)
    lstm_layer = LSTM(lstm_units_2nd_layer, return_sequences=True)(lstm_layer)
    ...
    lstm_layer = LSTM(lstm_units_nth_layer, return_sequences=False)(lstm_layer)
    merged = merge([lstm_layer, feature_input], mode='concat')
    blend = Dense(blending_units_1st_layer, activation='relu')(merged)
    blend = Dense(blending_units_2nd_layer, activation='relu')(blend)
    ...
    output = Dense(10)(blend)
    model = Model(input=[sequential_input, feature_input], output=output])

In this case your input should consist of list of two tables: [sequential_data, features] where sequential_data.shape = (nb_of_examples, timesteps, sequential_features) and features.shape = (nb_of_examples, feature_nb). So sales or temperature should be stored in sequential_features and store_type in features.

like image 178
Marcin Możejko Avatar answered Oct 24 '22 22:10

Marcin Możejko