I have built a LSTM model that works well on my test and validation set in Keras; however, when I try to use it to predict values where my two target variables are NaN, the model is unable to predict. Now, I am worried that the modeling process will be all for nothing. I will put my code here, and I have mostly referred to the guide on the tensorflow website. This is my first tensorflow model, so I apologize if this is simple but I can't seem to predict any values and I don't really know how to go about formatting it to make it predictable similar to how it was easy to do for the validation and then use those predictions for input to compute farther back because I only have 3 years of train data, but 40 years that need to be backcasted.
I believe the problem is that right now I have data in the form (batch size, inputs) and I need it in the form (batch size, time steps looking back, inputs), but I can't figure out the way to make this possible
Creating data:
df.rename(columns = {'Unnamed: 0':'date'}, inplace = True)
true_test = df[pd.isnull(df['Return'])]
df=df[pd.isnull(df['Return'])==False]
Window Generator Class:
class WindowGenerator():
def __init__(self, input_width, label_width, shift,
train_df=train_df, val_df=val_df, test_df=test_df,
label_columns=None):
# Store the raw data.
self.train_df = train_df
self.val_df = val_df
self.test_df = test_df
# Work out the label column indices.
self.label_columns = label_columns
if label_columns is not None:
self.label_columns_indices = {name: i for i, name in
enumerate(label_columns)}
self.column_indices = {name: i for i, name in
enumerate(train_df.columns)}
# Work out the window parameters.
self.input_width = input_width
self.label_width = label_width
self.shift = shift
self.total_window_size = input_width + shift
self.input_slice = slice(0, input_width)
self.input_indices = np.arange(self.total_window_size)[self.input_slice]
self.label_start = self.total_window_size - self.label_width
self.labels_slice = slice(self.label_start, None)
self.label_indices = np.arange(self.total_window_size)[self.labels_slice]
def __repr__(self):
return '\n'.join([
f'Total window size: {self.total_window_size}',
f'Input indices: {self.input_indices}',
f'Label indices: {self.label_indices}',
f'Label column name(s): {self.label_columns}'])
def split_window(self, features):
inputs = features[:, self.input_slice, :]
labels = features[:, self.labels_slice, :]
if self.label_columns is not None:
labels = tf.stack(
[labels[:, :, self.column_indices[name]] for name in self.label_columns],
axis=-1)
# Slicing doesn't preserve static shape information, so set the shapes
# manually. This way the `tf.data.Datasets` are easier to inspect.
inputs.set_shape([None, self.input_width, None])
labels.set_shape([None, self.label_width, None])
return inputs, labels
def make_dataset(self, data):
data = np.array(data, dtype=np.float32)
ds = tf.keras.utils.timeseries_dataset_from_array(
data=data,
targets=None,
sequence_length=self.total_window_size,
sequence_stride=1,
shuffle=True,
batch_size=32,)
ds = ds.map(self.split_window)
return ds
WindowGenerator.make_dataset = make_dataset
def plot(self, model=None, plot_col=['Return','Supply'], max_subplots=3):
if isinstance(plot_col, list):
self.plot(model = model, plot_col = 'Return')
self.plot(model = model, plot_col = 'Supply')
return None
inputs, labels = self.example
plt.figure(figsize=(12, 8), dpi=300)
plot_col_index = self.column_indices[plot_col]
max_n = min(max_subplots, len(inputs))
for n in range(max_n):
print("somthing plz \n\n\n\n")
plt.subplot(max_n, 1, n+1)
plt.ylabel(f'{plot_col} [normed]')
plt.plot(self.input_indices, inputs[n, :, plot_col_index],
label='Inputs', marker='.', zorder=-10)
if self.label_columns:
label_col_index = self.label_columns_indices.get(plot_col, None)
else:
label_col_index = plot_col_index
if label_col_index is None:
continue
plt.scatter(self.label_indices, labels[n, :, label_col_index],
edgecolors='k', label='Labels', c='#2ca02c', s=64)
if model is not None:
if plot_col == 'Return':
plt.scatter(self.label_indices, predictions[n, :, 0],
marker='X', edgecolors='k', label='Predictions',
c='#ff7f0e', s=64)
elif plot_col == 'Supply':
plt.scatter(self.label_indices, predictions[n, :, 1],
marker='X', edgecolors='k', label='Predictions',
c='#ff7f0e', s=64)
else:
plt.scatter(self.label_indices, predictions[n, :, label_col_index],
marker='X', edgecolors='k', label='Predictions',
c='#ff7f0e', s=64)
if n == 0:
plt.legend()
plt.xlabel('Time [h]')
WindowGenerator.plot = plot
Compile and Fit Function:
def compile_and_fit(model, window, patience=2):
early_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_loss',
patience=patience,
mode='min')
model.compile(loss=tf.keras.losses.MeanAbsoluteError(),
optimizer=tf.keras.optimizers.Adam(),
metrics=[tf.keras.metrics.MeanAbsoluteError(), coeff_determination])
history = model.fit(window.train, epochs=MAX_EPOCHS,
validation_data=window.val,
callbacks=[early_stopping])
return history
Fitting Model:
wide_window = WindowGenerator(
input_width=24, label_width=24, shift=1,
label_columns=['Return', 'Supply'])
## RNN: LSTM
n_steps = 24
n_features = 10
lstm_model = tf.keras.models.Sequential([
# Shape [batch, time, features] => [batch, time, lstm_units]
tf.keras.layers.LSTM(32, return_sequences = True, input_shape=(n_steps, n_features)),
tf.keras.layers.LSTM(16, return_sequences = True),
tf.keras.layers.LSTM(4, return_sequences = True),
# Shape => [batch, time, features]
tf.keras.layers.Dense(units=2)
])
val_performance['LSTM_SR'] = lstm_model.evaluate(wide_window.val)
performance['LSTM_SR'] = lstm_model.evaluate(wide_window.test, verbose=0)
Trying to test:
## Tried no expansion, axis = 1, and axis = 0, this one seems the closest
true_test2 = np.expand_dims(true_test, axis=1)
lstm_model.predict(true_test2, verbose = 2)
Error from above call:
ValueError Traceback (most recent call last)
path in <cell line:
5>()
----> 545 lstm_model.predict(true_test2, verbose = 2)
File ~/lib/python3.9/site-
packages/keras/utils/traceback_utils.py:67, in filter_traceback.
<locals>.error_handler(*args, **kwargs)
65 except Exception as e: # pylint: disable=broad-except
66 filtered_tb = _process_traceback_frames(e.__traceback__)
---> 67 raise e.with_traceback(filtered_tb) from None
68 finally:
69 del filtered_tb
File ~/lib/python3.9/site-
packages/keras/engine/input_spec.py:264, in assert_input_compatibility(input_spec,
inputs, layer_name)
262 if spec_dim is not None and dim is not None:
263 if spec_dim != dim:
--> 264 raise ValueError(f'Input {input_index} of layer "{layer_name}" is '
265 'incompatible with the layer: '
266 f'expected shape={spec.shape}, '
267 f'found shape={display_shape(x.shape)}')
ValueError: Input 0 of layer "sequential_21" is incompatible with the layer: expected
shape=(None, 24, 10), found shape=(32, 1, 10)
Error with Just true_test:
ValueError: Input 0 of layer "sequential_23" is incompatible with
the layer: expected shape=(None, 24, 10), found shape=(32, 10)