1 /*! 2 * Copyright 2018 by Contributors 3 * \author Tianqi Chen, Rory Mitchell 4 */ 5 6 #include <xgboost/linear_updater.h> 7 #include "coordinate_common.h" 8 9 namespace xgboost { 10 namespace linear { 11 12 DMLC_REGISTRY_FILE_TAG(updater_shotgun); 13 14 class ShotgunUpdater : public LinearUpdater { 15 public: 16 // set training parameter Configure(Args const & args)17 void Configure(Args const& args) override { 18 param_.UpdateAllowUnknown(args); 19 if (param_.feature_selector != kCyclic && 20 param_.feature_selector != kShuffle) { 21 LOG(FATAL) << "Unsupported feature selector for shotgun updater.\n" 22 << "Supported options are: {cyclic, shuffle}"; 23 } 24 selector_.reset(FeatureSelector::Create(param_.feature_selector)); 25 } LoadConfig(Json const & in)26 void LoadConfig(Json const& in) override { 27 auto const& config = get<Object const>(in); 28 FromJson(config.at("linear_train_param"), ¶m_); 29 } SaveConfig(Json * p_out) const30 void SaveConfig(Json* p_out) const override { 31 auto& out = *p_out; 32 out["linear_train_param"] = ToJson(param_); 33 } 34 Update(HostDeviceVector<GradientPair> * in_gpair,DMatrix * p_fmat,gbm::GBLinearModel * model,double sum_instance_weight)35 void Update(HostDeviceVector<GradientPair> *in_gpair, DMatrix *p_fmat, 36 gbm::GBLinearModel *model, double sum_instance_weight) override { 37 auto &gpair = in_gpair->HostVector(); 38 param_.DenormalizePenalties(sum_instance_weight); 39 const int ngroup = model->learner_model_param->num_output_group; 40 41 // update bias 42 for (int gid = 0; gid < ngroup; ++gid) { 43 auto grad = GetBiasGradientParallel(gid, ngroup, 44 in_gpair->ConstHostVector(), p_fmat); 45 auto dbias = static_cast<bst_float>(param_.learning_rate * 46 CoordinateDeltaBias(grad.first, grad.second)); 47 model->Bias()[gid] += dbias; 48 UpdateBiasResidualParallel(gid, ngroup, dbias, &in_gpair->HostVector(), p_fmat); 49 } 50 51 // lock-free parallel updates of weights 52 selector_->Setup(*model, in_gpair->ConstHostVector(), p_fmat, 53 param_.reg_alpha_denorm, param_.reg_lambda_denorm, 0); 54 for (const auto &batch : p_fmat->GetBatches<CSCPage>()) { 55 auto page = batch.GetView(); 56 const auto nfeat = static_cast<bst_omp_uint>(batch.Size()); 57 dmlc::OMPException exc; 58 #pragma omp parallel for schedule(static) 59 for (bst_omp_uint i = 0; i < nfeat; ++i) { 60 exc.Run([&]() { 61 int ii = selector_->NextFeature 62 (i, *model, 0, in_gpair->ConstHostVector(), p_fmat, param_.reg_alpha_denorm, 63 param_.reg_lambda_denorm); 64 if (ii < 0) return; 65 const bst_uint fid = ii; 66 auto col = page[ii]; 67 for (int gid = 0; gid < ngroup; ++gid) { 68 double sum_grad = 0.0, sum_hess = 0.0; 69 for (auto& c : col) { 70 const GradientPair &p = gpair[c.index * ngroup + gid]; 71 if (p.GetHess() < 0.0f) continue; 72 const bst_float v = c.fvalue; 73 sum_grad += p.GetGrad() * v; 74 sum_hess += p.GetHess() * v * v; 75 } 76 bst_float &w = (*model)[fid][gid]; 77 auto dw = static_cast<bst_float>( 78 param_.learning_rate * 79 CoordinateDelta(sum_grad, sum_hess, w, param_.reg_alpha_denorm, 80 param_.reg_lambda_denorm)); 81 if (dw == 0.f) continue; 82 w += dw; 83 // update grad values 84 for (auto& c : col) { 85 GradientPair &p = gpair[c.index * ngroup + gid]; 86 if (p.GetHess() < 0.0f) continue; 87 p += GradientPair(p.GetHess() * c.fvalue * dw, 0); 88 } 89 } 90 }); 91 } 92 exc.Rethrow(); 93 } 94 } 95 96 protected: 97 // training parameters 98 LinearTrainParam param_; 99 100 std::unique_ptr<FeatureSelector> selector_; 101 }; 102 103 XGBOOST_REGISTER_LINEAR_UPDATER(ShotgunUpdater, "shotgun") 104 .describe( 105 "Update linear model according to shotgun coordinate descent " 106 "algorithm.") __anon89e520760202() 107 .set_body([]() { return new ShotgunUpdater(); }); 108 } // namespace linear 109 } // namespace xgboost 110