Using the watsonx.ai Time Series Forecasting API to predict energy demand

Confident Female Data Scientist Works Closely to her Young Colleague in Big Control

Author

Meredith Syed

AI Developer Advocate Lead

Nisarg Patel

Product Manager, watsonx.ai

IBM

Aleksandra Kłeczek

Software Developer

IBM

IBM watsonx.ai Timeseries Forecasting API and SDK

We are pleased to announce that the IBM® watsonx.ai™ Timeseries Forecasting API and SDK is available to the public in GA from February 2025. Built on the IBM Granite™ timeseries models, this new API/SDK offers unparalleled accuracy and ease of use for tackling real-world forecasting challenges. At the core of this capability is the IBM Granite timeseries models (TinyTimeMixers), a family of open source pretrained, lightweight models based on a novel architecture.

Granite timeseries models are designed to:

  • Adapt to diverse datasets: Whether it’s IoT sensor data, stock market prices or energy demand, Granite dynamically adjusts to data irregularities, seasonality and trends, allowing for zero-shot forecasting.
  • Deliver state-of-the-art accuracy: Granite timeseries models outperform many larger timeseries models including TimesFM, Moirai, Chronos and more that are 10x the size on various industry benchmarks, while being computationally efficient.
  • Support scalability: From small-scale business needs to enterprise-grade implementations, the models handle forecasting at any scale.

These models are trained on a collection of publicly available datasets that permit commercial use. A total of 700 million timepoints were used from selected datasets from the Monash Forecasting Repository and the LOTSA collection. Granite timeseries models currently support multiple input context lengths (512, 1024 and 1536 data points), and are capable of multivariate predictions across a number of channels and IDs. For more information about use cases and training details, see the model card and the IBM Research® paper.

By launching the IBM watsonx.ai Timeseries Forecasting API and SDK, IBM reaffirms its commitment to providing developers with the tools they need to build impactful AI solutions. This new capability enhances IBM watsonx.ai, an enterprise-grade AI developer studio, enabling clients to develop AI and ML solutions with tools for agent development, fine-tuning, RAG, guardrails and more.

Steps

Step 1. Set up your environment

While you can choose from several tools, this tutorial walks you through how to set up an IBM account to use a Jupyter Notebook.

  1. Log in to watsonx.ai by using your IBM Cloud® account.

  2. Create a watsonx.ai project.

    You can get your project ID from within your project. Click the Manage tab. Then, copy the project ID from the Details section of the General page. You need this ID for this tutorial.

  3. Create a Jupyter Notebook.

This step opens a Jupyter Notebook environment where you can copy the code from this tutorial. Alternatively, you can download this notebook to your local system and upload it to your watsonx.ai project as an asset. To view more Granite tutorials, check out the IBM Granite Community. This Jupyter Notebook can be found on GitHub.

Step 2. Set up a watsonx.ai Runtime instance and API key

  1. Create a watsonx.ai service instance (select your appropriate region and choose the Lite plan, which is a free instance).
  2. Generate an application programming interface (API) key.
  3. Associate the watsonx.ai Runtime service instance to the project that you created in watsonx.ai.

Step 3. Install and import relevant libraries and set up your credentials

We need a few libraries and modules for this tutorial. Make sure to import the following ones and if they're not installed, a quick pip installation resolves the problem.

We'll use the libraries os and getpass to set up our credentials. To load the dataset, we'll use the libraries wget and pandas. For data visualization, we'll use the libraries numpy and matplotlib.

In addition to common Python libraries, we'll be using the ibm-watsonx-ai library that allows you to work with IBM watsonx.ai services. You can train, store and deploy your models, score them using APIs, and finally integrate them with your application development. We'll use the Credentials and APIClient functionality from this library to connect to watsonx.ai services.

For timeseries capabilities, we're using new functionality from the classes TSModelInference and TSForecastParameters to define the model and set parameters for forecasting. In order to evaluate the performance of the model, we'll use the Mean Absolute Percentage Error (MAPE) metric from the sklearn library.

*Note, this tutorial was built using Python 3.11*

#installations
%pip install wget | tail -n 1
%pip install -U matplotlib | tail -n 1
%pip install -U ibm-watsonx-ai | tail -n 1
#imports
import os
import getpass
import wget
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import mean_absolute_percentage_error

from ibm_watsonx_ai import Credentials
from ibm_watsonx_ai import APIClient
from ibm_watsonx_ai.foundation_models import TSModelInference
from ibm_watsonx_ai.foundation_models.schema import TSForecastParameters

To set our credentials, we need the WATSONX_APIKEY and WATSONX_PROJECT_ID you generated in step 1. We will also set the URL serving as the API endpoint.

If you're not sure of the URL, you can use these commands in the IBM Cloud CLI to retrieve the instance location:

    ibmcloud login --apikey API_KEY -a https://cloud.ibm.com
    ibmcloud resource service-instance INSTANCE_NAME

WATSONX_APIKEY = getpass.getpass("Please enter your watsonx.ai Runtime API key (hit enter): ")
WATSONX_PROJECT_ID = getpass.getpass("Please enter your project ID (hit enter): ")
URL = "https://us-south.ml.cloud.ibm.com"

