microsoft/qlib · error · ValueError

The length of sample_ratios should be equal to bins_fs.

Error message

The length of sample_ratios should be equal to bins_fs.

What it means

Thrown by DEnsembleModel's __init__ when len(sample_ratios) != bins_fs. The Double Ensemble algorithm bins features into bins_fs groups and applies one sampling ratio per bin, so the two parameters must agree in length. The default sample_ratios has 5 entries, matching the default bins_fs of 5.

Source

Thrown at qlib/contrib/model/double_ensemble.py:50

        epochs=100,
        early_stopping_rounds=None,
        **kwargs,
    ):
        self.base_model = base_model  # "gbm" or "mlp", specifically, we use lgbm for "gbm"
        self.num_models = num_models  # the number of sub-models
        self.enable_sr = enable_sr
        self.enable_fs = enable_fs
        self.alpha1 = alpha1
        self.alpha2 = alpha2
        self.bins_sr = bins_sr
        self.bins_fs = bins_fs
        self.decay = decay
        if sample_ratios is None:  # the default values for sample_ratios
            sample_ratios = [0.8, 0.7, 0.6, 0.5, 0.4]
        if sub_weights is None:  # the default values for sub_weights
            sub_weights = [1] * self.num_models
        if not len(sample_ratios) == bins_fs:
            raise ValueError("The length of sample_ratios should be equal to bins_fs.")
        self.sample_ratios = sample_ratios
        if not len(sub_weights) == num_models:
            raise ValueError("The length of sub_weights should be equal to num_models.")
        self.sub_weights = sub_weights
        self.epochs = epochs
        self.logger = get_module_logger("DEnsembleModel")
        self.logger.info("Double Ensemble Model...")
        self.ensemble = []  # the current ensemble model, a list contains all the sub-models
        self.sub_features = []  # the features for each sub model in the form of pandas.Index
        self.params = {"objective": loss}
        self.params.update(kwargs)
        self.loss = loss
        self.early_stopping_rounds = early_stopping_rounds

    def fit(self, dataset: DatasetH):
        df_train, df_valid = dataset.prepare(
            ["train", "valid"], col_set=["feature", "label"], data_key=DataHandlerLP.DK_L
        )

View on GitHub (pinned to 79633dd950)

Solutions

  1. Make len(sample_ratios) equal bins_fs, e.g. DEnsembleModel(bins_fs=3, sample_ratios=[0.8, 0.7, 0.6])
  2. Or change bins_fs to match the length of your sample_ratios list

Example fix

# before
model = DEnsembleModel(num_models=5, bins_fs=3)  # default sample_ratios has len 5

# after
model = DEnsembleModel(num_models=5, bins_fs=3, sample_ratios=[0.8, 0.7, 0.6])
Defensive patterns

Strategy: validation

Validate before calling

if sample_ratios is None:
    sample_ratios = [0.8, 0.7, 0.6, 0.5, 0.4][:bins_fs]
assert len(sample_ratios) == bins_fs, "sample_ratios length must match bins_fs"

Prevention

When it happens

Trigger: Passing DEnsembleModel(bins_fs=3) while leaving sample_ratios at its default [0.8, 0.7, 0.6, 0.5, 0.4]; or supplying a custom sample_ratios list whose length differs from bins_fs.

Common situations: Tuning the number of feature-select bins without adjusting the ratio list; copying hyperparameters between configs where one of the two was changed independently.

Related errors


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