1. Data Preprocessing for Time Series #
LSTMs require a 3D tensor input formatted as (samples, timesteps, features)
. To handle this, you have to transform flat temperature columns into overlapping windows.
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
df = pd.read_csv("weather_data.csv")
data = df['Temperature'].values.reshape(-1, 1)
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_data = scaler.fit_transform(data)
X, y = [], []
for i in range(7, len(scaled_data)):
X.append(scaled_data[i-7:i])
y.append(scaled_data[i])
X, y = np.array(X), np.array(y)
print(f"Input shape: {X.shape}") # Output: (Samples, 7, 1)
Skipping the MinMaxScaler
is a common mistake; without it, LSTMs are highly susceptible to exploding gradients, which can crash your training process.
2. Model Architecture and Deployment #
I use a stacked LSTM approach with dropout to prevent overfitting. A critical technical detail here is the return_sequences=True
parameter on the first layer, which is mandatory when stacking LSTMs so the second layer receives the full sequence of hidden states.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout, Input
from tensorflow.keras.callbacks import EarlyStopping
model = Sequential([
Input(shape=(7, 1)),
LSTM(units=100, activation='relu', return_sequences=True),
Dropout(0.2),
LSTM(units=100, activation='relu'),
Dropout(0.2),
Dense(units=1)
])
model.compile(optimizer='adam', loss='mse')
early_stopping = EarlyStopping(
monitor='val_loss',
patience=10,
restore_best_weights=True
)
history = model.fit(
X, y,
epochs=50,
batch_size=32,
validation_split=0.2,
callbacks=[early_stopping]
)
3. Applying XAI Methods #
To move beyond the black box, we can use permutation importance. This method identifies which "lag day" the model values most by shuffling the data for a specific day and measuring the resulting spike in error.
from sklearn.metrics import mean_squared_error
base_preds = model.predict(X, verbose=0)
base_error = mean_squared_error(y, base_preds)
feature_importance = []
for i in range(7):
X_permuted = X.copy()
np.random.shuffle(X_permuted[:, i, 0]) # Shuffle a specific lag day
permuted_preds = model.predict(X_permuted, verbose=0)
permuted_error = mean_squared_error(y, permuted_preds)
feature_importance.append(permuted_error - base_error)
By calculating the difference between the permuted_error
and base_error
, you can pinpoint exactly which days in the 7-day window are driving the forecast. For a deeper dive into AI workflows, check out the resources at promptcube3.com.
Next Hardening AI-generated code for legacy systems: A practical guide →