Skip to content

LightGBM 4.0+ Compatibility: TypeError when early_stopping_rounds=None #2231

@Olcmyk

Description

@Olcmyk

🐛 Bug Description

LightGBM 4.0+ compatibility issue: TypeError: early_stopping_round should be an integer. Got 'NoneType' when running DDG-DA workflow.

In LightGBM 4.0+, the lgb.early_stopping() function no longer accepts None as a parameter. When early_stopping_rounds=None is passed to the model, it causes a TypeError during training.

To Reproduce

Important: This bug is masked by the zscore unpickling error. To reproduce this bug, you must first apply PR #2230 (commit b5e58a006469c80caf4a4f228c3b6e57a0da8c50), otherwise you will encounter the zscore bug first.

Steps to reproduce the behavior:

  1. Apply PR Fix/pickle whitelist zscore #2230 to fix the zscore unpickling issue:

    git fetch origin pull/2230/head:fix/pickle-whitelist-zscore
    git checkout fix/pickle-whitelist-zscore
    # Or checkout commit b5e58a006469c80caf4a4f228c3b6e57a0da8c50
    pip install -e .
  2. Navigate to DDG-DA example directory:

    cd examples/benchmarks_dynamic/DDG-DA
  3. Clean previous runs and execute the workflow:

    rm -rf mlruns
    python workflow.py run
  4. The error occurs during the meta model training phase.

Expected Behavior

The DDG-DA workflow should run successfully without TypeError. When early_stopping_rounds=None, the code should either:

  • Skip the early stopping callback entirely, or
  • Use a default valid integer value

Screenshot

Error traceback:

TypeError: early_stopping_round should be an integer. Got 'NoneType'

File "/root/autodl-tmp/qlib-new/qlib/contrib/model/gbdt.py", line 71, in fit
    early_stopping_callback = lgb.early_stopping(
File "/root/miniconda3/lib/python3.8/site-packages/lightgbm/callback.py", line 493, in early_stopping
    return _EarlyStoppingCallback(
File "/root/miniconda3/lib/python3.8/site-packages/lightgbm/callback.py", line 288, in __init__
    self.enabled = _should_enable_early_stopping(stopping_rounds)
File "/root/miniconda3/lib/python3.8/site-packages/lightgbm/callback.py", line 450, in _should_enable_early_stopping
    raise TypeError(f"early_stopping_round should be an integer. Got '{type(stopping_rounds).__name__}'")

Environment

  • Qlib version: 0.9.8.dev33
  • Python version: 3.8.10
  • OS: Linux (Ubuntu 22.04)
  • LightGBM version: 4.6.0
  • Commit number: b5e58a006469c80caf4a4f228c3b6e57a0da8c50 (PR Fix/pickle whitelist zscore #2230)

Additional Notes

Root Cause:
In qlib/contrib/model/gbdt.py line 71-73:

early_stopping_callback = lgb.early_stopping(
    self.early_stopping_rounds if early_stopping_rounds is None else early_stopping_rounds
)

When self.early_stopping_rounds is None (or when early_stopping_rounds parameter is explicitly set to None), this code passes None to lgb.early_stopping(), which is not allowed in LightGBM 4.0+.

Suggested Fix:
Only create the early stopping callback when the value is not None:

callbacks = [verbose_eval_callback, evals_result_callback]
if early_stopping_rounds is not None or self.early_stopping_rounds is not None:
    stopping_rounds = self.early_stopping_rounds if early_stopping_rounds is None else early_stopping_rounds
    callbacks.insert(0, lgb.early_stopping(stopping_rounds))

Related Issues:

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions