microsoft/qlib · error · ValueError
unknown loss `%s`
Error message
unknown loss `%s`
What it means
Raised by GRUModel.loss_fn when self.loss is not the literal "mse". Like the general NN model, GRU only implements plain MSE (no weighting) and dispatches via a single if; every other value reaches the raise on the first training batch.
Source
Thrown at qlib/contrib/model/pytorch_gru.py:146
self.fitted = False
self.gru_model.to(self.device)
@property
def use_gpu(self):
return self.device != torch.device("cpu")
def mse(self, pred, label):
loss = (pred - label) ** 2
return torch.mean(loss)
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 train_epoch(self, x_train, y_train):
x_train_values = x_train.values
y_train_values = np.squeeze(y_train.values)
self.gru_model.train()
indices = np.arange(len(x_train_values))
np.random.shuffle(indices)
View on GitHub (pinned to 79633dd950)
Solutions
- Set loss="mse" (the only supported value for GRUModel).
- Subclass GRUModel and override loss_fn/mse to add your loss before the raise.
Example fix
# before GRUModel(loss="mae", ...) # after GRUModel(loss="mse", ...)
Defensive patterns
Strategy: validation
Validate before calling
assert params["loss"] == "mse", "GRUModel supports only loss='mse'"
Type guard
def is_supported_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("GRUModel only supports loss='mse'") from e
raise Prevention
- Treat 'mse' as the default and only loss for GRU/LSTM-family qlib models unless you subclass.
- Centralize model hyper-parameter validation in your experiment harness.
When it happens
Trigger: GRUModel(loss="huber") or any non-"mse" string, then fit() -> train_epoch -> loss_fn on the first batch. Also reached indirectly through metric_fn when metric is ""/"loss".
Common situations: Copying hyper-parameter blocks between qlib model classes where supported loss names differ; attempting to use a custom loss by name without subclassing.
Related errors
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/3d0ce0b437fcbdfb.
Report an issue: GitHub.