-
Notifications
You must be signed in to change notification settings - Fork 1
/
fit_cnn_lstm.py
129 lines (113 loc) · 4.21 KB
/
fit_cnn_lstm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# Resources
import pandas as pd
import numpy as np
import tensorflow as tf
from tensorflow import keras
# Function definition
def fit_cnn_lstm(data, step, learning_rate, batch_size, epochs, patience,
recurrent_dropout, other_dropout):
# Unpack training and validation sets
x_train = data["x_train"]
y_train = data["y_train"]
x_val = data["x_val"]
y_val = data["y_val"]
# Since step = 1 (no downsampling), the sequence length is the same as the
# number of past steps (= 18)
sequence_length = int(r.past / step)
# Create dataset of sliding windows over training data
dataset_train = keras.preprocessing.timeseries_dataset_from_array(
x_train,
y_train,
sequence_length = sequence_length,
sampling_rate = step,
batch_size = batch_size)
# Create dataset of sliding windows over validation data
dataset_val = keras.preprocessing.timeseries_dataset_from_array(
x_val,
y_val,
sequence_length = sequence_length,
sampling_rate = step,
batch_size = batch_size)
# Get tensor shapes for input and targets. The output of model.summary()
# should match this.
for batch in dataset_train.take(1):
inputs, targets = batch
print("Input shape:", inputs.numpy().shape)
print("Target shape:", targets.numpy().shape)
# Define model
# NOTE: Missing TimeDistributed wrapper that's featured here:
# https://machinelearningmastery.com/timedistributed-layer-for-long-short-term-memory-networks-in-python/
inputs = keras.layers.Input(
shape = (inputs.shape[1], inputs.shape[2]))
x = keras.layers.Conv1D(
filters = 32,
kernel_size = 2,
activation = "relu",
padding = "same")(inputs)
x = keras.layers.MaxPooling1D(
pool_size = 2)(x)
x = keras.layers.Dropout(rate = other_dropout)(x)
x = keras.layers.Conv1D(
filters = 64,
kernel_size = 2,
activation = "relu",
padding = "same")(x)
x = keras.layers.MaxPooling1D(
pool_size = 2)(x)
x = keras.layers.Dropout(rate = other_dropout)(x)
x = keras.layers.Conv1D(
filters = 128,
kernel_size = 2,
activation = "relu",
padding = "same")(x)
x = keras.layers.MaxPooling1D(
pool_size = 2)(x)
x = keras.layers.Dropout(rate = other_dropout)(x)
x = keras.layers.LSTM(32,
return_sequences = True)(x)
x = keras.layers.LSTM(
units = 300,
recurrent_dropout = recurrent_dropout)(x)
outputs = keras.layers.Dense(1)(x)
model = keras.Model(inputs = inputs, outputs = outputs)
model.compile(
# Adam optimizer
optimizer = keras.optimizers.Adam(learning_rate = learning_rate),
# MAE loss
loss = keras.losses.MeanAbsoluteError())
model.summary()
# Checkpoint path
path_checkpoint = "model_checkpoint.h5"
# Early stopping checkpoint. Stop if no improvement on val_loss after
# *patience* epochs.
es_callback = keras.callbacks.EarlyStopping(
monitor = "val_loss",
min_delta = 0,
patience = patience)
# Checkpoint callback
modelckpt_callback = keras.callbacks.ModelCheckpoint(
monitor = "val_loss",
filepath = path_checkpoint,
save_weights_only = True,
save_best_only = True)
# Fit model & record learning stats in history
history = model.fit(
dataset_train,
epochs = epochs,
validation_data = dataset_val,
callbacks = [es_callback, modelckpt_callback])
# Get predictions for the validation set
pred_y = np.array([]).astype("float32")
for x, y in dataset_val.take(-1):
pred_y = np.concatenate((pred_y, model.predict(x).flatten()))
# Get actuals for validation set
# val_x = np.concatenate([x for x, y in dataset_val], axis = 0)
val_y = np.concatenate([y for x, y in dataset_val], axis = 0)
# Return history, actual and predicted validation set numbers
return(
{"preds": data["preds"],
"loss": np.array(history.history["loss"]),
"val_loss": np.array(history.history["val_loss"]),
"actual_y": np.array(val_y.flatten()),
"pred_y": pred_y}
)