microsoft/qlib · error · NotImplementedError

optimizer {} is not supported!

Error message

optimizer {} is not supported!

What it means

Thrown in TCNTSModel's (time-series TCN) fit setup while constructing the training optimizer. The `optimizer` hyperparameter is matched case-insensitively against 'adam' and 'gd' (plain SGD); anything else raises NotImplementedError. This happens at the start of fit, before any training.

Source

Thrown at qlib/contrib/model/pytorch_tcn_ts.py:136

            np.random.seed(self.seed)
            torch.manual_seed(self.seed)

        self.TCN_model = TCNModel(
            num_input=self.d_feat,
            output_size=1,
            num_channels=[self.n_chans] * self.num_layers,
            kernel_size=self.kernel_size,
            dropout=self.dropout,
        )
        self.logger.info("model:\n{:}".format(self.TCN_model))
        self.logger.info("model size: {:.4f} MB".format(count_parameters(self.TCN_model)))

        if optimizer.lower() == "adam":
            self.train_optimizer = optim.Adam(self.TCN_model.parameters(), lr=self.lr)
        elif optimizer.lower() == "gd":
            self.train_optimizer = optim.SGD(self.TCN_model.parameters(), lr=self.lr)
        else:
            raise NotImplementedError("optimizer {} is not supported!".format(optimizer))

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

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

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

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

        if self.loss == "mse":
            return self.mse(pred[mask], label[mask])

View on GitHub (pinned to 79633dd950)

Solutions

  1. Use optimizer='adam' or optimizer='gd' — these are the only two supported by TCNTSModel.
  2. If you typed 'sgd', change it to 'gd' (that is this model's name for plain SGD).
  3. For another optimizer, subclass TCNTSModel, override the fit setup, and construct optim.<Opt>(self.TCN_model.parameters(), lr=self.lr) yourself.

Example fix

# before
model = TCNTSModel(..., optimizer="sgd")
model.fit(dataset)  # NotImplementedError

# after
model = TCNTSModel(..., optimizer="gd")
model.fit(dataset)
Defensive patterns

Strategy: validation

Validate before calling

optimizer = model_kwargs.get("optimizer", "adam")
assert optimizer.lower() in ("adam", "gd"), f"TCNTSModel optimizer must be 'adam' or 'gd', got {optimizer!r}"

Try / catch

try:
    model.fit(ds, valid)
except NotImplementedError as e:
    if "optimizer" in str(e):
        model_kwargs["optimizer"] = "adam"
        model = TCNTSModel(**model_kwargs)
        model.fit(ds, valid)
    else:
        raise

Prevention

When it happens

Trigger: Calling TCNTSModel.fit() with optimizer='sgd', 'adamw', 'rmsprop', or any string other than 'adam'/'gd'; the optimizer-dispatch if/elif falls through to the raise.

Common situations: Configs ported from other qlib models or tutorials that use 'sgd' (here plain SGD is spelled 'gd'); using newer PyTorch optimizer names like 'adamw' expecting support; typos.

Related errors


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