{"record":{"id":"e523b71cbea3a662","repo":"microsoft/qlib","slug":"optimizer-is-not-supported-e523b7","errorCode":null,"errorMessage":"optimizer {} is not supported!","messagePattern":"optimizer (.+?) is not supported!","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"qlib/contrib/model/pytorch_general_nn.py","lineNumber":138,"sourceCode":"                seed,\n                pt_model_uri,\n                pt_model_kwargs,\n            )\n        )\n\n        if self.seed is not None:\n            np.random.seed(self.seed)\n            torch.manual_seed(self.seed)\n\n        self.logger.info(\"model:\\n{:}\".format(self.dnn_model))\n        self.logger.info(\"model size: {:.4f} MB\".format(count_parameters(self.dnn_model)))\n\n        if optimizer.lower() == \"adam\":\n            self.train_optimizer = optim.Adam(self.dnn_model.parameters(), lr=self.lr, weight_decay=weight_decay)\n        elif optimizer.lower() == \"gd\":\n            self.train_optimizer = optim.SGD(self.dnn_model.parameters(), lr=self.lr, weight_decay=weight_decay)\n        else:\n            raise NotImplementedError(\"optimizer {} is not supported!\".format(optimizer))\n\n        # === ReduceLROnPlateau learning rate scheduler ===\n        self.lr_scheduler = ReduceLROnPlateau(\n            self.train_optimizer, mode=\"min\", factor=0.5, patience=5, min_lr=1e-6, threshold=1e-5\n        )\n        self.fitted = False\n        self.dnn_model.to(self.device)\n\n    @property\n    def use_gpu(self):\n        return self.device != torch.device(\"cpu\")\n\n    def mse(self, pred, label, weight):\n        loss = weight * (pred - label) ** 2\n        return torch.mean(loss)\n\n    def loss_fn(self, pred, label, weight=None):\n        mask = ~torch.isnan(label)","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/pytorch_general_nn.py#L120-L156","documentation":"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.","triggerScenarios":"DNNModelPt(...).fit(dataset) with optimizer='sgd', 'adamw', 'rmsprop', 'adagrad', or any string besides 'adam'/'gd'.","commonSituations":"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.","solutions":["Use 'adam' or 'gd'.","Change 'sgd' to 'gd'.","Subclass DNNModelPt and add a branch constructing the desired torch.optim class with weight_decay."],"exampleFix":"# before\nmodel = DNNModelPt(optimizer='sgd')\n\n# after\nmodel = DNNModelPt(optimizer='gd')","handlingStrategy":"validation","validationCode":"assert optimizer.lower() in ('adam', 'gd'), f\"optimizer must be 'adam' or 'gd', got {optimizer!r}\"","typeGuard":"def is_supported_optimizer(name: str) -> bool:\n    return name.lower() in ('adam', 'gd')","tryCatchPattern":"try:\n    model.fit(dataset)\nexcept NotImplementedError as e:\n    if 'optimizer' in str(e):\n        model = DNNModelPt(optimizer='adam')\n        model.fit(dataset)\n    else:\n        raise","preventionTips":["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."],"tags":["pytorch","qlib","optimizer","config-validation","dnn"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}