Skip to content

Commit 911a902

Browse files
authored
Merge model compatibility fixes from 1.0rc branch. (dmlc#5305)
* Port test model compatibility. * Port logit model fix. dmlc#5248 dmlc#5281
1 parent 29eeea7 commit 911a902

File tree

19 files changed

+550
-106
lines changed

19 files changed

+550
-106
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ option(USE_SANITIZER "Use santizer flags" OFF)
4949
option(SANITIZER_PATH "Path to sanitizes.")
5050
set(ENABLED_SANITIZERS "address" "leak" CACHE STRING
5151
"Semicolon separated list of sanitizer names. E.g 'address;leak'. Supported sanitizers are
52-
address, leak and thread.")
52+
address, leak, undefined and thread.")
5353
## Plugins
5454
option(PLUGIN_LZ4 "Build lz4 plugin" OFF)
5555
option(PLUGIN_DENSE_PARSER "Build dense parser plugin" OFF)

R-package/R/xgb.Booster.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ xgb.Booster.complete <- function(object, saveraw = TRUE) {
139139
#' @param reshape whether to reshape the vector of predictions to a matrix form when there are several
140140
#' prediction outputs per case. This option has no effect when either of predleaf, predcontrib,
141141
#' or predinteraction flags is TRUE.
142+
#' @param training whether is the prediction result used for training. For dart booster,
143+
#' training predicting will perform dropout.
142144
#' @param ... Parameters passed to \code{predict.xgb.Booster}
143145
#'
144146
#' @details

R-package/man/agaricus.test.Rd

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

R-package/man/agaricus.train.Rd

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

R-package/man/predict.xgb.Booster.Rd

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

R-package/tests/testthat/test_custom_objective.R

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ num_round <- 2
3131
test_that("custom objective works", {
3232
bst <- xgb.train(param, dtrain, num_round, watchlist)
3333
expect_equal(class(bst), "xgb.Booster")
34-
expect_equal(length(bst$raw), 1100)
3534
expect_false(is.null(bst$evaluation_log))
3635
expect_false(is.null(bst$evaluation_log$eval_error))
3736
expect_lt(bst$evaluation_log[num_round, eval_error], 0.03)
@@ -58,5 +57,4 @@ test_that("custom objective using DMatrix attr works", {
5857
param$objective = logregobjattr
5958
bst <- xgb.train(param, dtrain, num_round, watchlist)
6059
expect_equal(class(bst), "xgb.Booster")
61-
expect_equal(length(bst$raw), 1100)
6260
})

doc/python/convert_090to100.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
'''This is a simple script that converts a pickled XGBoost
2+
Scikit-Learn interface object from 0.90 to a native model. Pickle
3+
format is not stable as it's a direct serialization of Python object.
4+
We advice not to use it when stability is needed.
5+
6+
'''
7+
import pickle
8+
import json
9+
import os
10+
import argparse
11+
import numpy as np
12+
import xgboost
13+
import warnings
14+
15+
16+
def save_label_encoder(le):
17+
'''Save the label encoder in XGBClassifier'''
18+
meta = dict()
19+
for k, v in le.__dict__.items():
20+
if isinstance(v, np.ndarray):
21+
meta[k] = v.tolist()
22+
else:
23+
meta[k] = v
24+
return meta
25+
26+
27+
def xgboost_skl_90to100(skl_model):
28+
'''Extract the model and related metadata in SKL model.'''
29+
model = {}
30+
with open(skl_model, 'rb') as fd:
31+
old = pickle.load(fd)
32+
if not isinstance(old, xgboost.XGBModel):
33+
raise TypeError(
34+
'The script only handes Scikit-Learn interface object')
35+
36+
# Save Scikit-Learn specific Python attributes into a JSON document.
37+
for k, v in old.__dict__.items():
38+
if k == '_le':
39+
model[k] = save_label_encoder(v)
40+
elif k == 'classes_':
41+
model[k] = v.tolist()
42+
elif k == '_Booster':
43+
continue
44+
else:
45+
try:
46+
json.dumps({k: v})
47+
model[k] = v
48+
except TypeError:
49+
warnings.warn(str(k) + ' is not saved in Scikit-Learn meta.')
50+
booster = old.get_booster()
51+
# Store the JSON serialization as an attribute
52+
booster.set_attr(scikit_learn=json.dumps(model))
53+
54+
# Save it into a native model.
55+
i = 0
56+
while True:
57+
path = 'xgboost_native_model_from_' + skl_model + '-' + str(i) + '.bin'
58+
if os.path.exists(path):
59+
i += 1
60+
continue
61+
booster.save_model(path)
62+
break
63+
64+
65+
if __name__ == '__main__':
66+
assert xgboost.__version__ != '1.0.0', ('Please use the XGBoost version'
67+
' that generates this pickle.')
68+
parser = argparse.ArgumentParser(
69+
description=('A simple script to convert pickle generated by'
70+
' XGBoost 0.90 to XGBoost 1.0.0 model (not pickle).'))
71+
parser.add_argument(
72+
'--old-pickle',
73+
type=str,
74+
help='Path to old pickle file of Scikit-Learn interface object. '
75+
'Will output a native model converted from this pickle file',
76+
required=True)
77+
args = parser.parse_args()
78+
79+
xgboost_skl_90to100(args.old_pickle)

doc/tutorials/saving_model.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,12 @@ Loading pickled file from different version of XGBoost
9191

9292
As noted, pickled model is neither portable nor stable, but in some cases the pickled
9393
models are valuable. One way to restore it in the future is to load it back with that
94-
specific version of Python and XGBoost, export the model by calling `save_model`.
94+
specific version of Python and XGBoost, export the model by calling `save_model`. To help
95+
easing the mitigation, we created a simple script for converting pickled XGBoost 0.90
96+
Scikit-Learn interface object to XGBoost 1.0.0 native model. Please note that the script
97+
suits simple use cases, and it's advised not to use pickle when stability is needed.
98+
It's located in ``xgboost/doc/python`` with the name ``convert_090to100.py``. See
99+
comments in the script for more details.
95100

96101
********************************************************
97102
Saving and Loading the internal parameters configuration

include/xgboost/learner.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ struct LearnerModelParam {
208208
// As the old `LearnerModelParamLegacy` is still used by binary IO, we keep
209209
// this one as an immutable copy.
210210
LearnerModelParam(LearnerModelParamLegacy const& user_param, float base_margin);
211+
/* \brief Whether this parameter is initialized with LearnerModelParamLegacy. */
212+
bool Initialized() const { return num_feature != 0; }
211213
};
212214

213215
} // namespace xgboost

python-package/xgboost/dask.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ def fit(self,
600600
results = train(self.client, params, dtrain,
601601
num_boost_round=self.get_num_boosting_rounds(),
602602
evals=evals)
603+
# pylint: disable=attribute-defined-outside-init
603604
self._Booster = results['booster']
604605
# pylint: disable=attribute-defined-outside-init
605606
self.evals_result_ = results['history']

0 commit comments

Comments
 (0)