microsoft/qlib · error · ValueError

Unsupported reweighter type.

Error message

Unsupported reweighter type.

What it means

Thrown by CatBoostModel.fit when the reweighter argument is neither None nor an instance of qlib.model.base.Reweighter. The fit signature only accepts those two options; arbitrary callables (e.g. sklearn-style sample_weight functions) are not supported and rejected before training.

Source

Thrown at qlib/contrib/model/catboost_model.py:61

        if df_train.empty or df_valid.empty:
            raise ValueError("Empty data from dataset, please check your dataset config.")
        x_train, y_train = df_train["feature"], df_train["label"]
        x_valid, y_valid = df_valid["feature"], df_valid["label"]

        # CatBoost needs 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("CatBoost 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).values
            w_valid = reweighter.reweight(df_valid).values
        else:
            raise ValueError("Unsupported reweighter type.")

        train_pool = Pool(data=x_train, label=y_train_1d, weight=w_train)
        valid_pool = Pool(data=x_valid, label=y_valid_1d, weight=w_valid)

        # Initialize the catboost model
        self._params["iterations"] = num_boost_round
        self._params["early_stopping_rounds"] = early_stopping_rounds
        self._params["verbose_eval"] = verbose_eval
        self._params["task_type"] = "GPU" if get_gpu_device_count() > 0 else "CPU"
        self.model = CatBoost(self._params, **kwargs)

        # train the model
        self.model.fit(train_pool, eval_set=valid_pool, use_best_model=True, **kwargs)

        evals_result = self.model.get_evals_result()
        evals_result["train"] = list(evals_result["learn"].values())[0]
        evals_result["valid"] = list(evals_result["validation"].values())[0]

View on GitHub (pinned to 79633dd950)

Solutions

  1. Wrap custom logic in a qlib Reweighter subclass implementing reweight(df) -> pd.Series
  2. Pass reweighter=None if no reweighting is needed

Example fix

# before
model.fit(dataset, reweighter=lambda df: np.ones(len(df)))

# after
from qlib.model.base import Reweighter

class OnesReweighter(Reweighter):
    def reweight(self, df):
        return pd.Series(np.ones(len(df)), index=df.index)

model.fit(dataset, reweighter=OnesReweighter())
Defensive patterns

Strategy: type-guard

Validate before calling

from qlib.model.base import Reweighter
assert reweighter is None or isinstance(reweighter, Reweighter), "reweighter must be None or Reweighter"

Type guard

from qlib.model.base import Reweighter

def is_valid_reweighter(r) -> bool:
    return r is None or isinstance(r, Reweighter)

Prevention

When it happens

Trigger: Calling fit(dataset, reweighter=my_func) where my_func is a plain function or lambda; passing a custom class that duck-types reweight() but does not subclass Reweighter; passing a numpy array of weights.

Common situations: Porting code from another framework that takes sample_weight arrays directly; implementing a custom sample-weighting scheme without knowing qlib's Reweighter contract.

Related errors


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