We can use the Credentials class to encapsulate our passed credentials.

credentials = Credentials(
url=URL,
api_key=WATSONX_APIKEY
)

To be able to interact with all resources available in watsonx.ai Runtime, you need to set the project that you will be using via the WATSONX_PROJECT_ID.

client = APIClient(credentials)
client.set.default_project(WATSONX_PROJECT_ID)

Step 4. Load and prepare the dataset

This tutorial uses the Hourly energy demand dataset. This dataset contains 4 years of electrical consumption and energy generation data gathered in Spain from 2015–2018 aggregated by hour. It is a modified version of the Hourly energy demand generation and weather dataset. You can find more details about the dataset, including metadata in the preceding links.

For simplicity, the dataset was prepared to have no missing values and to remove irrelevant columns.

filename = 'energy_dataset.csv'
base_url = 'https://github.com/IBM/watson-machine-learning-samples/raw/refs/heads/master/cloud/data/energy/'
if not os.path.isfile(filename): wget.download(base_url + filename)

Let's examine the last few rows of the dataset. We can see the time column showing a timestamp for each hour. Other columns show numeric data types for energy generation from different sources, weather forecast details and actual energy usage, termed as total_load_actual. This will be our target column, the column for which we are trying to predict values. Since our model is performing multivariate forecasting, we'll use all of the other columns as input to our model to help inform it's predictions. These columns provide details about energy generation and weather forecasts for each hour, enabling us to predict actual energy demand on an hourly basis.

df = pd.read_csv(filename)
df.tail()

 

Split the data

 

For our forecasting problem, we'll need to split the data into 2 sets, the first which will be used as historical data. We'll provide the historical data to the model and ask it to predict future values. In order to test the accuracy of our predictions, we'll also need to compare these predictions against ground truth values. For our experiment, we'll use a second subset of our dataset as the ground truth and we'll compare the predicted values to the actual values in this ground truth subset.

Granite timeseries models come in different context lengths of 512, 1024 and 1536 tokens. The context length describes the amount of information the model can consider when making a single prediction. For the Granite timeseries models, each row in a dataset counts as one token towards the context length. We'll be using the 512 token context length timeseries model, ibm/granite-ttm-512-96-r2, in our experiment. In order to do this, we need a dataset of 512 rows to provide as input to the model, our historical data. We'll term this input dataset as data. We have many more rows in our dataset than are needed for this prediction problem. In this case, to subset the data, we'll simply take the most recent timestamps or the last rows of the dataset.

The second dataset we need is our evaluation or ground truth dataset. We'll use the last 96 rows of data in our dataset for this purpose. We'll call this future_context and we'll use this data to compare against our predictions.

Here, we also specify the columns to be used for prediction. The identifiers timestamp_column and target_column set these values for the model.

# how many rows and columns
df.shape

Output: 

(35064, 19)

timestamp_column = "time"
target_column = "total load actual"
context_length = 512
future_context = 96
# use the last `context_length` rows for prediction.
future_data = df.iloc[-future_context:,]
data = df.iloc[-(context_length + future_context):-future_context,]

Let's examine the data further with this data visualization, which plots the hourly timestamps against our target column, total load actual.

plt.figure(figsize=(10,2))
plt.plot(np.asarray(data[timestamp_column], 'datetime64[s]'), data[target_column])
plt.title("Actual Total Load")
plt.show()

 

In preparing data for timeseries forecasting, models can have different requirements for preprocessing the data. The Granite TTM model card recommends that data be scaled and a preprocessing script is provided as an example. For the purposes of this tutorial, we'll use our dataset 'as-is.'

timeseries energy demand plot

Step 5. Select a Granite Timeseries Foundation Model from watsonx.ai

Using the get_time_series_model_specs function from the watsonx.ai SDK, we can list the models available from the Timeseries Forecasting API. For this experiment, we'll use the 512 context length model, but we see that the larger context models are also available.

for model in client.foundation_models.get_time_series_model_specs()["resources"]:
print('--------------------------------------------------')
print(f'model_id: {model["model_id"]}')
print(f'functions: {model["functions"]}')
print(f'long_description: {model["long_description"]}')
print(f'label: {model["label"]}')

Output: 

