Mathew K Analytics

Lesson 36 · Python For Time Series

Understanding Convolutional Neural Networks for Time Series Analysis in Christian Data Studies

Welcome! In this lesson, you will learn how to use Convolutional Neural Networks (CNN) to analyze time series data. You do not need any experience with deep…

⬇ Download notebookOpen in Colab ↗

What you'll learn

Data

No separate download needed — the notebook creates or downloads everything it uses.

📓 Full notebook

Download .ipynb
 

Convolutional Neural Networks (CNN) for Time Series#

Welcome! In this lesson, you will learn how to use Convolutional Neural Networks (CNN) to analyze time series data.

You do not need any experience with deep learning to begin. We will start with basics and build step by step.

Let us get started!

What is a Time Series?#

A time series is a list of values measured in order by time. For example, temperatures each day or sales every month.

CNNs can help you find patterns in these sequences.

import warnings; warnings.filterwarnings("ignore")
# Let us load some basic helper modules
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

Data setup#

We will use monthly airline passenger data for this lesson. This data shows how many people flew each month for several years.

# Download and load the airline passengers dataset
url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/airline-passengers.csv"
df = pd.read_csv(url, parse_dates=["Month"])
print("Data shape:", df.shape)
df.head()
Data shape: (144, 2)
Month Passengers
0 1949-01-01 112
1 1949-02-01 118
2 1949-03-01 132
3 1949-04-01 129
4 1949-05-01 121
# Show the time series as a line chart
plt.figure(figsize=(8,4))
plt.plot(df["Month"], df["Passengers"])
plt.title("Monthly Airline Passengers")
plt.xlabel("Month")
plt.ylabel("Passengers")
plt.show()
No description has been provided for this image

What is a Convolutional Neural Network (CNN)?#

CNNs are smart computer models that can find patterns in data that happens in order, such as pictures or time series.

In time series, they can notice trends or spikes, much like how a person might spot a busy or slow month.

# Let us prepare the data as numbers for machine learning
series = df["Passengers"].values.astype(np.float32)
print(series[:10])
[112. 118. 132. 129. 121. 135. 148. 148. 136. 119.]
# Normalize (scale) the data to 0-1 range
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
series_scaled = scaler.fit_transform(series.reshape(-1,1)).flatten()
print(series_scaled[:10])
[0.01544401 0.02702703 0.05405405 0.04826255 0.03281853 0.05984557
 0.08494207 0.08494207 0.06177607 0.02895753]
# Split into training and test sets
split = int(len(series_scaled) * 0.8)
train, test = series_scaled[:split], series_scaled[split:]
print(f"Train size: {len(train)}  Test size: {len(test)}")
Train size: 115  Test size: 29
# Create features and labels for supervised learning
def make_windows(series, window_size):
    windows = []
    labels = []
    for i in range(len(series) - window_size):
        windows.append(series[i:i+window_size])
        labels.append(series[i+window_size])
    return np.array(windows), np.array(labels)

window_size = 12  # 12 months = 1 year
X_train, y_train = make_windows(train, window_size)
X_test, y_test = make_windows(test, window_size)
print("Train window shape:", X_train.shape)
Train window shape: (103, 12)

Building a Simple 1D CNN Model#

We will use the Keras library to build our model. Keras makes creating neural networks simple, even for beginners.

Let us get started by importing what we need.

# Import TensorFlow and Keras layers
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
# Prepare training data shape for CNN: (samples, steps, features)
X_train_cnn = X_train[..., np.newaxis]
X_test_cnn = X_test[..., np.newaxis]
print("CNN input shape:", X_train_cnn.shape)
CNN input shape: (103, 12, 1)
# Build a simple 1D CNN
model = keras.Sequential([
    layers.Conv1D(32, kernel_size=3, activation="relu", input_shape=(window_size, 1)),
    layers.MaxPooling1D(pool_size=2),
    layers.Flatten(),
    layers.Dense(32, activation="relu"),
    layers.Dense(1)
])
model.compile(optimizer="adam", loss="mse")
model.summary()
Model: "sequential"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Layer (type)                    ┃ Output Shape           ┃       Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ conv1d (Conv1D)                 │ (None, 10, 32)         │           128 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ max_pooling1d (MaxPooling1D)    │ (None, 5, 32)          │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ flatten (Flatten)               │ (None, 160)            │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense (Dense)                   │ (None, 32)             │         5,152 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_1 (Dense)                 │ (None, 1)              │            33 │
└─────────────────────────────────┴────────────────────────┴───────────────┘
 Total params: 5,313 (20.75 KB)
 Trainable params: 5,313 (20.75 KB)
 Non-trainable params: 0 (0.00 B)
