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 LGBModel._prepare_data when the label block is not a single column. LightGBM's Dataset label must be 1D, so qlib squeezes only (N, 1) label arrays and rejects label DataFrames with multiple columns.

Source

Thrown at qlib/contrib/model/gbdt.py:46

    def _prepare_data(self, dataset: DatasetH, reweighter=None) -> List[Tuple[lgb.Dataset, str]]:
        """
        The motivation of current version is to make validation optional
        - train segment is necessary;
        """
        ds_l = []
        assert "train" in dataset.segments
        for key in ["train", "valid"]:
            if key in dataset.segments:
                df = dataset.prepare(key, col_set=["feature", "label"], data_key=DataHandlerLP.DK_L)
                if df.empty:
                    raise ValueError("Empty data from dataset, please check your dataset config.")
                x, y = df["feature"], df["label"]

                # Lightgbm need 1D array as its label
                if y.values.ndim == 2 and y.values.shape[1] == 1:
                    y = np.squeeze(y.values)
                else:
                    raise ValueError("LightGBM doesn't support multi-label training")

                if reweighter is None:
                    w = None
                elif isinstance(reweighter, Reweighter):
                    w = reweighter.reweight(df)
                else:
                    raise ValueError("Unsupported reweighter type.")
                ds_l.append((lgb.Dataset(x.values, label=y, weight=w, free_raw_data=False), key))
        return ds_l

    def fit(
        self,
        dataset: DatasetH,
        num_boost_round=None,
        early_stopping_rounds=None,
        verbose_eval=20,
        evals_result=None,
        reweighter=None,

View on GitHub (pinned to 79633dd950)

Solutions

  1. Keep the label list to one expression in the data handler config
  2. Move extra targets into features or use a multi-output model (e.g. PyTorch-based)

Example fix

# before
label: ["Ref($close, -2)/Ref($close, -1) - 1", "Mean($close, 3)/$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.ndim == 2 and y.values.shape[1] == 1, "LightGBM requires a single-column (1D) label"

Prevention

When it happens

Trigger: Calling LGBModel.fit with a handler label of multiple expressions (shape[1] > 1); e.g. label: [expr1, expr2] in workflow config.

Common situations: Sharing one handler config across models where only some support multi-label; incremental label additions for custom evaluation.

Related errors


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