# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3.6
#     language: python
#     name: py36
# ---

# ## Rolling Windows
# <img src="./Figs/20.jpg" alt="Drawing" style="width: 500px;"/>
# <img src="./Figs/21.jpg" alt="Drawing" style="width: 500px;"/>
# <img src="./Figs/22.jpg" alt="Drawing" style="width: 500px;"/>
#
# ### How to fit
# - Fit whole window as many-to-one into RNN
# <img src="./Figs/23.jpg" alt="Drawing" style="width: 200px;"/>
#
# - Fit whole window as one-to-one into CNN or Fully-Connected
# <img src="./Figs/24.jpg" alt="Drawing" style="width: 200px;"/>

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from IPython.display import display

# # Dataset

df = pd.read_csv(
    'cansim-0800020-eng-6674700030567901031.csv',
    skiprows=6, skipfooter=9, engine='python')
df.head()

# ### Adjust date

# +
from pandas.tseries.offsets import MonthEnd

df['Adjustments'] = pd.to_datetime(df['Adjustments']) + MonthEnd(1)
df = df.set_index('Adjustments')

display(df.head())
display(df.plot())
# -

# ### Split train-testset

# +
split_date = pd.Timestamp('01-01-2011')

train = df.loc[:split_date, ['Unadjusted']]
test = df.loc[split_date:, ['Unadjusted']]
# -

ax = train.plot();
test.plot(ax=ax)
plt.legend(['train', 'test']);

# #### MinMax Scaling input

# +
from sklearn.preprocessing import MinMaxScaler

sc = MinMaxScaler()

train_sc = sc.fit_transform(train)
test_sc = sc.transform(test)
# -

ax = pd.DataFrame(train_sc).plot();
pd.DataFrame(test_sc).plot(ax=ax)
plt.legend(['train', 'test']);

# #### Create Sliding Windows

# +
train_sc_df = pd.DataFrame(train_sc, columns=['MinMax_Scaled'], index=train.index)
test_sc_df = pd.DataFrame(test_sc, columns=['MinMax_Scaled'], index=test.index)

train_sc_df.head()

# +
for s in range(1, 13):
    train_sc_df['shift_{}'.format(s)] = train_sc_df['MinMax_Scaled'].shift(s)
    test_sc_df['shift_{}'.format(s)] = test_sc_df['MinMax_Scaled'].shift(s)
    
train_sc_df.head(13)
# -

# #### Define train-testset 

# +
X_train = train_sc_df.dropna().drop('MinMax_Scaled', axis=1)
y_train = train_sc_df.dropna()[['MinMax_Scaled']]

X_test = test_sc_df.dropna().drop('MinMax_Scaled', axis=1)
y_test = test_sc_df.dropna()[['MinMax_Scaled']]

display(X_train.head())
display(y_train.head())

# +
X_train = X_train.values
X_test= X_test.values

y_train = y_train.values
y_test = y_test.values

print(X_train.shape)
print(y_train.shape)
print('')
print(X_test.shape)
print(y_test.shape)
# -

# # Model

# ## Fully connected on Windows

# +
from keras.models import Sequential
from keras.layers import Dense
import keras.backend as K
from keras.callbacks import EarlyStopping

K.clear_session()

model = Sequential()

model.add(Dense(12, input_dim=12, activation='relu'))
model.add(Dense(1))

model.compile(loss='mean_squared_error', optimizer='adam')
model.summary()
# -

early_stop = EarlyStopping(monitor='loss', patience=3, verbose=1)

history = model.fit(
    X_train, y_train,
    epochs=200,batch_size=1,
    validation_split=0.25,
    verbose=0, callbacks=[early_stop])

historydf = pd.DataFrame(history.history, index=history.epoch)
historydf.plot();

# #### Evaluate

y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)

# +
from sklearn.metrics import mean_squared_error as mse

print("The Mean Squared Error on the Train set is:\t{:0.5f}".format(mse(y_train, y_train_pred)))
print("The Mean Squared Error on the Test set is:\t{:0.5f}".format(mse(y_test, y_test_pred)))

# +
from sklearn.metrics import r2_score

print("The R2 score on the Train set is:\t{:0.3f}".format(r2_score(y_train, y_train_pred)))
print("The R2 score on the Test set is:\t{:0.3f}".format(r2_score(y_test, y_test_pred)))
# -

plt.plot(y_test)
plt.plot(y_test_pred)
plt.legend(['real vals', 'predicted']);

# ## LSTM on Windows

# +
# Convert to tensor: (batch_size, timesteps, input_dim)
X_train_t = X_train.reshape(X_train.shape[0], 1, 12)
X_test_t = X_test.reshape(X_test.shape[0], 1, 12)

print(X_train_t.shape)
print(X_test_t.shape)

# +
from keras.models import Sequential
import keras.backend as K
from keras.layers import LSTM, Dense
from keras.callbacks import EarlyStopping

K.clear_session()

model = Sequential()

model.add(LSTM(6, input_shape=(1, 12)))
model.add(Dense(1))

model.compile(loss='mean_squared_error', optimizer='adam')
model.summary()
# -

early_stop = EarlyStopping(monitor='loss', patience=3, verbose=1)

history = model.fit(
    X_train_t, y_train,
    epochs=100, batch_size=1, verbose=0,
    validation_split=0.25,
    callbacks=[early_stop])

historydf = pd.DataFrame(history.history, index=history.epoch)
historydf.plot();

# #### Evaluate

y_train_pred = model.predict(X_train_t)
y_test_pred = model.predict(X_test_t)

# +
from sklearn.metrics import mean_squared_error as mse

print("The Mean Squared Error on the Train set is:\t{:0.5f}".format(mse(y_train, y_train_pred)))
print("The Mean Squared Error on the Test set is:\t{:0.5f}".format(mse(y_test, y_test_pred)))

# +
from sklearn.metrics import r2_score

print("The R2 score on the Train set is:\t{:0.3f}".format(r2_score(y_train, y_train_pred)))
print("The R2 score on the Test set is:\t{:0.3f}".format(r2_score(y_test, y_test_pred)))
# -

plt.plot(y_test)
plt.plot(y_test_pred)
plt.legend(['real vals', 'predicted']);

# ## => The models are extremely good

StarcoderdataJupyterScriptsDedupFiltered