Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions qlib/contrib/model/gbdt.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,25 @@ def fit(
evals_result = {} # in case of unsafety of Python default values
ds_l = self._prepare_data(dataset, reweighter)
ds, names = list(zip(*ds_l))
early_stopping_callback = lgb.early_stopping(
self.early_stopping_rounds if early_stopping_rounds is None else early_stopping_rounds
early_stopping_rounds = (
self.early_stopping_rounds
if early_stopping_rounds is None
else early_stopping_rounds
)
callbacks = []
if early_stopping_rounds is not None:
callbacks.append(lgb.early_stopping(early_stopping_rounds))
# NOTE: if you encounter error here. Please upgrade your lightgbm
verbose_eval_callback = lgb.log_evaluation(period=verbose_eval)
evals_result_callback = lgb.record_evaluation(evals_result)
callbacks.extend([verbose_eval_callback, evals_result_callback])
self.model = lgb.train(
self.params,
ds[0], # training dataset
num_boost_round=self.num_boost_round if num_boost_round is None else num_boost_round,
valid_sets=ds,
valid_names=names,
callbacks=[early_stopping_callback, verbose_eval_callback, evals_result_callback],
callbacks=callbacks,
**kwargs,
)
for k in names:
Expand Down
7 changes: 5 additions & 2 deletions qlib/contrib/model/highfreq_gdbt_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,19 @@ def fit(
if evals_result is None:
evals_result = dict()
dtrain, dvalid = self._prepare_data(dataset)
early_stopping_callback = lgb.early_stopping(early_stopping_rounds)
callbacks = []
if early_stopping_rounds is not None:
callbacks.append(lgb.early_stopping(early_stopping_rounds))
verbose_eval_callback = lgb.log_evaluation(period=verbose_eval)
evals_result_callback = lgb.record_evaluation(evals_result)
callbacks.extend([verbose_eval_callback, evals_result_callback])
self.model = lgb.train(
self.params,
dtrain,
num_boost_round=num_boost_round,
valid_sets=[dtrain, dvalid],
valid_names=["train", "valid"],
callbacks=[early_stopping_callback, verbose_eval_callback, evals_result_callback],
callbacks=callbacks,
)
evals_result["train"] = list(evals_result["train"].values())[0]
evals_result["valid"] = list(evals_result["valid"].values())[0]
Expand Down
65 changes: 65 additions & 0 deletions tests/model/test_lightgbm_early_stopping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from qlib.contrib.model import gbdt, highfreq_gdbt_model


def test_lgb_model_skips_none_early_stopping(monkeypatch):
early_stopping_calls = []
train_kwargs = {}
model = gbdt.LGBModel(early_stopping_rounds=None)

monkeypatch.setattr(
model,
"_prepare_data",
lambda dataset, reweighter=None: [("train-dataset", "train")],
)
monkeypatch.setattr(
gbdt.lgb,
"early_stopping",
lambda rounds: early_stopping_calls.append(rounds) or "early",
)
monkeypatch.setattr(gbdt.lgb, "log_evaluation", lambda period: "log")
monkeypatch.setattr(gbdt.lgb, "record_evaluation", lambda evals_result: "record")

def train(*args, **kwargs):
train_kwargs.update(kwargs)
return object()

monkeypatch.setattr(gbdt.lgb, "train", train)

model.fit(object(), evals_result={"train": {}})

assert early_stopping_calls == []
assert train_kwargs["callbacks"] == ["log", "record"]


def test_hflgb_model_skips_none_early_stopping(monkeypatch):
early_stopping_calls = []
train_kwargs = {}
model = highfreq_gdbt_model.HFLGBModel()

monkeypatch.setattr(
model, "_prepare_data", lambda dataset: ("train-dataset", "valid-dataset")
)
monkeypatch.setattr(
highfreq_gdbt_model.lgb,
"early_stopping",
lambda rounds: early_stopping_calls.append(rounds) or "early",
)
monkeypatch.setattr(highfreq_gdbt_model.lgb, "log_evaluation", lambda period: "log")
monkeypatch.setattr(
highfreq_gdbt_model.lgb, "record_evaluation", lambda evals_result: "record"
)

def train(*args, **kwargs):
train_kwargs.update(kwargs)
return object()

monkeypatch.setattr(highfreq_gdbt_model.lgb, "train", train)

model.fit(
object(),
early_stopping_rounds=None,
evals_result={"train": {"loss": [1.0]}, "valid": {"loss": [1.1]}},
)

assert early_stopping_calls == []
assert train_kwargs["callbacks"] == ["log", "record"]