Skip to content

Commit c613e4d

Browse files
committed
Adding LSTM neural network
1 parent b2208f7 commit c613e4d

File tree

2 files changed

+150
-0
lines changed

2 files changed

+150
-0
lines changed

python/shampoo_sales/dataset.py

+44
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#!/usr/bin/env python
22

3+
import numpy as np
34
import os
45
import pandas as pd
6+
from sklearn.preprocessing import MinMaxScaler
57

68
def load_date_series():
79
dirname = os.path.dirname(os.path.realpath(__file__))
@@ -12,3 +14,45 @@ def split_date_series(series):
1214
X = series.values
1315
train, test = X[0:-12], X[-12:]
1416
return train, test
17+
18+
# frame a sequence as a supervised learning problem
19+
def timeseries_to_supervised(data, lag=1):
20+
df = pd.DataFrame(data)
21+
columns = [df.shift(i) for i in range(1, lag+1)]
22+
columns.append(df)
23+
df = pd.concat(columns, axis=1)
24+
df.fillna(0, inplace=True)
25+
return df
26+
27+
# create a differenced series
28+
def difference(dataset, interval=1):
29+
diff = []
30+
for i in range(interval, len(dataset)):
31+
value = dataset[i] - dataset[i - interval]
32+
diff.append(value)
33+
return pd.Series(diff)
34+
35+
# invert differenced value
36+
def inverse_difference(history, yhat, interval=1):
37+
return yhat + history[-interval]
38+
39+
# scale train and test data to [-1, 1]
40+
def scale(train, test):
41+
# fit scaler
42+
scaler = MinMaxScaler(feature_range=(-1, 1))
43+
scaler = scaler.fit(train)
44+
# transform train
45+
train = train.reshape(train.shape[0], train.shape[1])
46+
train_scaled = scaler.transform(train)
47+
# transform test
48+
test = test.reshape(test.shape[0], test.shape[1])
49+
test_scaled = scaler.transform(test)
50+
return scaler, train_scaled, test_scaled
51+
52+
# inverse scaling for a forecasted value
53+
def invert_scale(scaler, X, value):
54+
new_row = [x for x in X] + [value]
55+
array = np.array(new_row)
56+
array = array.reshape(1, len(array))
57+
inverted = scaler.inverse_transform(array)
58+
return inverted[0, -1]
+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#!/usr/bin/env python
2+
3+
import matplotlib.pyplot as plt
4+
import pandas as pd
5+
from dataset import load_date_series, timeseries_to_supervised, difference, inverse_difference, scale, invert_scale
6+
from keras.models import Sequential
7+
from keras.layers import Dense
8+
from keras.layers import LSTM
9+
from math import sqrt
10+
from sklearn.metrics import mean_squared_error as mse
11+
12+
# fit an LSTM network to training data
13+
def fit_lstm(train, batch_size, nb_epoch, neurons):
14+
X, y = train[:, 0:-1], train[:, -1]
15+
X = X.reshape(X.shape[0], 1, X.shape[1])
16+
model = Sequential()
17+
model.add(LSTM(neurons, batch_input_shape=(batch_size, X.shape[1], X.shape[2]), stateful=True))
18+
model.add(Dense(1))
19+
model.compile(loss='mean_squared_error', optimizer='adam')
20+
for i in range(nb_epoch):
21+
model.fit(X, y, epochs=1, batch_size=batch_size, verbose=0, shuffle=False)
22+
model.reset_states()
23+
return model
24+
25+
# make a one-step forecast
26+
def forecast_lstm(model, batch_size, X):
27+
X = X.reshape(1, 1, len(X))
28+
yhat = model.predict(X, batch_size=batch_size)
29+
return yhat[0,0]
30+
31+
def prepare_model():
32+
# Convert series into supervised learning problem
33+
series = load_date_series()
34+
X = series.values
35+
supervised = timeseries_to_supervised(X, 1)
36+
print("*** Supervised Learning ***")
37+
print(supervised.head())
38+
39+
# Convert time series to stationary
40+
differenced = difference(series, 1)
41+
print("*** Stationary Data Set ***")
42+
print(differenced.head())
43+
# invert transform
44+
inverted = list()
45+
for i in range(len(differenced)):
46+
value = inverse_difference(series, differenced[i], len(series)-i)
47+
inverted.append(value)
48+
inverted = pd.Series(inverted)
49+
print(inverted.head())
50+
51+
# Scale time series
52+
scaler, scaled_X = scale(series)
53+
scaled_series = pd.Series(scaled_X[:, 0])
54+
print("*** Scaled Time Series ***")
55+
print(scaled_series.head())
56+
# invert transform
57+
inverted_X = scaler.inverse_transform(scaled_X)
58+
inverted_series = pd.Series(inverted_X[:, 0])
59+
print(inverted_series.head())
60+
61+
def model(series):
62+
# transform data to be stationary
63+
raw_values = series.values
64+
diff_values = difference(raw_values, 1)
65+
66+
# transform data to be supervised learning
67+
supervised = timeseries_to_supervised(diff_values, 1)
68+
supervised_values = supervised.values
69+
70+
# split data into train and test-sets
71+
train, test = supervised_values[0:-12], supervised_values[-12:]
72+
73+
# transform the scale of the data
74+
scaler, train_scaled, test_scaled = scale(train, test)
75+
76+
# fit the model
77+
lstm_model = fit_lstm(train_scaled, 1, 3000, 4)
78+
# forecast the entire training dataset to build up state for forecasting
79+
train_reshaped = train_scaled[:, 0].reshape(len(train_scaled), 1, 1)
80+
lstm_model.predict(train_reshaped, batch_size=1)
81+
82+
# walk-forward validation on the test data
83+
predictions = list()
84+
for i in range(len(test_scaled)):
85+
# make one-step forecast
86+
X, y = test_scaled[i, 0:-1], test_scaled[i, -1]
87+
yhat = forecast_lstm(lstm_model, 1, X)
88+
# invert scaling
89+
yhat = invert_scale(scaler, X, yhat)
90+
# invert differencing
91+
yhat = inverse_difference(raw_values, yhat, len(test_scaled)+1-i)
92+
# store forecast
93+
predictions.append(yhat)
94+
expected = raw_values[len(train) + i + 1]
95+
print('Month=%d, Predicted=%f, Expected=%f' % (i+1, yhat, expected))
96+
97+
# report performance
98+
rmse = sqrt(mse(raw_values[-12:], predictions))
99+
print('Test RMSE: %.3f' % rmse)
100+
# line plot of observed vs predicted
101+
plt.plot(raw_values[-12:])
102+
plt.plot(predictions)
103+
plt.show()
104+
105+
series = load_date_series()
106+
model(series)

0 commit comments

Comments
 (0)