microsoft/qlib · error · ValueError

unknown loss `%s`

Error message

unknown loss `%s`

What it means

Raised by TabNet model loss_fn in qlib/contrib/model/pytorch_tabnet.py:372 when self.loss is not 'mse'. TabNet's supervised loss supports only masked MSE (labels that are NaN are excluded via mask); the pretrain loss (the paper's self-supervised objective) is separate and not selected through this kwarg. Any other loss string raises ValueError on first use.

Source

Thrown at qlib/contrib/model/pytorch_tabnet.py:372

                loss = self.pretrain_loss_fn(label, f, S_mask)
            losses.append(loss.item())

        return np.mean(losses)

    def pretrain_loss_fn(self, f_hat, f, S):
        """
        Pretrain loss function defined in the original paper, read "Tabular self-supervised learning" in https://arxiv.org/pdf/1908.07442.pdf
        """
        down_mean = torch.mean(f, dim=0)
        down = torch.sqrt(torch.sum(torch.square(f - down_mean), dim=0))
        up = (f_hat - f) * S
        return torch.sum(torch.square(up / down))

    def loss_fn(self, pred, label):
        mask = ~torch.isnan(label)
        if self.loss == "mse":
            return self.mse(pred[mask], label[mask])
        raise ValueError("unknown loss `%s`" % self.loss)

    def metric_fn(self, pred, label):
        mask = torch.isfinite(label)
        if self.metric in ("", "loss"):
            return -self.loss_fn(pred[mask], label[mask])
        raise ValueError("unknown metric `%s`" % self.metric)

    def mse(self, pred, label):
        loss = (pred - label) ** 2
        return torch.mean(loss)


class FinetuneModel(nn.Module):
    """
    FinuetuneModel for adding a layer by the end
    """

    def __init__(self, input_dim, output_dim, trained_model):

View on GitHub (pinned to 79633dd950)

Solutions

  1. Set loss: 'mse' (the only supported supervised loss).
  2. Subclass the qlib TabNet model and override loss_fn() for custom supervised losses; keep the NaN mask.

Example fix

# before
kwargs:
  loss: binary_crossentropy

# after
kwargs:
  loss: mse
Defensive patterns

Strategy: validation

Validate before calling

assert config.get("loss", "mse") == "mse", "qlib TabNet supports only loss='mse' (pretrain loss is separate)"

Type guard

def is_supported_tabnet_loss(loss: str) -> bool:
    return loss == "mse"

Try / catch

try:
    model.fit(dataset)
except ValueError as e:
    if "unknown loss" in str(e):
        raise ValueError("TabNet's supervised loss is 'mse' only; override loss_fn() for custom losses") from e
    raise

Prevention

When it happens

Trigger: Setting loss to anything but 'mse' in TabNet kwargs and calling fit(); triggered during train/test epoch loss computation. Note metric ('', 'loss') also calls loss_fn.

Common situations: Copying loss names from the original pytorch-tabnet library (e.g. its classification losses) into qlib kwargs; typos in YAML.

Related errors


AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15). Data as JSON: /api/errors/41e995eb2fd2a4b0. Report an issue: GitHub.