microsoft/qlib · error · NotImplementedError
optimizer {} is not supported!
Error message
optimizer {} is not supported! What it means
DNNModelPt.fit() selects the training optimizer from the optimizer hyperparameter with two branches: 'adam' -> torch.optim.Adam and 'gd' -> torch.optim.SGD, both including weight_decay. Any other string raises NotImplementedError before the ReduceLROnPlateau scheduler is attached. This generic feed-forward model otherwise follows the same optimizer switch pattern as the GATs/ALSTM contrib models.
Source
Thrown at qlib/contrib/model/pytorch_general_nn.py:138
seed,
pt_model_uri,
pt_model_kwargs,
)
)
if self.seed is not None:
np.random.seed(self.seed)
torch.manual_seed(self.seed)
self.logger.info("model:\n{:}".format(self.dnn_model))
self.logger.info("model size: {:.4f} MB".format(count_parameters(self.dnn_model)))
if optimizer.lower() == "adam":
self.train_optimizer = optim.Adam(self.dnn_model.parameters(), lr=self.lr, weight_decay=weight_decay)
elif optimizer.lower() == "gd":
self.train_optimizer = optim.SGD(self.dnn_model.parameters(), lr=self.lr, weight_decay=weight_decay)
else:
raise NotImplementedError("optimizer {} is not supported!".format(optimizer))
# === ReduceLROnPlateau learning rate scheduler ===
self.lr_scheduler = ReduceLROnPlateau(
self.train_optimizer, mode="min", factor=0.5, patience=5, min_lr=1e-6, threshold=1e-5
)
self.fitted = False
self.dnn_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=None):
mask = ~torch.isnan(label)View on GitHub (pinned to 79633dd950)
Solutions
- Use 'adam' or 'gd'.
- Change 'sgd' to 'gd'.
- Subclass DNNModelPt and add a branch constructing the desired torch.optim class with weight_decay.
Example fix
# before model = DNNModelPt(optimizer='sgd') # after model = DNNModelPt(optimizer='gd')
Defensive patterns
Strategy: validation
Validate before calling
assert optimizer.lower() in ('adam', 'gd'), f"optimizer must be 'adam' or 'gd', got {optimizer!r}" Type guard
def is_supported_optimizer(name: str) -> bool:
return name.lower() in ('adam', 'gd') Try / catch
try:
model.fit(dataset)
except NotImplementedError as e:
if 'optimizer' in str(e):
model = DNNModelPt(optimizer='adam')
model.fit(dataset)
else:
raise Prevention
- Use 'gd' rather than 'sgd' for the plain-SGD option.
- Validate optimizer names against the allowlist before fit in tuning loops.
- Subclass DNNModelPt early if you need AdamW or other optimizers with weight_decay.
When it happens
Trigger: DNNModelPt(...).fit(dataset) with optimizer='sgd', 'adamw', 'rmsprop', 'adagrad', or any string besides 'adam'/'gd'.
Common situations: The classic 'sgd' vs 'gd' mismatch; hyperparameter tuning scripts that enumerate torch optimizer names; wanting AdamW for proper weight decay handling in the general NN workflow.
Related errors
- optimizer {} is not supported!
- optimizer {} is not supported!
- optimizer {} is not supported!
- unknown metric `%s`
- unknown rnn_type `%s`
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/e523b71cbea3a662.
Report an issue: GitHub.