microsoft/qlib · error · ValueError
unknown loss `%s`
Error message
unknown loss `%s`
What it means
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.
Source
Thrown at qlib/contrib/model/pytorch_general_nn.py:164
@property
def use_gpu(self):
return self.device != torch.device("cpu")
def mse(self, pred, label, weight):
loss = weight * (pred - label) ** 2
return torch.mean(loss)
def loss_fn(self, pred, label, weight=None):
mask = ~torch.isnan(label)
if weight is None:
weight = torch.ones_like(label)
if self.loss == "mse":
return self.mse(pred[mask], label[mask].view(-1, 1), weight[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 _get_fl(self, data: torch.Tensor):
"""
get feature and label from data
- Handle the different data shape of time series and tabular data
Parameters
----------
data : torch.Tensor
input data which maybe 3 dimension or 2 dimensionView on GitHub (pinned to 79633dd950)
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).
Example fix
# before model = DNNModelPytorch(loss="mae", lr=0.001, ...) # ValueError at first batch # after model = DNNModelPytorch(loss="mse", lr=0.001, ...)
Defensive patterns
Strategy: validation
Validate before calling
from qlib.contrib.model.pytorch_general_nn import DNNModelPytorch
allowed = {"mse"}
assert params["loss"] in allowed, f"loss must be one of {allowed}, got {params['loss']!r}" Type guard
def is_supported_loss(loss: str) -> bool:
return isinstance(loss, str) and loss in {"mse"} Try / catch
try:
model.fit(dataset)
except ValueError as e:
if "unknown loss" in str(e):
raise ValueError(f"DNNModelPytorch only supports loss='mse'; got {model.loss!r}") from e
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/12be2e29541d3d54.
Report an issue: GitHub.