Stock Price
Materials¶
MSFT Stock data from Yahoo Finance
Load Helper Library¶
In [1]:
Copied!
import pandas as pd
import datetime
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import datetime
import matplotlib.pyplot as plt
import numpy as np
Load data¶
In [2]:
Copied!
data = pd.read_csv("./Data/MSFT.csv")
data.head()
data = pd.read_csv("./Data/MSFT.csv")
data.head()
Out[2]:
Date | Open | High | Low | Close | Adj Close | Volume | |
---|---|---|---|---|---|---|---|
0 | 1986-03-13 | 0.088542 | 0.101563 | 0.088542 | 0.097222 | 0.060274 | 1031788800 |
1 | 1986-03-14 | 0.097222 | 0.102431 | 0.097222 | 0.100694 | 0.062427 | 308160000 |
2 | 1986-03-17 | 0.100694 | 0.103299 | 0.100694 | 0.102431 | 0.063504 | 133171200 |
3 | 1986-03-18 | 0.102431 | 0.103299 | 0.098958 | 0.099826 | 0.061889 | 67766400 |
4 | 1986-03-19 | 0.099826 | 0.100694 | 0.097222 | 0.098090 | 0.060812 | 47894400 |
In [3]:
Copied!
df_clean = data[["Date","Close"]]
df_clean.head()
df_clean = data[["Date","Close"]]
df_clean.head()
Out[3]:
Date | Close | |
---|---|---|
0 | 1986-03-13 | 0.097222 |
1 | 1986-03-14 | 0.100694 |
2 | 1986-03-17 | 0.102431 |
3 | 1986-03-18 | 0.099826 |
4 | 1986-03-19 | 0.098090 |
In [4]:
Copied!
def str_to_datetime(s):
year,month,day = str(s).split("-")
return datetime.datetime(year = int(year),month= int(month),day = int(day))
str_to_datetime(df_clean['Date'][0])
def str_to_datetime(s):
year,month,day = str(s).split("-")
return datetime.datetime(year = int(year),month= int(month),day = int(day))
str_to_datetime(df_clean['Date'][0])
Out[4]:
datetime.datetime(1986, 3, 13, 0, 0)
In [5]:
Copied!
df_clean['Datetime'] = df_clean['Date'].apply(str_to_datetime)
df_clean['Datetime'][:5]
df_clean['Datetime'] = df_clean['Date'].apply(str_to_datetime)
df_clean['Datetime'][:5]
C:\Users\yyang\AppData\Local\Temp\ipykernel_7664\958298037.py:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy df_clean['Datetime'] = df_clean['Date'].apply(str_to_datetime)
Out[5]:
0 1986-03-13 1 1986-03-14 2 1986-03-17 3 1986-03-18 4 1986-03-19 Name: Datetime, dtype: datetime64[ns]
In [6]:
Copied!
df_clean.index = df_clean.pop('Datetime')
df_clean.head()
df_clean.index = df_clean.pop('Datetime')
df_clean.head()
Out[6]:
Date | Close | |
---|---|---|
Datetime | ||
1986-03-13 | 1986-03-13 | 0.097222 |
1986-03-14 | 1986-03-14 | 0.100694 |
1986-03-17 | 1986-03-17 | 0.102431 |
1986-03-18 | 1986-03-18 | 0.099826 |
1986-03-19 | 1986-03-19 | 0.098090 |
In [7]:
Copied!
plt.plot(df_clean.index,df_clean['Close'])
plt.plot(df_clean.index,df_clean['Close'])
Out[7]:
[<matplotlib.lines.Line2D at 0x28d4422f4c0>]
Create Windowed Data¶
In [8]:
Copied!
def df_to_windowed_df(df, first_date_str, last_date_str, n=3):
## Get start date and end date
first_date = str_to_datetime(first_date_str)
last_date = str_to_datetime(last_date_str)
## Initial target date as start date
target_date = first_date
dates = []
X,Y = [],[]
last_time = False
while True:
## Pick n+1 dates from the bottom of df
df_subset = df.loc[:target_date].tail(n+1)
if len(df_subset) != n+1:
print(f'Error: Window of size {n} is too large for date {target_date}')
return
values = df_subset['Close'].to_numpy()
x, y = values[:-1], values[-1]
dates.append(target_date)
X.append(x)
Y.append(y)
next_week = df.loc[target_date:target_date+datetime.timedelta(days=7)]
next_datetime_str = str(next_week.head(2).tail(1).index.values[0])
next_date_str = next_datetime_str.split('T')[0]
year_month_day = next_date_str.split('-')
year, month, day = year_month_day
next_date = datetime.datetime(day=int(day), month=int(month), year=int(year))
if last_time:
break
target_date = next_date
if target_date == last_date:
last_time = True
ret_df = pd.DataFrame({})
ret_df['Target Date'] = dates
X = np.array(X)
for i in range(0, n):
X[:, i]
ret_df[f'Target-{n-i}'] = X[:, i]
ret_df['Target'] = Y
return ret_df
def df_to_windowed_df(df, first_date_str, last_date_str, n=3):
## Get start date and end date
first_date = str_to_datetime(first_date_str)
last_date = str_to_datetime(last_date_str)
## Initial target date as start date
target_date = first_date
dates = []
X,Y = [],[]
last_time = False
while True:
## Pick n+1 dates from the bottom of df
df_subset = df.loc[:target_date].tail(n+1)
if len(df_subset) != n+1:
print(f'Error: Window of size {n} is too large for date {target_date}')
return
values = df_subset['Close'].to_numpy()
x, y = values[:-1], values[-1]
dates.append(target_date)
X.append(x)
Y.append(y)
next_week = df.loc[target_date:target_date+datetime.timedelta(days=7)]
next_datetime_str = str(next_week.head(2).tail(1).index.values[0])
next_date_str = next_datetime_str.split('T')[0]
year_month_day = next_date_str.split('-')
year, month, day = year_month_day
next_date = datetime.datetime(day=int(day), month=int(month), year=int(year))
if last_time:
break
target_date = next_date
if target_date == last_date:
last_time = True
ret_df = pd.DataFrame({})
ret_df['Target Date'] = dates
X = np.array(X)
for i in range(0, n):
X[:, i]
ret_df[f'Target-{n-i}'] = X[:, i]
ret_df['Target'] = Y
return ret_df
Use the previous 3 days data to predict target price¶
In [9]:
Copied!
# Start day second time around: '2020-03-25'
windowed_df = df_to_windowed_df(df_clean[['Close']],
'2020-03-25',
'2023-11-20',
n=5)
windowed_df.head()
# Start day second time around: '2020-03-25'
windowed_df = df_to_windowed_df(df_clean[['Close']],
'2020-03-25',
'2023-11-20',
n=5)
windowed_df.head()
Out[9]:
Target Date | Target-5 | Target-4 | Target-3 | Target-2 | Target-1 | Target | |
---|---|---|---|---|---|---|---|
0 | 2020-03-25 | 140.399994 | 142.710007 | 137.350006 | 135.979996 | 148.339996 | 146.919998 |
1 | 2020-03-26 | 142.710007 | 137.350006 | 135.979996 | 148.339996 | 146.919998 | 156.110001 |
2 | 2020-03-27 | 137.350006 | 135.979996 | 148.339996 | 146.919998 | 156.110001 | 149.699997 |
3 | 2020-03-30 | 135.979996 | 148.339996 | 146.919998 | 156.110001 | 149.699997 | 160.229996 |
4 | 2020-03-31 | 148.339996 | 146.919998 | 156.110001 | 149.699997 | 160.229996 | 157.710007 |
Convert to numpy array¶
In [10]:
Copied!
def windowed_df_to_date_X_y(windowed_df):
df_as_np = windowed_df.to_numpy()
dates = df_as_np[:,0] # get first col
middle_matrix = df_as_np[:,1:-1] # get all X (except date and target)
X = middle_matrix.reshape((len(dates),middle_matrix.shape[1],1))
Y = df_as_np[:,-1]
return dates, X.astype(np.float32), Y.astype(np.float32)
def windowed_df_to_date_X_y(windowed_df):
df_as_np = windowed_df.to_numpy()
dates = df_as_np[:,0] # get first col
middle_matrix = df_as_np[:,1:-1] # get all X (except date and target)
X = middle_matrix.reshape((len(dates),middle_matrix.shape[1],1))
Y = df_as_np[:,-1]
return dates, X.astype(np.float32), Y.astype(np.float32)
In [11]:
Copied!
dates, X, y = windowed_df_to_date_X_y(windowed_df=windowed_df)
dates.shape, X.shape, y.shape
dates, X, y = windowed_df_to_date_X_y(windowed_df=windowed_df)
dates.shape, X.shape, y.shape
Out[11]:
((922,), (922, 5, 1), (922,))
In [12]:
Copied!
q_80 = int(len(dates) * .8)
q_90 = int(len(dates) * .9)
dates_train, X_train, y_train = dates[:q_80], X[:q_80], y[:q_80]
dates_val, X_val, y_val = dates[q_80:q_90], X[q_80:q_90], y[q_80:q_90]
dates_test, X_test, y_test = dates[q_90:], X[q_90:], y[q_90:]
plt.plot(dates_train,y_train)
plt.plot(dates_val,y_val)
plt.plot(dates_test,y_test)
plt.legend(['Train','Validation','Test'])
plt.show()
q_80 = int(len(dates) * .8)
q_90 = int(len(dates) * .9)
dates_train, X_train, y_train = dates[:q_80], X[:q_80], y[:q_80]
dates_val, X_val, y_val = dates[q_80:q_90], X[q_80:q_90], y[q_80:q_90]
dates_test, X_test, y_test = dates[q_90:], X[q_90:], y[q_90:]
plt.plot(dates_train,y_train)
plt.plot(dates_val,y_val)
plt.plot(dates_test,y_test)
plt.legend(['Train','Validation','Test'])
plt.show()
Build model¶
In [13]:
Copied!
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import layers
In [14]:
Copied!
model = Sequential([layers.Input((5, 1)),
layers.LSTM(64),
layers.Dense(32, activation='relu'),
layers.Dense(32, activation='relu'),
layers.Dense(1)])
model.compile(loss='mse',
optimizer=Adam(learning_rate=0.001),
metrics=['mean_absolute_error'])
model.fit(X_train, y_train, validation_data=(X_val, y_val), epochs=100)
model = Sequential([layers.Input((5, 1)),
layers.LSTM(64),
layers.Dense(32, activation='relu'),
layers.Dense(32, activation='relu'),
layers.Dense(1)])
model.compile(loss='mse',
optimizer=Adam(learning_rate=0.001),
metrics=['mean_absolute_error'])
model.fit(X_train, y_train, validation_data=(X_val, y_val), epochs=100)
Epoch 1/100 24/24 [==============================] - 3s 22ms/step - loss: 64700.7969 - mean_absolute_error: 250.8540 - val_loss: 90639.2266 - val_mean_absolute_error: 299.7093 Epoch 2/100 24/24 [==============================] - 0s 5ms/step - loss: 62909.3477 - mean_absolute_error: 247.2332 - val_loss: 87260.4141 - val_mean_absolute_error: 294.0069 Epoch 3/100 24/24 [==============================] - 0s 5ms/step - loss: 58325.8984 - mean_absolute_error: 237.7573 - val_loss: 79421.5938 - val_mean_absolute_error: 280.3708 Epoch 4/100 24/24 [==============================] - 0s 5ms/step - loss: 50302.2539 - mean_absolute_error: 220.2361 - val_loss: 66288.1172 - val_mean_absolute_error: 255.8769 Epoch 5/100 24/24 [==============================] - 0s 5ms/step - loss: 36923.7109 - mean_absolute_error: 187.1199 - val_loss: 46130.1641 - val_mean_absolute_error: 212.8674 Epoch 6/100 24/24 [==============================] - 0s 5ms/step - loss: 20537.5977 - mean_absolute_error: 135.8048 - val_loss: 23830.1621 - val_mean_absolute_error: 151.7127 Epoch 7/100 24/24 [==============================] - 0s 5ms/step - loss: 7167.4141 - mean_absolute_error: 73.2448 - val_loss: 8843.2949 - val_mean_absolute_error: 89.6171 Epoch 8/100 24/24 [==============================] - 0s 5ms/step - loss: 2285.6494 - mean_absolute_error: 38.3769 - val_loss: 3809.8811 - val_mean_absolute_error: 54.7855 Epoch 9/100 24/24 [==============================] - 0s 5ms/step - loss: 1773.1282 - mean_absolute_error: 34.3347 - val_loss: 3243.3267 - val_mean_absolute_error: 49.7099 Epoch 10/100 24/24 [==============================] - 0s 5ms/step - loss: 1619.5012 - mean_absolute_error: 32.6725 - val_loss: 3407.9321 - val_mean_absolute_error: 52.2982 Epoch 11/100 24/24 [==============================] - 0s 5ms/step - loss: 1307.7965 - mean_absolute_error: 28.7729 - val_loss: 2744.8015 - val_mean_absolute_error: 45.8001 Epoch 12/100 24/24 [==============================] - 0s 6ms/step - loss: 942.3654 - mean_absolute_error: 23.7589 - val_loss: 1874.2069 - val_mean_absolute_error: 36.7833 Epoch 13/100 24/24 [==============================] - 0s 6ms/step - loss: 570.8736 - mean_absolute_error: 18.0162 - val_loss: 1290.1581 - val_mean_absolute_error: 29.6485 Epoch 14/100 24/24 [==============================] - 0s 5ms/step - loss: 270.0463 - mean_absolute_error: 10.8772 - val_loss: 743.5017 - val_mean_absolute_error: 21.6188 Epoch 15/100 24/24 [==============================] - 0s 5ms/step - loss: 166.8246 - mean_absolute_error: 8.5275 - val_loss: 497.0657 - val_mean_absolute_error: 17.1792 Epoch 16/100 24/24 [==============================] - 0s 5ms/step - loss: 119.8960 - mean_absolute_error: 7.2713 - val_loss: 418.4578 - val_mean_absolute_error: 16.2316 Epoch 17/100 24/24 [==============================] - 0s 5ms/step - loss: 89.0200 - mean_absolute_error: 6.3018 - val_loss: 276.2355 - val_mean_absolute_error: 13.6817 Epoch 18/100 24/24 [==============================] - 0s 5ms/step - loss: 88.1300 - mean_absolute_error: 6.6992 - val_loss: 252.4207 - val_mean_absolute_error: 12.5406 Epoch 19/100 24/24 [==============================] - 0s 5ms/step - loss: 68.9827 - mean_absolute_error: 5.9186 - val_loss: 171.6811 - val_mean_absolute_error: 10.1333 Epoch 20/100 24/24 [==============================] - 0s 5ms/step - loss: 59.6638 - mean_absolute_error: 5.5242 - val_loss: 167.8197 - val_mean_absolute_error: 10.1644 Epoch 21/100 24/24 [==============================] - 0s 5ms/step - loss: 52.5270 - mean_absolute_error: 5.3334 - val_loss: 151.7720 - val_mean_absolute_error: 9.7537 Epoch 22/100 24/24 [==============================] - 0s 5ms/step - loss: 48.7350 - mean_absolute_error: 5.1499 - val_loss: 100.8088 - val_mean_absolute_error: 8.1104 Epoch 23/100 24/24 [==============================] - 0s 5ms/step - loss: 50.7943 - mean_absolute_error: 5.4135 - val_loss: 92.2259 - val_mean_absolute_error: 7.4285 Epoch 24/100 24/24 [==============================] - 0s 5ms/step - loss: 49.6154 - mean_absolute_error: 5.4821 - val_loss: 89.5156 - val_mean_absolute_error: 8.2630 Epoch 25/100 24/24 [==============================] - 0s 5ms/step - loss: 52.7349 - mean_absolute_error: 5.6618 - val_loss: 85.3826 - val_mean_absolute_error: 8.1461 Epoch 26/100 24/24 [==============================] - 0s 5ms/step - loss: 60.7915 - mean_absolute_error: 6.3895 - val_loss: 80.9683 - val_mean_absolute_error: 7.9389 Epoch 27/100 24/24 [==============================] - 0s 5ms/step - loss: 54.3358 - mean_absolute_error: 5.8916 - val_loss: 56.4830 - val_mean_absolute_error: 6.0659 Epoch 28/100 24/24 [==============================] - 0s 5ms/step - loss: 34.5925 - mean_absolute_error: 4.5107 - val_loss: 77.3948 - val_mean_absolute_error: 6.9514 Epoch 29/100 24/24 [==============================] - 0s 5ms/step - loss: 40.0486 - mean_absolute_error: 4.9999 - val_loss: 74.7032 - val_mean_absolute_error: 6.8890 Epoch 30/100 24/24 [==============================] - 0s 5ms/step - loss: 34.0681 - mean_absolute_error: 4.4945 - val_loss: 42.8746 - val_mean_absolute_error: 5.4615 Epoch 31/100 24/24 [==============================] - 0s 5ms/step - loss: 38.7259 - mean_absolute_error: 4.8292 - val_loss: 127.1407 - val_mean_absolute_error: 9.5193 Epoch 32/100 24/24 [==============================] - 0s 5ms/step - loss: 68.7405 - mean_absolute_error: 6.6049 - val_loss: 71.5374 - val_mean_absolute_error: 6.7948 Epoch 33/100 24/24 [==============================] - 0s 5ms/step - loss: 33.1348 - mean_absolute_error: 4.4463 - val_loss: 60.0183 - val_mean_absolute_error: 6.0556 Epoch 34/100 24/24 [==============================] - 0s 5ms/step - loss: 32.5504 - mean_absolute_error: 4.3806 - val_loss: 45.8464 - val_mean_absolute_error: 5.3553 Epoch 35/100 24/24 [==============================] - 0s 5ms/step - loss: 42.8262 - mean_absolute_error: 5.1307 - val_loss: 50.6827 - val_mean_absolute_error: 6.0563 Epoch 36/100 24/24 [==============================] - 0s 5ms/step - loss: 49.1252 - mean_absolute_error: 5.3723 - val_loss: 41.9963 - val_mean_absolute_error: 5.0642 Epoch 37/100 24/24 [==============================] - 0s 5ms/step - loss: 29.9774 - mean_absolute_error: 4.1824 - val_loss: 37.1403 - val_mean_absolute_error: 4.7612 Epoch 38/100 24/24 [==============================] - 0s 5ms/step - loss: 28.8963 - mean_absolute_error: 4.1712 - val_loss: 32.6261 - val_mean_absolute_error: 4.6011 Epoch 39/100 24/24 [==============================] - 0s 5ms/step - loss: 32.2622 - mean_absolute_error: 4.4233 - val_loss: 73.6528 - val_mean_absolute_error: 6.9744 Epoch 40/100 24/24 [==============================] - 0s 5ms/step - loss: 30.8628 - mean_absolute_error: 4.3757 - val_loss: 44.1038 - val_mean_absolute_error: 5.1233 Epoch 41/100 24/24 [==============================] - 0s 5ms/step - loss: 34.1367 - mean_absolute_error: 4.5432 - val_loss: 212.1691 - val_mean_absolute_error: 13.4217 Epoch 42/100 24/24 [==============================] - 0s 5ms/step - loss: 96.6283 - mean_absolute_error: 7.8120 - val_loss: 48.0220 - val_mean_absolute_error: 5.4731 Epoch 43/100 24/24 [==============================] - 0s 5ms/step - loss: 36.5719 - mean_absolute_error: 4.7640 - val_loss: 49.7376 - val_mean_absolute_error: 5.4738 Epoch 44/100 24/24 [==============================] - 0s 5ms/step - loss: 32.5199 - mean_absolute_error: 4.3832 - val_loss: 50.2171 - val_mean_absolute_error: 5.8298 Epoch 45/100 24/24 [==============================] - 0s 5ms/step - loss: 41.3961 - mean_absolute_error: 5.2220 - val_loss: 36.1180 - val_mean_absolute_error: 4.5924 Epoch 46/100 24/24 [==============================] - 0s 8ms/step - loss: 28.8887 - mean_absolute_error: 4.1693 - val_loss: 29.4751 - val_mean_absolute_error: 4.3090 Epoch 47/100 24/24 [==============================] - 0s 5ms/step - loss: 27.7767 - mean_absolute_error: 4.0879 - val_loss: 48.7646 - val_mean_absolute_error: 5.7600 Epoch 48/100 24/24 [==============================] - 0s 5ms/step - loss: 40.0560 - mean_absolute_error: 4.9137 - val_loss: 32.8701 - val_mean_absolute_error: 4.4227 Epoch 49/100 24/24 [==============================] - 0s 5ms/step - loss: 33.5932 - mean_absolute_error: 4.5672 - val_loss: 45.3128 - val_mean_absolute_error: 5.2364 Epoch 50/100 24/24 [==============================] - 0s 5ms/step - loss: 29.0120 - mean_absolute_error: 4.1996 - val_loss: 34.8846 - val_mean_absolute_error: 4.5825 Epoch 51/100 24/24 [==============================] - 0s 5ms/step - loss: 28.8310 - mean_absolute_error: 4.1569 - val_loss: 25.3244 - val_mean_absolute_error: 4.0584 Epoch 52/100 24/24 [==============================] - 0s 5ms/step - loss: 26.6185 - mean_absolute_error: 3.9462 - val_loss: 51.4832 - val_mean_absolute_error: 5.6690 Epoch 53/100 24/24 [==============================] - 0s 5ms/step - loss: 31.0599 - mean_absolute_error: 4.3876 - val_loss: 33.3232 - val_mean_absolute_error: 4.3753 Epoch 54/100 24/24 [==============================] - 0s 5ms/step - loss: 25.6572 - mean_absolute_error: 3.9117 - val_loss: 26.8376 - val_mean_absolute_error: 4.0606 Epoch 55/100 24/24 [==============================] - 0s 7ms/step - loss: 26.5836 - mean_absolute_error: 3.9805 - val_loss: 31.1554 - val_mean_absolute_error: 4.2142 Epoch 56/100 24/24 [==============================] - 0s 5ms/step - loss: 32.5101 - mean_absolute_error: 4.4840 - val_loss: 66.6746 - val_mean_absolute_error: 6.5821 Epoch 57/100 24/24 [==============================] - 0s 5ms/step - loss: 31.8220 - mean_absolute_error: 4.4113 - val_loss: 72.7425 - val_mean_absolute_error: 7.1828 Epoch 58/100 24/24 [==============================] - 0s 5ms/step - loss: 27.5739 - mean_absolute_error: 4.0573 - val_loss: 28.1068 - val_mean_absolute_error: 4.1540 Epoch 59/100 24/24 [==============================] - 0s 6ms/step - loss: 25.7077 - mean_absolute_error: 3.9102 - val_loss: 29.2847 - val_mean_absolute_error: 4.2125 Epoch 60/100 24/24 [==============================] - 0s 5ms/step - loss: 27.2269 - mean_absolute_error: 3.9994 - val_loss: 93.8386 - val_mean_absolute_error: 8.4723 Epoch 61/100 24/24 [==============================] - 0s 5ms/step - loss: 41.8726 - mean_absolute_error: 5.1354 - val_loss: 31.5979 - val_mean_absolute_error: 4.5271 Epoch 62/100 24/24 [==============================] - 0s 5ms/step - loss: 32.9103 - mean_absolute_error: 4.5482 - val_loss: 24.1847 - val_mean_absolute_error: 3.8983 Epoch 63/100 24/24 [==============================] - 0s 5ms/step - loss: 25.0374 - mean_absolute_error: 3.8368 - val_loss: 24.1437 - val_mean_absolute_error: 3.9048 Epoch 64/100 24/24 [==============================] - 0s 5ms/step - loss: 27.3458 - mean_absolute_error: 3.9913 - val_loss: 165.4915 - val_mean_absolute_error: 11.9186 Epoch 65/100 24/24 [==============================] - 0s 5ms/step - loss: 47.1763 - mean_absolute_error: 5.4960 - val_loss: 24.8587 - val_mean_absolute_error: 4.0202 Epoch 66/100 24/24 [==============================] - 0s 5ms/step - loss: 26.6300 - mean_absolute_error: 4.0043 - val_loss: 25.7603 - val_mean_absolute_error: 3.9999 Epoch 67/100 24/24 [==============================] - 0s 6ms/step - loss: 24.8104 - mean_absolute_error: 3.7768 - val_loss: 25.6079 - val_mean_absolute_error: 3.8815 Epoch 68/100 24/24 [==============================] - 0s 5ms/step - loss: 25.4632 - mean_absolute_error: 3.8594 - val_loss: 41.4011 - val_mean_absolute_error: 5.0629 Epoch 69/100 24/24 [==============================] - 0s 5ms/step - loss: 25.7855 - mean_absolute_error: 3.8966 - val_loss: 61.3608 - val_mean_absolute_error: 6.6592 Epoch 70/100 24/24 [==============================] - 0s 5ms/step - loss: 40.3738 - mean_absolute_error: 4.8690 - val_loss: 26.2879 - val_mean_absolute_error: 4.0042 Epoch 71/100 24/24 [==============================] - 0s 5ms/step - loss: 32.3756 - mean_absolute_error: 4.4222 - val_loss: 27.9265 - val_mean_absolute_error: 4.1227 Epoch 72/100 24/24 [==============================] - 0s 5ms/step - loss: 25.9243 - mean_absolute_error: 3.8898 - val_loss: 28.4754 - val_mean_absolute_error: 3.9795 Epoch 73/100 24/24 [==============================] - 0s 6ms/step - loss: 24.4715 - mean_absolute_error: 3.7476 - val_loss: 32.1392 - val_mean_absolute_error: 4.2417 Epoch 74/100 24/24 [==============================] - 0s 6ms/step - loss: 25.2986 - mean_absolute_error: 3.8623 - val_loss: 62.8205 - val_mean_absolute_error: 6.5797 Epoch 75/100 24/24 [==============================] - 0s 5ms/step - loss: 39.9704 - mean_absolute_error: 4.8703 - val_loss: 29.0779 - val_mean_absolute_error: 4.3468 Epoch 76/100 24/24 [==============================] - 0s 5ms/step - loss: 26.9675 - mean_absolute_error: 3.9638 - val_loss: 56.1122 - val_mean_absolute_error: 6.0081 Epoch 77/100 24/24 [==============================] - 0s 5ms/step - loss: 24.9551 - mean_absolute_error: 3.8377 - val_loss: 34.6093 - val_mean_absolute_error: 4.4631 Epoch 78/100 24/24 [==============================] - 0s 5ms/step - loss: 25.7704 - mean_absolute_error: 3.9037 - val_loss: 28.6368 - val_mean_absolute_error: 4.2265 Epoch 79/100 24/24 [==============================] - 0s 5ms/step - loss: 27.9652 - mean_absolute_error: 4.0877 - val_loss: 44.9156 - val_mean_absolute_error: 5.3097 Epoch 80/100 24/24 [==============================] - 0s 6ms/step - loss: 28.0543 - mean_absolute_error: 4.0745 - val_loss: 22.9045 - val_mean_absolute_error: 3.7758 Epoch 81/100 24/24 [==============================] - 0s 6ms/step - loss: 28.2708 - mean_absolute_error: 4.1408 - val_loss: 46.6391 - val_mean_absolute_error: 5.7242 Epoch 82/100 24/24 [==============================] - 0s 5ms/step - loss: 31.3436 - mean_absolute_error: 4.3788 - val_loss: 23.1505 - val_mean_absolute_error: 3.8523 Epoch 83/100 24/24 [==============================] - 0s 6ms/step - loss: 24.9986 - mean_absolute_error: 3.8784 - val_loss: 33.7528 - val_mean_absolute_error: 4.3467 Epoch 84/100 24/24 [==============================] - 0s 6ms/step - loss: 32.9308 - mean_absolute_error: 4.5280 - val_loss: 31.9002 - val_mean_absolute_error: 4.5682 Epoch 85/100 24/24 [==============================] - 0s 6ms/step - loss: 25.7413 - mean_absolute_error: 3.8218 - val_loss: 258.5181 - val_mean_absolute_error: 15.1648 Epoch 86/100 24/24 [==============================] - 0s 6ms/step - loss: 64.6340 - mean_absolute_error: 6.2498 - val_loss: 73.5435 - val_mean_absolute_error: 6.7066 Epoch 87/100 24/24 [==============================] - 0s 5ms/step - loss: 29.9883 - mean_absolute_error: 4.2062 - val_loss: 41.2897 - val_mean_absolute_error: 5.0119 Epoch 88/100 24/24 [==============================] - 0s 5ms/step - loss: 26.2929 - mean_absolute_error: 3.9575 - val_loss: 49.4074 - val_mean_absolute_error: 5.5488 Epoch 89/100 24/24 [==============================] - 0s 6ms/step - loss: 29.6033 - mean_absolute_error: 4.2211 - val_loss: 40.0240 - val_mean_absolute_error: 4.8799 Epoch 90/100 24/24 [==============================] - 0s 6ms/step - loss: 25.0577 - mean_absolute_error: 3.8291 - val_loss: 30.7329 - val_mean_absolute_error: 4.2625 Epoch 91/100 24/24 [==============================] - 0s 5ms/step - loss: 27.9640 - mean_absolute_error: 4.1603 - val_loss: 38.7160 - val_mean_absolute_error: 4.8258 Epoch 92/100 24/24 [==============================] - 0s 5ms/step - loss: 25.8501 - mean_absolute_error: 3.9570 - val_loss: 30.1615 - val_mean_absolute_error: 4.1986 Epoch 93/100 24/24 [==============================] - 0s 5ms/step - loss: 25.8615 - mean_absolute_error: 4.0211 - val_loss: 34.7884 - val_mean_absolute_error: 4.4977 Epoch 94/100 24/24 [==============================] - 0s 5ms/step - loss: 31.2621 - mean_absolute_error: 4.4461 - val_loss: 27.7025 - val_mean_absolute_error: 4.1202 Epoch 95/100 24/24 [==============================] - 0s 5ms/step - loss: 26.7086 - mean_absolute_error: 4.0049 - val_loss: 98.7044 - val_mean_absolute_error: 8.7104 Epoch 96/100 24/24 [==============================] - 0s 5ms/step - loss: 42.5731 - mean_absolute_error: 4.9649 - val_loss: 96.4132 - val_mean_absolute_error: 8.4731 Epoch 97/100 24/24 [==============================] - 0s 5ms/step - loss: 28.7466 - mean_absolute_error: 4.1438 - val_loss: 27.6218 - val_mean_absolute_error: 4.3021 Epoch 98/100 24/24 [==============================] - 0s 5ms/step - loss: 27.0661 - mean_absolute_error: 4.0125 - val_loss: 34.7287 - val_mean_absolute_error: 4.5324 Epoch 99/100 24/24 [==============================] - 0s 6ms/step - loss: 25.8701 - mean_absolute_error: 3.9764 - val_loss: 138.1102 - val_mean_absolute_error: 10.7745 Epoch 100/100 24/24 [==============================] - 0s 7ms/step - loss: 64.4138 - mean_absolute_error: 6.5826 - val_loss: 34.0510 - val_mean_absolute_error: 4.5269
Out[14]:
<keras.callbacks.History at 0x28d07e8eb20>
Visualize Results¶
In [15]:
Copied!
train_predictions = model.predict(X_train).flatten()
plt.figure(figsize=(12, 8), dpi=200)
plt.plot(dates_train, train_predictions)
plt.plot(dates_train, y_train)
plt.legend(['Training Predictions', 'Training Observations'])
train_predictions = model.predict(X_train).flatten()
plt.figure(figsize=(12, 8), dpi=200)
plt.plot(dates_train, train_predictions)
plt.plot(dates_train, y_train)
plt.legend(['Training Predictions', 'Training Observations'])
24/24 [==============================] - 0s 2ms/step
Out[15]:
<matplotlib.legend.Legend at 0x28d55408730>
In [16]:
Copied!
val_predictions = model.predict(X_val).flatten()
plt.figure(figsize=(12, 8), dpi=200)
plt.plot(dates_val, val_predictions)
plt.plot(dates_val, y_val)
plt.legend(['Validation Predictions', 'Validation Observations'])
val_predictions = model.predict(X_val).flatten()
plt.figure(figsize=(12, 8), dpi=200)
plt.plot(dates_val, val_predictions)
plt.plot(dates_val, y_val)
plt.legend(['Validation Predictions', 'Validation Observations'])
3/3 [==============================] - 0s 2ms/step
Out[16]:
<matplotlib.legend.Legend at 0x28d554c9d30>
In [17]:
Copied!
test_predictions = model.predict(X_test).flatten()
plt.figure(figsize=(12, 8), dpi=200)
plt.plot(dates_test, test_predictions)
plt.plot(dates_test, y_test)
plt.legend(['Testing Predictions', 'Testing Observations'])
test_predictions = model.predict(X_test).flatten()
plt.figure(figsize=(12, 8), dpi=200)
plt.plot(dates_test, test_predictions)
plt.plot(dates_test, y_test)
plt.legend(['Testing Predictions', 'Testing Observations'])
3/3 [==============================] - 0s 3ms/step
Out[17]:
<matplotlib.legend.Legend at 0x28d5568ef40>
In [18]:
Copied!
plt.figure(figsize=(12, 8), dpi=200)
plt.plot(dates_train, train_predictions)
plt.plot(dates_train, y_train)
plt.plot(dates_val, val_predictions)
plt.plot(dates_val, y_val)
plt.plot(dates_test, test_predictions)
plt.plot(dates_test, y_test)
plt.legend(['Training Predictions',
'Training Observations',
'Validation Predictions',
'Validation Observations',
'Testing Predictions',
'Testing Observations'])
plt.figure(figsize=(12, 8), dpi=200)
plt.plot(dates_train, train_predictions)
plt.plot(dates_train, y_train)
plt.plot(dates_val, val_predictions)
plt.plot(dates_val, y_val)
plt.plot(dates_test, test_predictions)
plt.plot(dates_test, y_test)
plt.legend(['Training Predictions',
'Training Observations',
'Validation Predictions',
'Validation Observations',
'Testing Predictions',
'Testing Observations'])
Out[18]:
<matplotlib.legend.Legend at 0x28d556ed940>
Make a recursive prediction¶
Use the predicted data as the input to forecast further result
In [19]:
Copied!
from copy import deepcopy
recursive_predictions = []
recursive_dates = np.concatenate([dates_val,dates_test])
## Pick the last windows to make prediction
last_window = deepcopy(X_train[-1])
for target_date in recursive_dates:
next_prediction = model.predict(np.array([last_window])).flatten()
recursive_predictions.append(next_prediction)
## update last window use predicted value
# break
last_window[:-1] = last_window[1:]
last_window[-1] = next_prediction
from copy import deepcopy
recursive_predictions = []
recursive_dates = np.concatenate([dates_val,dates_test])
## Pick the last windows to make prediction
last_window = deepcopy(X_train[-1])
for target_date in recursive_dates:
next_prediction = model.predict(np.array([last_window])).flatten()
recursive_predictions.append(next_prediction)
## update last window use predicted value
# break
last_window[:-1] = last_window[1:]
last_window[-1] = next_prediction
1/1 [==============================] - 0s 18ms/step
1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 19ms/step 1/1 [==============================] - 0s 19ms/step 1/1 [==============================] - 0s 20ms/step 1/1 [==============================] - 0s 19ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 19ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 19ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 19ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 19ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 19ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 19ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 19ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 18ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 17ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 16ms/step 1/1 [==============================] - 0s 17ms/step
In [20]:
Copied!
plt.figure(figsize=(12, 8), dpi=200)
plt.plot(recursive_dates, recursive_predictions)
plt.plot(recursive_dates, np.concatenate([y_val,y_test]))
plt.legend(['Recursive Predictions','Observation'])
plt.show()
plt.figure(figsize=(12, 8), dpi=200)
plt.plot(recursive_dates, recursive_predictions)
plt.plot(recursive_dates, np.concatenate([y_val,y_test]))
plt.legend(['Recursive Predictions','Observation'])
plt.show()