{"record":{"id":"db8843eabbdb3b38","repo":"microsoft/qlib","slug":"unknown-loss-s-db8843","errorCode":null,"errorMessage":"unknown loss `%s`","messagePattern":"unknown loss `(.+?)`","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/contrib/model/pytorch_transformer_ts.py","lineNumber":92,"sourceCode":"\r\n        self.fitted = False\r\n        self.model.to(self.device)\r\n\r\n    @property\r\n    def use_gpu(self):\r\n        return self.device != torch.device(\"cpu\")\r\n\r\n    def mse(self, pred, label):\r\n        loss = (pred.float() - label.float()) ** 2\r\n        return torch.mean(loss)\r\n\r\n    def loss_fn(self, pred, label):\r\n        mask = ~torch.isnan(label)\r\n\r\n        if self.loss == \"mse\":\r\n            return self.mse(pred[mask], label[mask])\r\n\r\n        raise ValueError(\"unknown loss `%s`\" % self.loss)\r\n\r\n    def metric_fn(self, pred, label):\r\n        mask = torch.isfinite(label)\r\n\r\n        if self.metric in (\"\", \"loss\"):\r\n            return -self.loss_fn(pred[mask], label[mask])\r\n\r\n        raise ValueError(\"unknown metric `%s`\" % self.metric)\r\n\r\n    def train_epoch(self, data_loader):\r\n        self.model.train()\r\n\r\n        for data in data_loader:\r\n            feature = data[:, :, 0:-1].to(self.device)\r\n            label = data[:, -1, -1].to(self.device)\r\n\r\n            pred = self.model(feature.float())  # .float()\r\n            loss = self.loss_fn(pred, label)\r","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/pytorch_transformer_ts.py#L74-L110","documentation":"Thrown by TransformerTSModel.loss_fn. The time-series Transformer implements exactly one loss, 'mse', evaluated over the non-NaN label mask; any other `loss` hyperparameter value reaches the terminal ValueError on the first batch.","triggerScenarios":"TransformerTSModel(..., loss='mae'|'smoothl1'|'MSE') followed by fit(); train_epoch's loss_fn call raises immediately.","commonSituations":"Case-sensitive typo 'MSE'; hyperparameter dicts shared across models where another loss name was valid; assuming the loss vocabulary of the wider qlib/TRA stack applies here.","solutions":["Set loss='mse' (exact lowercase) — the only supported value.","Subclass TransformerTSModel and override loss_fn to add other losses while keeping the NaN mask."],"exampleFix":"# before\nmodel = TransformerTSModel(..., loss=\"smoothl1\")\n\n# after\nmodel = TransformerTSModel(..., loss=\"mse\")","handlingStrategy":"validation","validationCode":"assert model_kwargs.get(\"loss\", \"mse\") == \"mse\", \"TransformerTSModel supports only loss='mse'\"","typeGuard":null,"tryCatchPattern":"try:\n    model.fit(ds, valid)\nexcept ValueError as e:\n    if \"unknown loss\" in str(e):\n        model_kwargs[\"loss\"] = \"mse\"\n        model = TransformerTSModel(**model_kwargs)\n        model.fit(ds, valid)\n    else:\n        raise","preventionTips":["Use exact lowercase 'mse'; no other loss exists in these models.","Lint config values against per-model enums before launching training jobs."],"tags":["qlib","pytorch","transformer","loss-function","hyperparameter"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}