# Train the CNN model
history = model.fit(X_train_cnn, y_train, epochs=40, batch_size=8, validation_data=(X_test_cnn, y_test), verbose=0)
print("Training complete.")
Training complete.
# Plot the training history
plt.plot(history.history["loss"], label="Train Loss")
plt.plot(history.history["val_loss"], label="Val Loss")
plt.title("Training Loss over Epochs")
plt.xlabel("Epoch")
plt.ylabel("Loss (MSE)")
plt.legend()
plt.show()
No description has been provided for this image
# Make predictions using the trained model
preds = model.predict(X_test_cnn).flatten()
# Reverse scaling to get back to the real passenger numbers
y_test_real = scaler.inverse_transform(y_test.reshape(-1,1)).flatten()
preds_real = scaler.inverse_transform(preds.reshape(-1,1)).flatten()

# Plot predictions vs actual values
plt.figure(figsize=(8,4))
plt.plot(y_test_real, label="Actual")
plt.plot(preds_real, label="Predicted")
plt.title("CNN Predictions vs Actual Passengers")
plt.xlabel("Time Step")
plt.ylabel("Passengers")
plt.legend()
plt.show()
1/1 ━━━━━━━━━━━━━━━━━━━━ 0s 87ms/step
No description has been provided for this image
# Calculate how good our model is (Mean Squared Error)
from sklearn.metrics import mean_squared_error
mse = mean_squared_error(y_test_real, preds_real)
print(f"Mean Squared Error on Test Data: {mse:.2f}")
Mean Squared Error on Test Data: 841.98

Extra: Try Your Own Data!#

Can you load a different time series dataset from the list below and repeat the steps?

  • Daily Minimum Temperatures (weather)
  • Shampoo Sales (retail forecasting)
  • CO Concentrations (climate change)
# Best practices: Avoid overfitting with Dropout layers
model2 = keras.Sequential([
    layers.Conv1D(32, kernel_size=3, activation="relu", input_shape=(window_size, 1)),
    layers.MaxPooling1D(pool_size=2),
    layers.Dropout(0.2),
    layers.Flatten(),
    layers.Dense(32, activation="relu"),
    layers.Dropout(0.2),
    layers.Dense(1)
])
model2.compile(optimizer="adam", loss="mse")
model2.summary()
Model: "sequential_1"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Layer (type)                    ┃ Output Shape           ┃       Param # ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ conv1d_1 (Conv1D)               │ (None, 10, 32)         │           128 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ max_pooling1d_1 (MaxPooling1D)  │ (None, 5, 32)          │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dropout (Dropout)               │ (None, 5, 32)          │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ flatten_1 (Flatten)             │ (None, 160)            │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_2 (Dense)                 │ (None, 32)             │         5,152 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dropout_1 (Dropout)             │ (None, 32)             │             0 │
├─────────────────────────────────┼────────────────────────┼───────────────┤
│ dense_3 (Dense)                 │ (None, 1)              │            33 │
└─────────────────────────────────┴────────────────────────┴───────────────┘
 Total params: 5,313 (20.75 KB)
 Trainable params: 5,313 (20.75 KB)
 Non-trainable params: 0 (0.00 B)
# Troubleshooting: If you get errors about input shapes, print your data shapes.
print("X_train_cnn shape:", X_train_cnn.shape)
print("y_train shape:", y_train.shape)
X_train_cnn shape: (103, 12, 1)
y_train shape: (103,)
# Tip: Use input() to ask the user for the window size.
user_window = input("Enter the number of months to use for each window (example: 12): ")
user_window = int(user_window)
X_train2, y_train2 = make_windows(train, user_window)
print(f"New shape: {X_train2.shape}")
New shape: (109, 6)
 

Challenge Exercise#

Try changing the CNN model's layers or number of filters. See how your results improve or change.

Can you beat your first model?

Recap: CNNs for Time Series#

  • You learned what a time series is.
  • You prepared data for a CNN.
  • You built, trained, and tested a simple 1D CNN.
  • You saw how to improve and troubleshoot your model.

Practice on new datasets and try different CNN shapes as you gain confidence!

Thank you for learning with us!#

If you found this lesson helpful, please like and subscribe to our channel for more tutorials.

What would you like to learn next? Leave your ideas in the comments!

Found this useful?

All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.