microsoft/qlib · error · NotImplementedError
optimizer {} is not supported!
Error message
optimizer {} is not supported! What it means
Thrown in TransformerModel's fit setup while creating the training optimizer. The `optimizer` hyperparameter is compared case-insensitively to 'adam' and 'gd'; both branches add weight_decay=self.reg. Any other value raises NotImplementedError before any epoch runs.
Source
Thrown at qlib/contrib/model/pytorch_transformer.py:75
self.optimizer = optimizer.lower()
self.loss = loss
self.n_jobs = n_jobs
self.device = torch.device("cuda:%d" % GPU if torch.cuda.is_available() and GPU >= 0 else "cpu")
self.seed = seed
self.logger = get_module_logger("TransformerModel")
self.logger.info("Naive Transformer:" "\nbatch_size : {}" "\ndevice : {}".format(self.batch_size, self.device))
if self.seed is not None:
np.random.seed(self.seed)
torch.manual_seed(self.seed)
self.model = Transformer(d_feat, d_model, nhead, num_layers, dropout, self.device)
if optimizer.lower() == "adam":
self.train_optimizer = optim.Adam(self.model.parameters(), lr=self.lr, weight_decay=self.reg)
elif optimizer.lower() == "gd":
self.train_optimizer = optim.SGD(self.model.parameters(), lr=self.lr, weight_decay=self.reg)
else:
raise NotImplementedError("optimizer {} is not supported!".format(optimizer))
self.fitted = False
self.model.to(self.device)
@property
def use_gpu(self):
return self.device != torch.device("cpu")
def mse(self, pred, label):
loss = (pred.float() - label.float()) ** 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
- Set optimizer='adam' or optimizer='gd' (with optional reg for weight decay).
- Replace 'sgd' with 'gd' — this model's spelling of plain SGD.
- Subclass TransformerModel and override the fit preamble to instantiate another torch.optim optimizer on self.model.parameters() if needed.
Example fix
# before model = TransformerModel(..., optimizer="adamw", reg=1e-4) # after model = TransformerModel(..., optimizer="adam", reg=1e-4)
Defensive patterns
Strategy: validation
Validate before calling
optimizer = model_kwargs.get("optimizer", "adam")
assert optimizer.lower() in ("adam", "gd"), f"TransformerModel optimizer must be 'adam' or 'gd', got {optimizer!r}" Try / catch
try:
model.fit(dataset, evals_result)
except NotImplementedError as e:
if "optimizer" in str(e):
model_kwargs["optimizer"] = "adam"
model = TransformerModel(**model_kwargs)
model.fit(dataset, evals_result)
else:
raise Prevention
- Use 'adam'/'gd' only in qlib model configs; map 'sgd'→'gd' when porting.
- Centralize optimizer allowlists per model class in config validation.
When it happens
Trigger: TransformerModel(..., optimizer='sgd'|'adamw'|'rmsprop') followed by fit(); the dispatch falls through to the raise.
Common situations: Benchmark yaml configs using 'sgd'; users expecting AdamW support; typos; configs copied from models with wider optimizer support.
Related errors
- optimizer {} is not supported!
- optimizer {} is not supported!
- optimizer {} is not supported!
- optimizer {} is not supported!
- unknown loss `%s`
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/ceac844ad2d3d645.
Report an issue: GitHub.