{"record":{"id":"e13e92da5e57a6eb","repo":"microsoft/qlib","slug":"unknown-metric-s-e13e92","errorCode":null,"errorMessage":"unknown metric `%s`","messagePattern":"unknown metric `(.+?)`","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/contrib/model/pytorch_tabnet.py","lineNumber":378,"sourceCode":"        \"\"\"\n        Pretrain loss function defined in the original paper, read \"Tabular self-supervised learning\" in https://arxiv.org/pdf/1908.07442.pdf\n        \"\"\"\n        down_mean = torch.mean(f, dim=0)\n        down = torch.sqrt(torch.sum(torch.square(f - down_mean), dim=0))\n        up = (f_hat - f) * S\n        return torch.sum(torch.square(up / down))\n\n    def loss_fn(self, pred, label):\n        mask = ~torch.isnan(label)\n        if self.loss == \"mse\":\n            return self.mse(pred[mask], label[mask])\n        raise ValueError(\"unknown loss `%s`\" % self.loss)\n\n    def metric_fn(self, pred, label):\n        mask = torch.isfinite(label)\n        if self.metric in (\"\", \"loss\"):\n            return -self.loss_fn(pred[mask], label[mask])\n        raise ValueError(\"unknown metric `%s`\" % self.metric)\n\n    def mse(self, pred, label):\n        loss = (pred - label) ** 2\n        return torch.mean(loss)\n\n\nclass FinetuneModel(nn.Module):\n    \"\"\"\n    FinuetuneModel for adding a layer by the end\n    \"\"\"\n\n    def __init__(self, input_dim, output_dim, trained_model):\n        super().__init__()\n        self.model = trained_model\n        self.fc = nn.Linear(input_dim, output_dim)\n\n    def forward(self, x, priors):\n        return self.fc(self.model(x, priors)[0]).squeeze()  # take the vec out","sourceCodeStart":360,"sourceCodeEnd":396,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/pytorch_tabnet.py#L360-L396","documentation":"Raised by TabNet model metric_fn in qlib/contrib/model/pytorch_tabnet.py:378 when self.metric is neither '' nor 'loss'. Early stopping in this model can only track negative masked MSE ('loss' or empty string); passing 'ic', 'auc', etc. raises ValueError on the first validation scoring in fit().","triggerScenarios":"metric='ic' (or any unsupported token) in TabNet kwargs, then fit(); the raise occurs mid-training at the first evaluation step.","commonSituations":"Porting metric names from other qlib examples; expecting sklearn/pytorch-tabnet metric names to carry over.","solutions":["Set metric: '' or metric: 'loss'.","Subclass and override metric_fn() with a custom metric (e.g. IC) for alternative early stopping."],"exampleFix":"# before\nkwargs:\n  metric: ic\n\n# after\nkwargs:\n  metric: loss   # or ''","handlingStrategy":"validation","validationCode":"metric = config.get(\"metric\", \"\")\nassert metric in (\"\", \"loss\"), f\"TabNet metric must be '' or 'loss', got {metric!r}\"","typeGuard":"def is_supported_tabnet_metric(metric: str) -> bool:\n    return metric in (\"\", \"loss\")","tryCatchPattern":"try:\n    model.fit(dataset)\nexcept ValueError as e:\n    if \"unknown metric\" in str(e):\n        raise ValueError(\"TabNet early stopping tracks only the loss; use metric='' or 'loss'\") from e\n    raise","preventionTips":["Omit metric in configs unless overriding metric_fn in a subclass.","Validate metric tokens per model class before launching training."],"tags":["qlib","pytorch","metric","config","early-stopping","tabnet"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}