Time Series Forecasting with TCN-BiLSTM for Univariate Data
Hybrid models combniing Temporal Convolutional Networks (TCN) and Bidirectional Long Short-Term Memory (BiLSTM) enhence forecasting accuracy by leveraging their cmoplementary strengths in capturing temporal dependencies. This approach is demonstrated through a Python implementation using Keras and TensorFlow for univariate time series prediction.
Data Loading and Preprocessing
Load the dataset and prepare it for modeling.
import pandas as pd
# Load the dataset
df = pd.read_csv('airline_passengers.csv')
# Convert the date column to datetime type
df['Date'] = pd.to_datetime(df['Date'])
# Set date as index
df.set_index('Date', inplace=True)
Dataset Splitting
Divide the data into training and testing subsets.
import matplotlib.pyplot as plt
# Split data into training and testing sets
train_split = int(len(df) * 0.8)
train_set = df[:train_split]
test_set = df[train_split:]
# Visualize the split
plt.figure(figsize=(12, 6))
plt.plot(train_set, label='Training Set')
plt.plot(test_set, label='Testing Set')
plt.xlabel('Time')
plt.ylabel('Passenger Count')
plt.title('Airline Passenger Data Split')
plt.legend()
plt.show()
Data Normalization
Scale the data to a range between 0 and 1.
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
train_scaled = scaler.fit_transform(train_set.values.reshape(-1, 1))
test_scaled = scaler.transform(test_set.values.reshape(-1, 1))
Dataset Construction
Create sliding window datasets for model input.
def generate_sequences(data, seq_len=1):
X, y = [], []
for i in range(len(data) - seq_len):
X.append(data[i:i + seq_len])
y.append(data[i + seq_len])
return np.array(X), np.array(y)
import numpy as np
window_length = 3
X_train, y_train = generate_sequences(train_scaled, window_length)
X_test, y_test = generate_sequences(test_scaled, window_length)
Model Building and Training
Construct and train the TCN-BiLSTM hybrid model.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Input, Dense, Bidirectional, LSTM
from tcn import TCN
# Define the model
model = Sequential()
model.add(Input(shape=(window_length, 1)))
model.add(TCN(nb_filters=30, kernel_size=3, return_sequences=True, dilations=[1, 2, 4]))
model.add(Bidirectional(LSTM(50, return_sequences=True)))
model.add(Bidirectional(LSTM(50)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
model.summary()
# Train the model
model.fit(X_train, y_train, epochs=50, batch_size=16, verbose=1)
Model Prediction
Generate predictions on training and testing data.
train_pred = model.predict(X_train)
test_pred = model.predict(X_test)
Results Visualizaiton
Plot the predictions against actual values.
# Inverse transform predictions to original scale
train_pred_inv = scaler.inverse_transform(train_pred)
test_pred_inv = scaler.inverse_transform(test_pred)
# Plot testing set predictions
plt.figure(figsize=(12, 6))
plt.plot(test_set.index, test_set.values, label='Actual Values')
plt.plot(test_set.index[window_length:], test_pred_inv, label='Predicted Values', linestyle='--')
plt.xlabel('Date')
plt.ylabel('Passenger Count')
plt.title('Testing Set: Actual vs Predicted')
plt.legend()
plt.show()
# Plot full dataset with predictions
plt.figure(figsize=(12, 6))
plt.plot(df.index, df.values, label='Full Dataset')
plt.plot(train_set.index[window_length:], train_pred_inv, label='Training Predictions', linestyle=':')
plt.plot(test_set.index[window_length:], test_pred_inv, label='Testing Predictions', linestyle='--')
plt.xlabel('Date')
plt.ylabel('Passenger Count')
plt.title('Complete Dataset with Predictions')
plt.legend()
plt.show()