From c7c485d05228fb8540d00b23ec3fdc560fde390c Mon Sep 17 00:00:00 2001 From: Jiaming Yuan Date: Wed, 15 Feb 2023 22:41:31 +0800 Subject: [PATCH] Extract fit intercept. (#8793) --- R-package/src/Makevars.in | 1 + R-package/src/Makevars.win | 1 + src/objective/init_estimation.cc | 39 ++++++++++++++++++++++++ src/objective/init_estimation.h | 19 ++++++++++++ src/objective/regression_obj.cu | 51 ++++++-------------------------- 5 files changed, 69 insertions(+), 42 deletions(-) create mode 100644 src/objective/init_estimation.cc create mode 100644 src/objective/init_estimation.h diff --git a/R-package/src/Makevars.in b/R-package/src/Makevars.in index 630965e38..6195ce0e7 100644 --- a/R-package/src/Makevars.in +++ b/R-package/src/Makevars.in @@ -36,6 +36,7 @@ OBJECTS= \ $(PKGROOT)/src/objective/hinge.o \ $(PKGROOT)/src/objective/aft_obj.o \ $(PKGROOT)/src/objective/adaptive.o \ + $(PKGROOT)/src/objective/init_estimation.o \ $(PKGROOT)/src/gbm/gbm.o \ $(PKGROOT)/src/gbm/gbtree.o \ $(PKGROOT)/src/gbm/gbtree_model.o \ diff --git a/R-package/src/Makevars.win b/R-package/src/Makevars.win index 09f09598a..3a5587190 100644 --- a/R-package/src/Makevars.win +++ b/R-package/src/Makevars.win @@ -36,6 +36,7 @@ OBJECTS= \ $(PKGROOT)/src/objective/hinge.o \ $(PKGROOT)/src/objective/aft_obj.o \ $(PKGROOT)/src/objective/adaptive.o \ + $(PKGROOT)/src/objective/init_estimation.o \ $(PKGROOT)/src/gbm/gbm.o \ $(PKGROOT)/src/gbm/gbtree.o \ $(PKGROOT)/src/gbm/gbtree_model.o \ diff --git a/src/objective/init_estimation.cc b/src/objective/init_estimation.cc new file mode 100644 index 000000000..3a2ff0dec --- /dev/null +++ b/src/objective/init_estimation.cc @@ -0,0 +1,39 @@ +#include "init_estimation.h" + +#include "../common/stats.h" // Mean +#include "../tree/fit_stump.h" // FitStump +#include "xgboost/base.h" // GradientPair +#include "xgboost/data.h" // MetaInfo +#include "xgboost/host_device_vector.h" // HostDeviceVector +#include "xgboost/json.h" // Json +#include "xgboost/linalg.h" // Tensor,Vector +#include "xgboost/task.h" // ObjInfo + +namespace xgboost { +namespace obj { +void FitIntercept::InitEstimation(MetaInfo const& info, linalg::Vector* base_score) const { + if (this->Task().task == ObjInfo::kRegression) { + CheckInitInputs(info); + } + // Avoid altering any state in child objective. + HostDeviceVector dummy_predt(info.labels.Size(), 0.0f, this->ctx_->gpu_id); + HostDeviceVector gpair(info.labels.Size(), GradientPair{}, this->ctx_->gpu_id); + + Json config{Object{}}; + this->SaveConfig(&config); + + std::unique_ptr new_obj{ + ObjFunction::Create(get(config["name"]), this->ctx_)}; + new_obj->LoadConfig(config); + new_obj->GetGradient(dummy_predt, info, 0, &gpair); + bst_target_t n_targets = this->Targets(info); + linalg::Vector leaf_weight; + tree::FitStump(this->ctx_, gpair, n_targets, &leaf_weight); + + // workaround, we don't support multi-target due to binary model serialization for + // base margin. + common::Mean(this->ctx_, leaf_weight, base_score); + this->PredTransform(base_score->Data()); +} +} // namespace obj +} // namespace xgboost diff --git a/src/objective/init_estimation.h b/src/objective/init_estimation.h new file mode 100644 index 000000000..1a243523c --- /dev/null +++ b/src/objective/init_estimation.h @@ -0,0 +1,19 @@ +#include "xgboost/data.h" // MetaInfo +#include "xgboost/linalg.h" // Tensor +#include "xgboost/objective.h" // ObjFunction + +namespace xgboost { +namespace obj { +class FitIntercept : public ObjFunction { + void InitEstimation(MetaInfo const& info, linalg::Vector* base_score) const override; +}; + +inline void CheckInitInputs(MetaInfo const& info) { + CHECK_EQ(info.labels.Shape(0), info.num_row_) << "Invalid shape of labels."; + if (!info.weights_.Empty()) { + CHECK_EQ(info.weights_.Size(), info.num_row_) + << "Number of weights should be equal to number of data points."; + } +} +} // namespace obj +} // namespace xgboost diff --git a/src/objective/regression_obj.cu b/src/objective/regression_obj.cu index 7a0df336a..29e2255e4 100644 --- a/src/objective/regression_obj.cu +++ b/src/objective/regression_obj.cu @@ -20,12 +20,12 @@ #include "../common/stats.h" #include "../common/threading_utils.h" #include "../common/transform.h" -#include "../tree/fit_stump.h" // FitStump #include "./regression_loss.h" #include "adaptive.h" +#include "init_estimation.h" // FitIntercept #include "xgboost/base.h" -#include "xgboost/context.h" -#include "xgboost/data.h" // MetaInfo +#include "xgboost/context.h" // Context +#include "xgboost/data.h" // MetaInfo #include "xgboost/host_device_vector.h" #include "xgboost/json.h" #include "xgboost/linalg.h" @@ -43,45 +43,12 @@ namespace xgboost { namespace obj { namespace { -void CheckInitInputs(MetaInfo const& info) { - CHECK_EQ(info.labels.Shape(0), info.num_row_) << "Invalid shape of labels."; - if (!info.weights_.Empty()) { - CHECK_EQ(info.weights_.Size(), info.num_row_) - << "Number of weights should be equal to number of data points."; - } -} - void CheckRegInputs(MetaInfo const& info, HostDeviceVector const& preds) { CheckInitInputs(info); CHECK_EQ(info.labels.Size(), preds.Size()) << "Invalid shape of labels."; } } // anonymous namespace -class RegInitEstimation : public ObjFunction { - void InitEstimation(MetaInfo const& info, linalg::Tensor* base_score) const override { - CheckInitInputs(info); - // Avoid altering any state in child objective. - HostDeviceVector dummy_predt(info.labels.Size(), 0.0f, this->ctx_->gpu_id); - HostDeviceVector gpair(info.labels.Size(), GradientPair{}, this->ctx_->gpu_id); - - Json config{Object{}}; - this->SaveConfig(&config); - - std::unique_ptr new_obj{ - ObjFunction::Create(get(config["name"]), this->ctx_)}; - new_obj->LoadConfig(config); - new_obj->GetGradient(dummy_predt, info, 0, &gpair); - bst_target_t n_targets = this->Targets(info); - linalg::Vector leaf_weight; - tree::FitStump(this->ctx_, gpair, n_targets, &leaf_weight); - - // workaround, we don't support multi-target due to binary model serialization for - // base margin. - common::Mean(this->ctx_, leaf_weight, base_score); - this->PredTransform(base_score->Data()); - } -}; - #if defined(XGBOOST_USE_CUDA) DMLC_REGISTRY_FILE_TAG(regression_obj_gpu); #endif // defined(XGBOOST_USE_CUDA) @@ -96,7 +63,7 @@ struct RegLossParam : public XGBoostParameter { }; template -class RegLossObj : public RegInitEstimation { +class RegLossObj : public FitIntercept { protected: HostDeviceVector additional_input_; @@ -243,7 +210,7 @@ XGBOOST_REGISTER_OBJECTIVE(LinearRegression, "reg:linear") return new RegLossObj(); }); // End deprecated -class PseudoHuberRegression : public RegInitEstimation { +class PseudoHuberRegression : public FitIntercept { PesudoHuberParam param_; public: @@ -318,7 +285,7 @@ struct PoissonRegressionParam : public XGBoostParameter }; // poisson regression for count -class PoissonRegression : public RegInitEstimation { +class PoissonRegression : public FitIntercept { public: // declare functions void Configure(const std::vector >& args) override { @@ -413,7 +380,7 @@ XGBOOST_REGISTER_OBJECTIVE(PoissonRegression, "count:poisson") // cox regression for survival data (negative values mean they are censored) -class CoxRegression : public RegInitEstimation { +class CoxRegression : public FitIntercept { public: void Configure(Args const&) override {} ObjInfo Task() const override { return ObjInfo::kRegression; } @@ -510,7 +477,7 @@ XGBOOST_REGISTER_OBJECTIVE(CoxRegression, "survival:cox") .set_body([]() { return new CoxRegression(); }); // gamma regression -class GammaRegression : public RegInitEstimation { +class GammaRegression : public FitIntercept { public: void Configure(Args const&) override {} ObjInfo Task() const override { return ObjInfo::kRegression; } @@ -601,7 +568,7 @@ struct TweedieRegressionParam : public XGBoostParameter }; // tweedie regression -class TweedieRegression : public RegInitEstimation { +class TweedieRegression : public FitIntercept { public: // declare functions void Configure(const std::vector >& args) override {