microsoft/qlib · error · ValueError
LightGBM doesn't support multi-label training
Error message
LightGBM doesn't support multi-label training
What it means
Thrown by DEnsembleModel._prepare_data_gbm when the label block is not exactly one column. The underlying base model is LightGBM, whose Dataset label must be 1D, so qlib only squeezes labels of shape (N, 1) and rejects multi-column labels.
Source
Thrown at qlib/contrib/model/double_ensemble.py:134
dtrain,
num_boost_round=self.epochs,
valid_sets=[dtrain, dvalid],
valid_names=["train", "valid"],
callbacks=callbacks,
)
evals_result["train"] = list(evals_result["train"].values())[0]
evals_result["valid"] = list(evals_result["valid"].values())[0]
return model
def _prepare_data_gbm(self, df_train, df_valid, weights, features):
x_train, y_train = df_train["feature"].loc[:, features], df_train["label"]
x_valid, y_valid = df_valid["feature"].loc[:, features], df_valid["label"]
# Lightgbm need 1D array as its label
if y_train.values.ndim == 2 and y_train.values.shape[1] == 1:
y_train, y_valid = np.squeeze(y_train.values), np.squeeze(y_valid.values)
else:
raise ValueError("LightGBM doesn't support multi-label training")
dtrain = lgb.Dataset(x_train, label=y_train, weight=weights)
dvalid = lgb.Dataset(x_valid, label=y_valid)
return dtrain, dvalid
def sample_reweight(self, loss_curve, loss_values, k_th):
"""
the SR module of Double Ensemble
:param loss_curve: the shape is NxT
the loss curve for the previous sub-model, where the element (i, t) if the error on the i-th sample
after the t-th iteration in the training of the previous sub-model.
:param loss_values: the shape is N
the loss of the current ensemble on the i-th sample.
:param k_th: the index of the current sub-model, starting from 1
:return: weights
the weights for all the samples.
"""
# normalize loss_curve and loss_values with rankingView on GitHub (pinned to 79633dd950)
Solutions
- Set the handler label to a single expression, e.g. label: ["Ref($close, -2)/Ref($close, -1) - 1"]
- Use a multi-output-capable model if you truly need several targets
Example fix
# before (handler config) label: ["Ref($close, -2)/Ref($close, -1) - 1", "Ref($high, -1)/$close - 1"] # after label: ["Ref($close, -2)/Ref($close, -1) - 1"]
Defensive patterns
Strategy: validation
Validate before calling
y = dataset.prepare("train", col_set="label", data_key="learn")
assert y.values.shape[1] == 1, "Double Ensemble (LightGBM base) supports only single-column labels" Prevention
- Use single-label handler configs for all LightGBM-based models
- Assert label width once at workflow startup when configs are shared
When it happens
Trigger: Running Double Ensemble (workflow 'DENsemble' / model.cls: DEnsembleModel) with a handler whose label list has more than one expression.
Common situations: Reusing a multi-label handler config from another model; adding auxiliary label columns for analysis.
Related errors
- LightGBM doesn't support multi-label training
- LightGBM doesn't support multi-label training
- CatBoost doesn't support multi-label training
- The length of sample_ratios should be equal to bins_fs.
- The length of sub_weights should be equal to num_models.
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/3e956d56b8e23ea2.
Report an issue: GitHub.