microsoft/qlib · error · NotImplementedError

optimizer {} is not supported!

Error message

optimizer {} is not supported!

What it means

Raised by the SFM (Stationary-Factory-Model) model init in qlib/contrib/model/pytorch_sfm.py:299 when optimizer.lower() is neither 'adam' nor 'gd'. The constructor maps 'adam' to torch.optim.Adam and 'gd' to torch.optim.SGD at the configured lr; everything else raises NotImplementedError during model construction.

Source

Thrown at qlib/contrib/model/pytorch_sfm.py:299

        self.sfm_model = SFM_Model(
            d_feat=self.d_feat,
            output_dim=self.output_dim,
            hidden_size=self.hidden_size,
            freq_dim=self.freq_dim,
            dropout_W=self.dropout_W,
            dropout_U=self.dropout_U,
            device=self.device,
        )
        self.logger.info("model:\n{:}".format(self.sfm_model))
        self.logger.info("model size: {:.4f} MB".format(count_parameters(self.sfm_model)))

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

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

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

    def test_epoch(self, data_x, data_y):
        # prepare training data
        x_values = data_x.values
        y_values = np.squeeze(data_y.values)

        self.sfm_model.eval()

        scores = []
        losses = []

View on GitHub (pinned to 79633dd950)

Solutions

  1. Set optimizer: 'adam' or 'gd' in the SFM model kwargs.
  2. For other optimizers, subclass the SFM model and rebuild self.train_optimizer after super().__init__.

Example fix

# before
kwargs:
  optimizer: adamw

# after
kwargs:
  optimizer: adam   # or 'gd'
Defensive patterns

Strategy: validation

Validate before calling

assert config["optimizer"].lower() in ("adam", "gd"), "SFM supports only 'adam' or 'gd'"

Type guard

def is_supported_optimizer(optimizer: str) -> bool:
    return optimizer.lower() in ("adam", "gd")

Try / catch

try:
    model = SFMModel(**kwargs)
except NotImplementedError as e:
    if "optimizer" in str(e):
        raise ValueError("Use optimizer='adam' or 'gd'") from e
    raise

Prevention

When it happens

Trigger: Passing optimizer='sgd', 'adamw', 'rmsprop', etc. to the SFM model kwargs; fires in __init__ (well before fit/predict), typically right after the 'model size: ... MB' log line.

Common situations: Same trap as other qlib pytorch models: 'sgd' is the intuitive token but qlib wants 'gd'; optimizer strings copied from sklearn/LightGBM configs.

Related errors


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