--------------------------------------------------
model_id: ibm/granite-ttm-1024-96-r2
functions: [{'id': 'time_series_forecast'}]
long_description: TinyTimeMixers (TTMs) are compact pre-trained models for Multivariate Time-Series Forecasting, open-sourced by IBM Research. Given the last 1024 time-points (i.e. context length), this model can forecast up to next 96 time-points (i.e. forecast length) in future. This model is targeted towards a forecasting setting of context length 1024 and forecast length 96 and recommended for hourly and minutely resolutions (Ex. 10 min, 15 min, 1 hour, etc)
label: granite-ttm-1024-96-r2
--------------------------------------------------
model_id: ibm/granite-ttm-1536-96-r2
functions: [{'id': 'time_series_forecast'}]
long_description: TinyTimeMixers (TTMs) are compact pre-trained models for Multivariate Time-Series Forecasting, open-sourced by IBM Research. Given the last 1536 time-points (i.e. context length), this model can forecast up to next 96 time-points (i.e. forecast length) in future. This model is targeted towards a forecasting setting of context length 1536 and forecast length 96 and recommended for hourly and minutely resolutions (Ex. 10 min, 15 min, 1 hour, etc)
label: granite-ttm-1536-96-r2
--------------------------------------------------
model_id: ibm/granite-ttm-512-96-r2
functions: [{'id': 'time_series_forecast'}]
long_description: TinyTimeMixers (TTMs) are compact pre-trained models for Multivariate Time-Series Forecasting, open-sourced by IBM Research. Given the last 512 time-points (i.e. context length), this model can forecast up to next 96 time-points (i.e. forecast length) in future. This model is targeted towards a forecasting setting of context length 512 and forecast length 96 and recommended for hourly and minutely resolutions (Ex. 10 min, 15 min, 1 hour, etc)
label: granite-ttm-512-96-r2

We need to specify the model_id that will be used for inferencing.

ts_model_id = client.foundation_models.TimeSeriesModels.GRANITE_TTM_512_96_R2

Next, we need to intialize an object of the TSModelInference class. TSModelInference is a wrapper around watsonx.ai models that provides integration around the models. This ts_model object will be able to make an API call to the model hosted by watsonx.ai.

ts_model = TSModelInference(
model_id=ts_model_id,
api_client=client
)

Here, we provide a set of model parameters as a specification that will influence our predictions. In this case, we set the frequency to a time range of 1 hour. TSForecastParameters documentation provides details about the parameters to the model. You can also see more details in our API documentation.

forecasting_params = TSForecastParameters(
timestamp_column=timestamp_column,
freq="1h",
target_columns=[target_column],
)

Step 6. Forecasting using your model

In order to create predictions, we'll call the forecast() method to compute values for our target variable total_load_actual, predicting electricity usage for the future time range. Using the Granite TTM (TinyTimeMixer) model via the API, we get a fast response time, even for a multivariate forecasting problem.

results = ts_model.forecast(data=data, params=forecasting_params)['results'][0]

For an initial evaluation of our model's performance, we'll use a data visualization. Here, we plot the predictions (shown in gold), along with the historical data (shown in blue) for past values. We can also see the green dotted line, our future_data or the ground truth against which to compare our predictions.

This gold line predicts hourly energy demand based on the patterns in the historical data. In evaluating the green dotted line against the gold line, we can see instances of overlap where the model's predictions are accurate.

plt.figure(figsize=(10,2))
plt.plot(np.asarray(data[timestamp_column], dtype='datetime64[s]'), data[target_column], label="Historical data")
plt.plot(np.asarray(results[timestamp_column], dtype='datetime64[s]'), results[target_column], label="Predicted")
plt.plot(np.asarray(future_data[timestamp_column], dtype='datetime64[s]'), future_data[target_column], label="True", linestyle='dashed')
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))
plt.show()

We can also calculate evaluation metrics to quantify the accuracy of the model. We'll use the Mean Absolute Percentage Error (MAPE) as our metric. A lower percentage is better and our result, at less than 10%, is a good indication of the performance of the model for this use case.

Using the watsonx.ai Timeseries Forecasting API, the Granite model's accuracy and response time for a multivariate forecasting problem is noteworthy.

mape = mean_absolute_percentage_error(future_data[target_column], results[target_column]) * 100
mape

Output:

6.081524040679701

timeseries forecasting energy demand plot

Summary

In this tutorial, you used the watsonx.ai Timeseries Forecasting API and SDK to make predictions for energy demand.

Whether you’re improving and streamlining operations, predicting share prices, navigating emissions for sustainability or exploring entirely new use cases, this Forecasting API delivers the foundation for smarter, data-driven decisions, complementing watsonx.ai’s existing foundation model library.

Get started today for free at our IBM watsonx Developer Hub.

For more use cases using watsonx.ai and IBM's open source Granite models, try out our other tutorials.

Related solutions
IBM® watsonx Orchestrate™ 

Easily design scalable AI assistants and agents, automate repetitive tasks and simplify complex processes with IBM® watsonx Orchestrate™.

Explore watsonx Orchestrate
Artificial intelligence solutions

Put AI to work in your business with IBM’s industry-leading AI expertise and portfolio of solutions at your side.

Explore AI solutions
Artificial intelligence consulting and services

IBM Consulting AI services help reimagine how businesses work with AI for transformation.

Explore AI services
Startup business partners walking through office corridor using digital tablet and discussing work. Businesswoman looking at digital tablet and talking colleague at work.

Think Newsletter

 

The latest AI and tech insights from Think

Sign up today
Take the next step

Train, validate, tune and deploy generative AI, foundation models and machine learning capabilities with IBM watsonx.ai, a next-generation enterprise studio for AI builders. Build AI applications in a fraction of the time with a fraction of the data.

Explore watsonx.ai Book a live demo