Berlin Tech Meetup: The Future of Relational Foundation Models, Systems, and Real-World Applications

Register now:
PyG/Use Case11 min read

Energy Load Forecasting: GNN on Meter + Weather Graphs

Grid operators must balance supply and demand in real time. A 1% forecasting error costs utilities $10M+ annually in spot market purchases. Here is how to build a GNN that forecasts load using the spatial meter graph and weather correlations.

PyTorch Geometric

TL;DR

  • 1Energy load forecasting is a spatial-temporal graph regression problem. Meters are correlated through geography, grid topology, and shared weather conditions.
  • 2SAGEConv on the meter-weather graph combines spatial correlations with temporal patterns (GRU) for hierarchical load prediction from meters to substations.
  • 3On grid forecasting benchmarks, GNNs reduce MAPE from ~8% (per-meter ARIMA) to ~4-5%. Spatial correlations during extreme weather events drive the largest improvements.
  • 4Hierarchical graph aggregation produces consistent forecasts at every grid level: meter, feeder, substation, and system.
  • 5KumoRFM predicts load with one PQL query, capturing spatial and weather correlations automatically without graph construction or temporal architecture design.

The business problem

Electric utilities must balance generation with demand in real time. Over-forecasting wastes money on unnecessary generation. Under-forecasting requires expensive spot-market purchases or, in extreme cases, rolling blackouts. A 1% improvement in forecast accuracy saves a large utility $10M+ annually in procurement costs. During extreme weather events, when demand spikes are correlated across the grid, accurate forecasting can prevent cascading failures.

Why flat ML fails

  • Independent meter forecasts: Forecasting each meter independently ignores spatial correlations. Meters in the same zone experience the same weather, demographics, and economic conditions.
  • No grid topology: Load on a transformer is the sum of downstream meters. Independent forecasts at different hierarchy levels are inconsistent. The graph enforces consistency.
  • Weather correlation blindness: A heat wave affects all meters in a region, but the impact varies by building type and grid position. Flat models cannot propagate weather effects through the spatial network.
  • Extreme event failure: Independent models fail most during extreme events (heat waves, cold snaps) when spatial correlation is highest and accurate forecasting is most critical.

The relational schema

schema.txt
Node types:
  Meter      (id, type, building_class, capacity)
  Feeder     (id, capacity, transformer_count)
  Substation (id, capacity, voltage_level)
  Weather    (id, station_name, geo_lat, geo_lon)

Edge types:
  Meter      --[on_feeder]-->    Feeder
  Feeder     --[at_substation]--> Substation
  Meter      --[near]-->         Meter       (distance_km)
  Meter      --[monitored_by]--> Weather
  Weather    --[correlated]-->   Weather     (distance_km)

The hierarchical grid graph (meter-feeder-substation) plus spatial proximity and weather connections.

PyG architecture: SAGEConv + GRU for spatial-temporal load

energy_model.py
import torch
import torch.nn.functional as F
from torch_geometric.nn import SAGEConv, HeteroConv, Linear

class EnergyGNN(torch.nn.Module):
    def __init__(self, meter_dim, hidden_dim=128):
        super().__init__()
        self.meter_lin = Linear(meter_dim, hidden_dim)
        self.feeder_lin = Linear(-1, hidden_dim)
        self.weather_lin = Linear(-1, hidden_dim)

        self.conv1 = HeteroConv({
            ('meter', 'near', 'meter'): SAGEConv(
                hidden_dim, hidden_dim),
            ('meter', 'on_feeder', 'feeder'): SAGEConv(
                hidden_dim, hidden_dim),
            ('meter', 'monitored_by', 'weather'): SAGEConv(
                hidden_dim, hidden_dim),
        }, aggr='mean')

        self.conv2 = HeteroConv({
            ('meter', 'near', 'meter'): SAGEConv(
                hidden_dim, hidden_dim),
            ('meter', 'on_feeder', 'feeder'): SAGEConv(
                hidden_dim, hidden_dim),
        }, aggr='mean')

        # Temporal: GRU over hourly snapshots
        self.gru = torch.nn.GRU(
            hidden_dim, hidden_dim, batch_first=True)

        # Forecast head: next 24 hours
        self.head = torch.nn.Sequential(
            Linear(hidden_dim, 64),
            torch.nn.ReLU(),
            Linear(64, 24),  # 24-hour forecast
        )

    def forward(self, x_seq_dict, edge_index_dict):
        # Process each hourly snapshot through spatial GNN
        T = len(x_seq_dict['meter'])
        embeddings = []
        for t in range(T):
            x_dict = {
                'meter': self.meter_lin(x_seq_dict['meter'][t]),
                'feeder': self.feeder_lin(x_seq_dict['feeder'][t]),
                'weather': self.weather_lin(
                    x_seq_dict['weather'][t]),
            }
            x_dict = {k: F.relu(v) for k, v in
                      self.conv1(x_dict, edge_index_dict).items()}
            x_dict = self.conv2(x_dict, edge_index_dict)
            embeddings.append(x_dict['meter'])

        h_seq = torch.stack(embeddings, dim=1)
        _, h_final = self.gru(h_seq)

        return self.head(h_final.squeeze(0))

Spatial GNN per timestep + GRU for temporal patterns. Output: 24-hour load forecast per meter. Aggregate up the grid hierarchy for feeder and substation forecasts.

Expected performance

Load forecasting is a regression task. The standard metric is Mean Absolute Percentage Error (MAPE):

  • ARIMA (per-meter): ~8% MAPE
  • LightGBM (flat-table): ~6% MAPE
  • GNN (spatial-temporal): ~4-5% MAPE
  • KumoRFM (zero-shot): ~4% MAPE

Or use KumoRFM in one line

KumoRFM PQL
PREDICT hourly_load FOR meter
USING meter, feeder, substation, weather, reading_history

One PQL query. KumoRFM captures spatial meter correlations and weather effects for hierarchical load forecasting.

Frequently asked questions

Why use GNNs for energy load forecasting?

Energy demand at one meter is correlated with nearby meters (shared weather, demographics) and upstream/downstream grid topology. GNNs model these spatial correlations, improving forecasts especially during extreme events (heat waves, cold snaps) when correlated demand spikes can cause grid failures.

What graph structure represents the power grid for forecasting?

Smart meters are nodes with consumption time series. Edges connect meters in the same geographic zone, on the same distribution feeder, or in similar building types. Weather stations connect to their covered meters. The grid topology (substations, feeders, transformers) provides the electrical connectivity graph.

How do weather events propagate through the meter graph?

A heat wave affects all meters in a geographic zone, but the impact varies by building type (commercial AC vs residential), time of day, and grid position. The GNN propagates weather features through the spatial graph, learning that a 100F day increases load 40% for commercial buildings but 25% for residential, and that upstream transformers face the sum of these increases.

Can GNNs forecast at different levels of the grid hierarchy?

Yes. The hierarchical grid topology (meters to feeders to substations to the grid) is a natural tree graph. The GNN aggregates meter-level forecasts up through the hierarchy, producing consistent forecasts at every level. This is more accurate than independent forecasting at each level.

How does KumoRFM handle energy forecasting?

KumoRFM takes your energy data (meters, readings, weather, grid topology) and predicts load with one PQL query. It captures spatial correlations and weather effects automatically through its graph transformer architecture.

Learn more about graph ML

PyTorch Geometric is the open-source foundation for graph neural networks. Explore more layers, concepts, and production patterns.