From 3eb1279bbf427743325c823979f323d4140b51db Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Sat, 25 Jan 2020 11:26:46 +0800 Subject: [PATCH] Config for linear updaters. (#5222) --- include/xgboost/linear_updater.h | 5 ++- src/gbm/gblinear.cc | 7 +++++ src/linear/updater_coordinate.cc | 13 ++++++++ src/linear/updater_gpu_coordinate.cu | 12 ++++++++ src/linear/updater_shotgun.cc | 9 ++++++ tests/cpp/c_api/test_c_api.cc | 2 +- tests/cpp/gbm/test_gblinear.cc | 2 +- tests/cpp/gbm/test_gbtree.cc | 6 ++-- tests/cpp/linear/test_json_io.h | 41 +++++++++++++++++++++++++ tests/cpp/linear/test_linear.cc | 13 ++++++-- tests/cpp/linear/test_linear.cu | 5 +++ tests/cpp/objective/test_ranking_obj.cc | 2 +- tests/cpp/test_learner.cc | 2 +- tests/cpp/tree/test_tree_model.cc | 2 +- 14 files changed, 110 insertions(+), 11 deletions(-) create mode 100644 tests/cpp/linear/test_json_io.h diff --git a/include/xgboost/linear_updater.h b/include/xgboost/linear_updater.h index 4cbf84f9f..30803b96b 100644 --- a/include/xgboost/linear_updater.h +++ b/include/xgboost/linear_updater.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,8 @@ namespace xgboost { +class Json; + namespace gbm { class GBLinearModel; } // namespace gbm @@ -24,7 +27,7 @@ class GBLinearModel; /*! * \brief interface of linear updater */ -class LinearUpdater { +class LinearUpdater : public Configurable { protected: GenericParameter const* learner_param_; diff --git a/src/gbm/gblinear.cc b/src/gbm/gblinear.cc index a0108e21a..db45dae42 100644 --- a/src/gbm/gblinear.cc +++ b/src/gbm/gblinear.cc @@ -102,11 +102,18 @@ class GBLinear : public GradientBooster { void LoadConfig(Json const& in) override { CHECK_EQ(get(in["name"]), "gblinear"); fromJson(in["gblinear_train_param"], ¶m_); + updater_.reset(LinearUpdater::Create(param_.updater, generic_param_)); + this->updater_->LoadConfig(in["updater"]); } void SaveConfig(Json* p_out) const override { auto& out = *p_out; out["name"] = String{"gblinear"}; out["gblinear_train_param"] = toJson(param_); + + out["updater"] = Object(); + auto& j_updater = out["updater"]; + CHECK(this->updater_); + this->updater_->SaveConfig(&j_updater); } void DoBoost(DMatrix *p_fmat, diff --git a/src/linear/updater_coordinate.cc b/src/linear/updater_coordinate.cc index aeaf855f3..74e5d414a 100644 --- a/src/linear/updater_coordinate.cc +++ b/src/linear/updater_coordinate.cc @@ -7,6 +7,7 @@ #include "./param.h" #include "../common/timer.h" #include "coordinate_common.h" +#include "xgboost/json.h" namespace xgboost { namespace linear { @@ -32,6 +33,18 @@ class CoordinateUpdater : public LinearUpdater { selector_.reset(FeatureSelector::Create(tparam_.feature_selector)); monitor_.Init("CoordinateUpdater"); } + + void LoadConfig(Json const& in) override { + auto const& config = get(in); + fromJson(config.at("linear_train_param"), &tparam_); + fromJson(config.at("coordinate_param"), &cparam_); + } + void SaveConfig(Json* p_out) const override { + auto& out = *p_out; + out["linear_train_param"] = toJson(tparam_); + out["coordinate_param"] = toJson(cparam_); + } + void Update(HostDeviceVector *in_gpair, DMatrix *p_fmat, gbm::GBLinearModel *model, double sum_instance_weight) override { tparam_.DenormalizePenalties(sum_instance_weight); diff --git a/src/linear/updater_gpu_coordinate.cu b/src/linear/updater_gpu_coordinate.cu index 7eec2cc42..d5287fb70 100644 --- a/src/linear/updater_gpu_coordinate.cu +++ b/src/linear/updater_gpu_coordinate.cu @@ -37,10 +37,22 @@ class GPUCoordinateUpdater : public LinearUpdater { // NOLINT // set training parameter void Configure(Args const& args) override { tparam_.UpdateAllowUnknown(args); + coord_param_.UpdateAllowUnknown(args); selector_.reset(FeatureSelector::Create(tparam_.feature_selector)); monitor_.Init("GPUCoordinateUpdater"); } + void LoadConfig(Json const& in) override { + auto const& config = get(in); + fromJson(config.at("linear_train_param"), &tparam_); + fromJson(config.at("coordinate_param"), &coord_param_); + } + void SaveConfig(Json* p_out) const override { + auto& out = *p_out; + out["linear_train_param"] = toJson(tparam_); + out["coordinate_param"] = toJson(coord_param_); + } + void LazyInitDevice(DMatrix *p_fmat, const LearnerModelParam &model_param) { if (learner_param_->gpu_id < 0) return; diff --git a/src/linear/updater_shotgun.cc b/src/linear/updater_shotgun.cc index 5fcd27bd9..10cb7912b 100644 --- a/src/linear/updater_shotgun.cc +++ b/src/linear/updater_shotgun.cc @@ -23,6 +23,15 @@ class ShotgunUpdater : public LinearUpdater { } selector_.reset(FeatureSelector::Create(param_.feature_selector)); } + void LoadConfig(Json const& in) override { + auto const& config = get(in); + fromJson(config.at("linear_train_param"), ¶m_); + } + void SaveConfig(Json* p_out) const override { + auto& out = *p_out; + out["linear_train_param"] = toJson(param_); + } + void Update(HostDeviceVector *in_gpair, DMatrix *p_fmat, gbm::GBLinearModel *model, double sum_instance_weight) override { auto &gpair = in_gpair->HostVector(); diff --git a/tests/cpp/c_api/test_c_api.cc b/tests/cpp/c_api/test_c_api.cc index 1371d01e7..02c0e6126 100644 --- a/tests/cpp/c_api/test_c_api.cc +++ b/tests/cpp/c_api/test_c_api.cc @@ -112,7 +112,7 @@ TEST(c_api, ConfigIO) { delete pp_dmat; } -TEST(c_api, Json_ModelIO) { +TEST(c_api, JsonModelIO) { size_t constexpr kRows = 10; dmlc::TemporaryDirectory tempdir; diff --git a/tests/cpp/gbm/test_gblinear.cc b/tests/cpp/gbm/test_gblinear.cc index dbd7885e3..481e4a726 100644 --- a/tests/cpp/gbm/test_gblinear.cc +++ b/tests/cpp/gbm/test_gblinear.cc @@ -16,7 +16,7 @@ namespace xgboost { namespace gbm { -TEST(GBLinear, Json_IO) { +TEST(GBLinear, JsonIO) { size_t constexpr kRows = 16, kCols = 16; LearnerModelParam param; diff --git a/tests/cpp/gbm/test_gbtree.cc b/tests/cpp/gbm/test_gbtree.cc index 8533b8302..6c8a6a3dc 100644 --- a/tests/cpp/gbm/test_gbtree.cc +++ b/tests/cpp/gbm/test_gbtree.cc @@ -103,8 +103,8 @@ TEST(GBTree, ChoosePredictor) { } #endif // XGBOOST_USE_CUDA -// Some other parts of test are in `Tree.Json_IO'. -TEST(GBTree, Json_IO) { +// Some other parts of test are in `Tree.JsonIO'. +TEST(GBTree, JsonIO) { size_t constexpr kRows = 16, kCols = 16; LearnerModelParam mparam; @@ -143,7 +143,7 @@ TEST(GBTree, Json_IO) { ASSERT_EQ(get(j_train_param["num_parallel_tree"]), "1"); } -TEST(Dart, Json_IO) { +TEST(Dart, JsonIO) { size_t constexpr kRows = 16, kCols = 16; LearnerModelParam mparam; diff --git a/tests/cpp/linear/test_json_io.h b/tests/cpp/linear/test_json_io.h new file mode 100644 index 000000000..db8b49e98 --- /dev/null +++ b/tests/cpp/linear/test_json_io.h @@ -0,0 +1,41 @@ +/*! + * Copyright 2020 XGBoost contributors + */ +#ifndef XGBOOST_TEST_JSON_IO_H_ +#define XGBOOST_TEST_JSON_IO_H_ + +#include +#include +#include +#include "../helpers.h" +#include "../../../src/gbm/gblinear_model.h" + +namespace xgboost { +inline void TestUpdaterJsonIO(std::string updater_str) { + auto runtime = xgboost::CreateEmptyGenericParam(GPUIDX); + Json config_0 {Object() }; + + { + auto updater = std::unique_ptr( + xgboost::LinearUpdater::Create(updater_str, &runtime)); + updater->Configure({{"eta", std::to_string(3.14)}}); + updater->SaveConfig(&config_0); + } + + { + auto updater = std::unique_ptr( + xgboost::LinearUpdater::Create(updater_str, &runtime)); + updater->LoadConfig(config_0); + Json config_1 { Object() }; + updater->SaveConfig(&config_1); + + ASSERT_EQ(config_0, config_1); + auto eta = atof(get(config_1["linear_train_param"]["eta"]).c_str()); + ASSERT_NEAR(eta, 3.14, kRtEps); + } + +} + +} // namespace xgboost + +#endif // XGBOOST_TEST_JSON_IO_H_ diff --git a/tests/cpp/linear/test_linear.cc b/tests/cpp/linear/test_linear.cc index dd42b38c4..694c4d1a2 100644 --- a/tests/cpp/linear/test_linear.cc +++ b/tests/cpp/linear/test_linear.cc @@ -5,12 +5,13 @@ #include #include "../helpers.h" - +#include "test_json_io.h" #include "../../../src/gbm/gblinear_model.h" +#include "xgboost/base.h" namespace xgboost { -TEST(Linear, shotgun) { +TEST(Linear, Shotgun) { size_t constexpr kRows = 10; size_t constexpr kCols = 10; @@ -45,6 +46,10 @@ TEST(Linear, shotgun) { delete pp_dmat; } +TEST(Shotgun, JsonIO) { + TestUpdaterJsonIO("shotgun"); +} + TEST(Linear, coordinate) { size_t constexpr kRows = 10; size_t constexpr kCols = 10; @@ -72,4 +77,8 @@ TEST(Linear, coordinate) { delete pp_dmat; } +TEST(Coordinate, JsonIO){ + TestUpdaterJsonIO("coord_descent"); +} + } // namespace xgboost diff --git a/tests/cpp/linear/test_linear.cu b/tests/cpp/linear/test_linear.cu index 4a2741680..f84307c97 100644 --- a/tests/cpp/linear/test_linear.cu +++ b/tests/cpp/linear/test_linear.cu @@ -3,6 +3,7 @@ #include #include "../helpers.h" +#include "test_json_io.h" #include "../../../src/gbm/gblinear_model.h" namespace xgboost { @@ -33,4 +34,8 @@ TEST(Linear, GPUCoordinate) { delete mat; } + +TEST(GPUCoordinate, JsonIO) { + TestUpdaterJsonIO("gpu_coord_descent"); +} } // namespace xgboost \ No newline at end of file diff --git a/tests/cpp/objective/test_ranking_obj.cc b/tests/cpp/objective/test_ranking_obj.cc index 6f3571a0f..0bd8872e8 100644 --- a/tests/cpp/objective/test_ranking_obj.cc +++ b/tests/cpp/objective/test_ranking_obj.cc @@ -36,7 +36,7 @@ TEST(Objective, DeclareUnifiedTest(PairwiseRankingGPair)) { ASSERT_NO_THROW(obj->DefaultEvalMetric()); } -TEST(Objective, DeclareUnifiedTest(NDCG_Json_IO)) { +TEST(Objective, DeclareUnifiedTest(NDCG_JsonIO)) { xgboost::GenericParameter tparam; tparam.UpdateAllowUnknown(Args{}); diff --git a/tests/cpp/test_learner.cc b/tests/cpp/test_learner.cc index 1260a8327..c04bca61e 100644 --- a/tests/cpp/test_learner.cc +++ b/tests/cpp/test_learner.cc @@ -134,7 +134,7 @@ TEST(Learner, Configuration) { } } -TEST(Learner, Json_ModelIO) { +TEST(Learner, JsonModelIO) { // Test of comparing JSON object directly. size_t constexpr kRows = 8; int32_t constexpr kIters = 4; diff --git a/tests/cpp/tree/test_tree_model.cc b/tests/cpp/tree/test_tree_model.cc index 39cc54937..0edf00e80 100644 --- a/tests/cpp/tree/test_tree_model.cc +++ b/tests/cpp/tree/test_tree_model.cc @@ -220,7 +220,7 @@ TEST(Tree, DumpDot) { ASSERT_NE(str.find(R"(graph [ bgcolor="#FFFF00" ])"), std::string::npos); } -TEST(Tree, Json_IO) { +TEST(Tree, JsonIO) { RegTree tree; tree.ExpandNode(0, 0, 0.0f, false, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); Json j_tree{Object()};