microsoft/qlib · error · NotImplementedError

optimizer {} is not supported!

Error message

optimizer {} is not supported!

What it means

The time-series LSTM model's constructor accepts only 'adam' (optim.Adam) and 'gd' (optim.SGD), both lr-only without weight decay. Any other optimizer string raises NotImplementedError('optimizer {} is not supported!') in __init__, right after the LSTM module is created and moved to device.

Source

Thrown at qlib/contrib/model/pytorch_lstm_ts.py:128

            )
        )

        if self.seed is not None:
            np.random.seed(self.seed)
            torch.manual_seed(self.seed)

        self.LSTM_model = LSTMModel(
            d_feat=self.d_feat,
            hidden_size=self.hidden_size,
            num_layers=self.num_layers,
            dropout=self.dropout,
        ).to(self.device)
        if optimizer.lower() == "adam":
            self.train_optimizer = optim.Adam(self.LSTM_model.parameters(), lr=self.lr)
        elif optimizer.lower() == "gd":
            self.train_optimizer = optim.SGD(self.LSTM_model.parameters(), lr=self.lr)
        else:
            raise NotImplementedError("optimizer {} is not supported!".format(optimizer))

        self.fitted = False
        self.LSTM_model.to(self.device)

    @property
    def use_gpu(self):
        return self.device != torch.device("cpu")

    def mse(self, pred, label, weight):
        loss = weight * (pred - label) ** 2
        return torch.mean(loss)

    def loss_fn(self, pred, label, weight):
        mask = ~torch.isnan(label)

        if weight is None:
            weight = torch.ones_like(label)

View on GitHub (pinned to 79633dd950)

Solutions

  1. Use optimizer='adam' or optimizer='gd'.
  2. Need another optimizer? Subclass and after super().__init__() assign self.train_optimizer over self.LSTM_model.parameters().
  3. Verify the string in your YAML/kwargs matches exactly (case-insensitive).

Example fix

# before
model = LSTMModel(..., optimizer="adamw")  # NotImplementedError

# after
model = LSTMModel(..., optimizer="adam")
# plain SGD:
model = LSTMModel(..., optimizer="gd")
Defensive patterns

Strategy: validation

Validate before calling

assert optimizer.lower() in {"adam", "gd"}, "TS LSTM supports only 'adam' and 'gd'"
model = LSTMModel(..., optimizer=optimizer)

Type guard

def is_supported_optimizer(name: str) -> bool:
    return isinstance(name, str) and name.lower() in {"adam", "gd"}

Try / catch

try:
    model = LSTMModel(..., optimizer=opt)
except NotImplementedError as e:
    raise ValueError(f"{e} — use 'adam' or 'gd'") from e

Prevention

When it happens

Trigger: LSTMModel(..., optimizer=opt) in qlib/contrib/model/pytorch_lstm_ts.py with opt.lower() not in {'adam','gd'} — e.g. 'sgd', 'adamw', 'adagrad'.

Common situations: Sharing optimizer settings across different contrib model classes; expecting the PyTorch optimizer name 'SGD' or 'adamw' to work; typo'd strings.

Related errors


AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15). Data as JSON: /api/errors/7ffbe2ccca6a3391. Report an issue: GitHub.