microsoft/qlib · error · ValueError

XGBoost doesn't support multi-label training

Error message

XGBoost doesn't support multi-label training

What it means

Raised by XGBModel.fit when the training labels are not a single column. The wrapper squeezes labels to a 1D array for xgb.DMatrix, and only accepts y_train.values.ndim == 2 with exactly one label column; anything else (multi-column labels, 0-d, or 3-d arrays) is rejected because XGBoost's booster API requires a single-label target.

Source

Thrown at qlib/contrib/model/xgboost.py:45

        early_stopping_rounds=50,
        verbose_eval=20,
        evals_result=dict(),
        reweighter=None,
        **kwargs,
    ):
        df_train, df_valid = dataset.prepare(
            ["train", "valid"],
            col_set=["feature", "label"],
            data_key=DataHandlerLP.DK_L,
        )
        x_train, y_train = df_train["feature"], df_train["label"]
        x_valid, y_valid = df_valid["feature"], 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_1d, y_valid_1d = np.squeeze(y_train.values), np.squeeze(y_valid.values)
        else:
            raise ValueError("XGBoost doesn't support multi-label training")

        if reweighter is None:
            w_train = None
            w_valid = None
        elif isinstance(reweighter, Reweighter):
            w_train = reweighter.reweight(df_train)
            w_valid = reweighter.reweight(df_valid)
        else:
            raise ValueError("Unsupported reweighter type.")

        dtrain = xgb.DMatrix(x_train.values, label=y_train_1d, weight=w_train)
        dvalid = xgb.DMatrix(x_valid.values, label=y_valid_1d, weight=w_valid)
        self.model = xgb.train(
            self._params,
            dtrain=dtrain,
            num_boost_round=num_boost_round,
            evals=[(dtrain, "train"), (dvalid, "valid")],
            early_stopping_rounds=early_stopping_rounds,

View on GitHub (pinned to 79633dd950)

Solutions

  1. Restrict the label to a single column, e.g. dataset.prepare(..., col_set=['feature','label']) after configuring the handler with only one label (drop extra LABELx columns via data_key/col_set filters or drop_raw_label).
  2. If you have multiple horizons, train one XGBModel per label column by slicing the prepared dataframe per label.
  3. If you truly need multi-label regression, switch to a model that supports it (e.g. a multi-output sklearn estimator wrapped in qlib, or a neural model) instead of XGBoost.

Example fix

# before
# handler label config exposes LABEL0 and LABEL1 -> 2 label columns
model.fit(dataset)  # ValueError: XGBoost doesn't support multi-label training

# after
# keep only one label column in the data handler config
handler_config = {
    "class": "Alpha158",
    "kwargs": {"label": ["Ref($close, -2) / Ref($close, -1) - 1"]},  # single label
}
model.fit(dataset)
Defensive patterns

Strategy: validation

Validate before calling

y = dataset.prepare("train", col_set="label", data_key=DataHandlerLP.DK_L)
if y.values.ndim != 2 or y.values.shape[1] != 1:
    raise RuntimeError(f"XGBModel needs exactly 1 label column, got shape {y.values.shape}")
model.fit(dataset)

Type guard

def is_single_label(dataset) -> bool:
    y = dataset.prepare("train", col_set="label", data_key=DataHandlerLP.DK_L)
    return y.values.ndim == 2 and y.values.shape[1] == 1

Try / catch

try:
    model.fit(dataset)
except ValueError as e:
    if "multi-label" in str(e):
        # slice to one label column or reconfigure the handler's label expression
        ...
    raise

Prevention

When it happens

Trigger: Calling fit() with a dataset whose label col_set resolves to multiple columns, e.g. LABEL0 and LABEL1 both selected, or a custom label expression list producing >1 column. Also triggered if the label handler returns a shape that is not (n, 1).

Common situations: Alpha158/Alpha360 datasets configured to expose multiple labels (e.g. LABEL0 plus LABEL5 for horizon studies); custom DataHandlerLP with label expression list of length > 1; users assuming tree models support multi-output like some sklearn estimators do.

Related errors


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