Skip to content

[BUG] NHiTS fails when TimeSeriesDataSet includes static real variables #2281

Description

@cngmid

Summary

When using NHiTS.from_dataset() with a TimeSeriesDataSet that includes static real variables, the model fails during the forward pass with:

NameError: free variable 'encoder_features' referenced before assignment

This occurs whenever add_target_scales=True (or any other configuration that adds static reals).

Minimal Reproducible Example

from pytorch_forecasting.data.examples import generate_ar_data
from pytorch_forecasting import TimeSeriesDataSet, NHiTS

data = generate_ar_data(seasonality=10.0, timesteps=400, n_series=100, seed=42)

dataset = TimeSeriesDataSet(
    data,
    time_idx="time_idx",
    target="value",
    group_ids=["series"],
    time_varying_unknown_reals=["value"],
    max_encoder_length=60,
    max_prediction_length=20,
    add_target_scales=True,   # <-- introduces static real variables
)

dataloader = dataset.to_dataloader(train=True, batch_size=8)
model = NHiTS.from_dataset(dataset)

batch, _ = next(iter(dataloader))
model(batch)  # crashes

Observed Error

The failure occurs inside NHiTS.forward() when static variables are present:

x_s = torch.concat([encoder_features[name][:, 0] for name in self.static_variables], dim=1)
NameError: free variable 'encoder_features' referenced before assignment

This matches the traceback in the notebook.

Root Cause Analysis

self.static_size > 0 triggers the static‑feature branch in forward().
But encoder_features is never defined because the call to:

encoder_features = self.extract_features(x, self.embeddings, period="encoder")

is only set if self.encoder_covariate_size > 0.

This happens either:

  • (most likely) because encoder_covariate_size() does not include len(self.hparams.static_reals), so the model incorrectly assumes there are no encoder covariates and skips feature extraction, or

  • because encoder_features is not defined in the block if self.static_size > 0.

Expected Behavior

Unless I am mistaken, N‑HiTS should support static real variables (as other models do), or at minimum should not crash.

Proposed Fix

Either:

  1. Preferred:
    Update encoder_covariate_size() to include static reals:
return len(self.hparams.time_varying_encoder_reals) + len(self.hparams.static_reals)
        return len(
            set(self.hparams.time_varying_reals_encoder) - set(self.target_names)
        ) + sum(
            self.embeddings.output_size[name]
            for name in self.hparams.time_varying_categoricals_encoder
        ) + len(
            self.hparams.static_reals
        )
  1. Alternative (would this be correct?):
    In forward(), define encoder_features when self.static_size > 0:
        if self.static_size > 0:
            encoder_features = self.extract_features(
                x, self.embeddings, period="encoder"
            )

Environment

pytorch-forecasting version: 1.7.0

PyTorch version: 2.10

Lightning version: 2.6.1

OS: Windows 11

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Needs triage & validation

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions