{"record":{"id":"a91861c2c26b3aae","repo":"microsoft/qlib","slug":"optimizer-is-not-supported-a91861","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_sfm.py","lineNumber":299,"sourceCode":"\n        self.sfm_model = SFM_Model(\n            d_feat=self.d_feat,\n            output_dim=self.output_dim,\n            hidden_size=self.hidden_size,\n            freq_dim=self.freq_dim,\n            dropout_W=self.dropout_W,\n            dropout_U=self.dropout_U,\n            device=self.device,\n        )\n        self.logger.info(\"model:\\n{:}\".format(self.sfm_model))\n        self.logger.info(\"model size: {:.4f} MB\".format(count_parameters(self.sfm_model)))\n\n        if optimizer.lower() == \"adam\":\n            self.train_optimizer = optim.Adam(self.sfm_model.parameters(), lr=self.lr)\n        elif optimizer.lower() == \"gd\":\n            self.train_optimizer = optim.SGD(self.sfm_model.parameters(), lr=self.lr)\n        else:\n            raise NotImplementedError(\"optimizer {} is not supported!\".format(optimizer))\n\n        self.fitted = False\n        self.sfm_model.to(self.device)\n\n    @property\n    def use_gpu(self):\n        return self.device != torch.device(\"cpu\")\n\n    def test_epoch(self, data_x, data_y):\n        # prepare training data\n        x_values = data_x.values\n        y_values = np.squeeze(data_y.values)\n\n        self.sfm_model.eval()\n\n        scores = []\n        losses = []\n","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/pytorch_sfm.py#L281-L317","documentation":"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.","triggerScenarios":"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.","commonSituations":"Same trap as other qlib pytorch models: 'sgd' is the intuitive token but qlib wants 'gd'; optimizer strings copied from sklearn/LightGBM configs.","solutions":["Set optimizer: 'adam' or 'gd' in the SFM model kwargs.","For other optimizers, subclass the SFM model and rebuild self.train_optimizer after super().__init__."],"exampleFix":"# before\nkwargs:\n  optimizer: adamw\n\n# after\nkwargs:\n  optimizer: adam   # or 'gd'","handlingStrategy":"validation","validationCode":"assert config[\"optimizer\"].lower() in (\"adam\", \"gd\"), \"SFM supports only 'adam' or 'gd'\"","typeGuard":"def is_supported_optimizer(optimizer: str) -> bool:\n    return optimizer.lower() in (\"adam\", \"gd\")","tryCatchPattern":"try:\n    model = SFMModel(**kwargs)\nexcept NotImplementedError as e:\n    if \"optimizer\" in str(e):\n        raise ValueError(\"Use optimizer='adam' or 'gd'\") from e\n    raise","preventionTips":["Share one validated optimizer whitelist across all qlib pytorch models.","Remember 'gd' means plain SGD in qlib's config vocabulary."],"tags":["qlib","pytorch","optimizer","config","not-implemented","sfm"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}