Time-Series Prediction Beyond Test Data | by Andrej Baranovskij | Towards Data Science

I was working on the assignment to build a large scale time-series prediction solution. I end up using a combination of approaches in the single solution — Prophet, ARIMA and LSTM Neural Network (running on top of Keras/TensorFlow). With Prophet (Serving Prophet Model with Flask — Predicting Future) and ARIMA it is straightforward to calculate a prediction for future dates, both provide a function to return prediction for a given future horizon. The same is not obvious with LSTM, if you are new — this will require a significant amount of time to research how to forecast true future dates (most of the examples are showing how to predict against test dataset only).
I found one good example though which I was following and it helped me to solve my task — A Quick Example of Time-Series Prediction Using Long Short-Term Memory (LSTM) Networks. In this post, I will show how to predict shampoo sales monthly data, mainly based on the code from the above example.
A dataset with shampoo monthly sales data can be downloaded from Kaggle.
LSTM model is built with TensorFlow 2.0 and Keras.
First, we need to fetch and parse time-series data:
def parser(x):    return pd.datetime.strptime('190'+x, '%Y-%m')df = pd.read_csv('shampoo.csv', parse_dates=[0], index_col=0, date_parser=parser)df.tail()
For LSTM model training, data must be scaled, this is done with MinMaxScaler from sklearn library:
train = dfscaler = MinMaxScaler()scaler.fit(train)train = scaler.transform(train)
Time-series prediction is a sequence prediction task. Dates are not really important to ML algorithm, it rather tries to identify dependency patterns between past and future data. There are numerous ways how to transform raw sequence data to be suitable for LSTM neural network training. I prefer to use Keras TimeseriesGenerator (read more about it here — How to Use the TimeseriesGenerator for Time Series Forecasting in Keras). We are going to predict 12 months of shampoo sales, for that will use 12 months window from the past to identify prediction:
n_input = 12n_features = 1generator = TimeseriesGenerator(train, train, length=n_input, batch_size=6)
LSTM model training. For input and target, we are going to use entire set of time-series data, the model will be trained on the entire set. This will allow generating prediction for the dates onward after the last date available in the training set:
model = Sequential()model.add(LSTM(200, activation='relu', input_shape=(n_input, n_features)))model.add(Dropout(0.15))model.add(Dense(1))optimizer = keras.optimizers.Adam(learning_rate=0.001)model.compile(optimizer=optimizer, loss='mse')history = model.fit_generator(generator,epochs=100,verbose=1)
Once the model is trained, we can generate a prediction for future dates. The idea here — generate a prediction for one future step, using the last 12 steps. Add new prediction to the array, remove the first entry from the same array and predict the next step with an updated array of 12 steps.
pred_list = []batch = train[-n_input:].reshape((1, n_input, n_features))for i in range(n_input):       pred_list.append(model.predict(batch)[0])     batch = np.append(batch[:,1:,:],[[pred_list[i]]],axis=1)
Create a data frame with future months, we will assign calculated prediction data to these months:
add_dates = [df.index[-1] + DateOffset(months=x) for x in range(0,13) ]future_dates = pd.DataFrame(index=add_dates[1:],columns=df.columns)
Create a data frame with dates and prediction data. Finally, merge with training data frame to draw a chart showing training data and true future prediction:
df_predict = pd.DataFrame(scaler.inverse_transform(pred_list),                          index=future_dates[-n_input:].index, columns=['Prediction'])df_proj = pd.concat([df,df_predict], axis=1)
The result is displayed with Plotly:
plot_data = [    go.Scatter(        x=df_proj.index,        y=df_proj['Sales'],        name='actual'    ),    go.Scatter(        x=df_proj.index,        y=df_proj['Prediction'],        name='prediction'    )]plot_layout = go.Layout(        title='Shampoo sales prediction'    )fig = go.Figure(data=plot_data, layout=plot_layout)pyoff.iplot(fig)
True future sales predicted and displayed in yellow:
Source code is available on GitHub.