{"record":{"id":"12be2e29541d3d54","repo":"microsoft/qlib","slug":"unknown-loss-s-12be2e","errorCode":null,"errorMessage":"unknown loss `%s`","messagePattern":"unknown loss `(.+?)`","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/contrib/model/pytorch_general_nn.py","lineNumber":164,"sourceCode":"\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)\n\n        if weight is None:\n            weight = torch.ones_like(label)\n\n        if self.loss == \"mse\":\n            return self.mse(pred[mask], label[mask].view(-1, 1), weight[mask])\n\n        raise ValueError(\"unknown loss `%s`\" % self.loss)\n\n    def metric_fn(self, pred, label):\n        mask = torch.isfinite(label)\n\n        if self.metric in (\"\", \"loss\"):\n            return self.loss_fn(pred[mask], label[mask])\n\n        raise ValueError(\"unknown metric `%s`\" % self.metric)\n\n    def _get_fl(self, data: torch.Tensor):\n        \"\"\"\n        get feature and label from data\n        - Handle the different data shape of time series and tabular data\n\n        Parameters\n        ----------\n        data : torch.Tensor\n            input data which maybe 3 dimension or 2 dimension","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/pytorch_general_nn.py#L146-L182","documentation":"Raised by DNNModelPytorch.loss_fn when the configured `loss` hyper-parameter is anything other than the literal string \"mse\". The class only implements a weighted MSE loss; the dispatch is a simple if-chain, so any other value (e.g. \"mae\", \"cross_entropy\", \"MSE\" with different case) reaches the terminal raise. This fires at the first training batch, not at construction, so config errors surface late.","triggerScenarios":"Calling model.fit(dataset) on a DNNModelPytorch whose init args include loss=\"mse\"-anything-else, e.g. loss=\"mae\" or loss=\"MSE\". The error is thrown from train_epoch -> loss_fn on the first forward pass, and from metric_fn when metric is \"\" or \"loss\" since that path delegates to loss_fn.","commonSituations":"Copying a workflow YAML from another qlib model (e.g. ALSTM or TabNet) that supports other loss names; passing a capitalized \"MSE\"; upgrading qlib versions where loss names changed; hand-rolling a custom loss name without subclassing.","solutions":["Set loss=\"mse\" in the model init args / workflow YAML handler parameters (this is the only supported value).","If you need another loss, subclass DNNModelPytorch, override loss_fn (and mse) to add your branch before the raise.","Check for stray whitespace or case differences in the YAML value (e.g. loss: ' mse ' will not match)."],"exampleFix":"# before\nmodel = DNNModelPytorch(loss=\"mae\", lr=0.001, ...)  # ValueError at first batch\n\n# after\nmodel = DNNModelPytorch(loss=\"mse\", lr=0.001, ...)","handlingStrategy":"validation","validationCode":"from qlib.contrib.model.pytorch_general_nn import DNNModelPytorch\nallowed = {\"mse\"}\nassert params[\"loss\"] in allowed, f\"loss must be one of {allowed}, got {params['loss']!r}\"","typeGuard":"def is_supported_loss(loss: str) -> bool:\n    return isinstance(loss, str) and loss in {\"mse\"}","tryCatchPattern":"try:\n    model.fit(dataset)\nexcept ValueError as e:\n    if \"unknown loss\" in str(e):\n        raise ValueError(f\"DNNModelPytorch only supports loss='mse'; got {model.loss!r}\") from e\n    raise","preventionTips":["Keep a project-level allowlist of per-model loss/metric values and validate workflow YAML against it before starting a run.","Never copy hyper-parameter blocks between different qlib contrib model classes without checking each class's loss_fn/metric_fn dispatch."],"tags":["pytorch","qlib","configuration","loss-function"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}