XGBoost рдХреЗ рдЕрдВрджрд░ рдХреНрдпрд╛ рд╣реИ, рдФрд░ Go рдХреЛ рдЗрд╕рд╕реЗ рдХреНрдпрд╛ рд▓реЗрдирд╛ рджреЗрдирд╛ рд╣реИ?

рдорд╢реАрди рд╕реАрдЦрдиреЗ рдХреА рджреБрдирд┐рдпрд╛ рдореЗрдВ, рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рдкреНрд░рдХрд╛рд░ рдХреЗ рдореЙрдбрд▓ рдореЗрдВ рд╕реЗ рдПрдХ рдирд┐рд░реНрдгрд╛рдпрдХ рдкреЗрдбрд╝ рд╣реИ рдФрд░ рдЙрди рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╕рдорд╛рдирддрд╛рдПрдВ рд╣реИрдВред рдкреЗрдбрд╝реЛрдВ рдХреЗ рдлрд╛рдпрджреЗ рд╣реИрдВ: рд╡реНрдпрд╛рдЦреНрдпрд╛ рдореЗрдВ рдЖрд╕рд╛рдиреА, рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рдкреНрд░рдХрд╛рд░ рдкрд░ рдХреЛрдИ рдкреНрд░рддрд┐рдмрдВрдз рдирд╣реАрдВ рд╣реИ, рдирдореВрдиреЗ рдХреЗ рдЖрдХрд╛рд░ рдкрд░ рдирд░рдо рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рд╣реИрдВред рдкреЗрдбрд╝реЛрдВ рдХрд╛ рднреА рдПрдХ рдкреНрд░рдореБрдЦ рджреЛрд╖ рд╣реИ - рдкреАрдЫреЗ рд╣рдЯрдиреЗ рдХреА рдкреНрд░рд╡реГрддреНрддрд┐ред рдЗрд╕рд▓рд┐рдП, рд▓рдЧрднрдЧ рд╣рдореЗрд╢рд╛ рдкреЗрдбрд╝реЛрдВ рдХреЛ рдЯреБрдХрдбрд╝рд┐рдпреЛрдВ рдореЗрдВ рдЬреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╡рди, рдврд╛рд▓ рдмрдврд╝рд╛рдиреЗ рдЖрджрд┐, рдЬрдЯрд┐рд▓ рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рдФрд░ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рдХрд╛рд░реНрдп рдкреЗрдбрд╝реЛрдВ рдХреЛ рд░рдЪрдирд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдЯреБрдХрдбрд╝рд┐рдпреЛрдВ рдореЗрдВ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдирд╛ рд╣реИред

рдПрдХ рд╣реА рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд рдкреЗрдбрд╝ рдкрд╣рдирд╛рд╡рд╛ рдореЙрдбрд▓ рд╕реЗ рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгрд┐рдпреЛрдВ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ, рд▓реЛрдХрдкреНрд░рд┐рдп рдЧреНрд░реЗрдбрд┐рдВрдЧ рдмреВрд╕реНрдЯрд┐рдВрдЧ XGBoost рдФрд░ LightGBM рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реБрд╡рд┐рдзрд╛рдПрдБред рдФрд░ рдкрд╛рдардХ рдХреЛ рдЧреЛ рдХреЗ рд▓рд┐рдП leaves рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕реЗ рднреА рдкрд░рд┐рдЪрд┐рдд рдХрд░рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рдЖрдкрдХреЛ рдореВрд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд╕реА рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдкреЗрдбрд╝ рдЯреБрдХрдбрд╝рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгрд┐рдпрд╛рдВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рдкреЗрдбрд╝ рдХрд╣рд╛рдБ рд╕реЗ рдЙрдЧрддреЗ рд╣реИрдВ?


рдкрд╣рд▓реЗ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рд╛рд╡рдзрд╛рдиреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рд╡реЗ рдЖрдорддреМрд░ рдкрд░ рдкреЗрдбрд╝реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ:

  1. рдиреЛрдб рдореЗрдВ рд╡рд┐рднрд╛рдЬрди рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╣реЛрддрд╛ рд╣реИ
  2. рдмрд╛рдЗрдирд░реА рдЯреНрд░реА - рдкреНрд░рддреНрдпреЗрдХ рдиреЛрдб рдореЗрдВ рдПрдХ рдмрд╛рдПрдВ рдФрд░ рджрд╛рдПрдВ рд╡рдВрд╢рдЬ рд╣реИрдВ
  3. рдПрдХ рднреМрддрд┐рдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдирд┐рд░реНрдгрдп рдирд┐рдпрдо рдореЗрдВ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рдореВрд▓реНрдп рдХреА рд╕реАрдорд╛ рдореВрд▓реНрдп рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░рдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИ

рдореИрдВрдиреЗ рдЗрд╕ рдЪрд┐рддреНрд░рдг рдХреЛ XGBoost рдкреНрд░рд▓реЗрдЦрди рд╕реЗ рд▓рд┐рдпрд╛ рд╣реИ



рдЗрд╕ рдкреЗрдбрд╝ рдореЗрдВ рд╣рдорд╛рд░реЗ 2 рдиреЛрдбреНрд╕, 2 рдирд┐рд░реНрдгрдп рдирд┐рдпрдо рдФрд░ 3 рд╢реАрдЯ рд╣реИрдВред рдордВрдбрд▓рд┐рдпреЛрдВ рдХреЗ рддрд╣рдд, рдореВрд▓реНрдпреЛрдВ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ - рдХрд┐рд╕реА рд╡рд╕реНрддреБ рдХреЛ рдкреЗрдбрд╝ рд▓рдЧрд╛рдиреЗ рдХрд╛ рдкрд░рд┐рдгрд╛рдоред рдЖрдорддреМрд░ рдкрд░, рдПрдХ рдкрд░рд┐рд╡рд░реНрддрди рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдкреЗрдбрд╝ рдпрд╛ рдкреЗрдбрд╝ рдХреА рдЯреБрдХрдбрд╝реА рдХреА рдЧрдгрдирд╛ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рджреНрд╡рд┐рдЖрдзрд╛рд░реА рд╡рд░реНрдЧреАрдХрд░рдг рд╕рдорд╕реНрдпрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд┐рдЧреНрдореЙрдЗрдб ред

рдзреАрд░реЗ-рдзреАрд░реЗ рдмреВрд╕реНрдЯрд┐рдВрдЧ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╛рдкреНрдд рдкреЗрдбрд╝реЛрдВ рдХреА рдЯреБрдХрдбрд╝реА рд╕реЗ рдкреВрд░реНрд╡рд╛рдиреБрдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╕рднреА рдкреЗрдбрд╝реЛрдВ рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгрд┐рдпреЛрдВ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛:

 double pred = 0.0; for (auto& tree: trees) pred += tree->Predict(feature_values); 

рдЗрд╕рдХреЗ рдмрд╛рдж, C++ , рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдЗрд╕ рднрд╛рд╖рд╛ рдореЗрдВ рд╣реИ рдХрд┐ XGBoost рдФрд░ LightGBM рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИред рдореИрдВ рдЕрдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рдЫреЛрдбрд╝ рджреВрдВрдЧрд╛ рдФрд░ рд╕рдмрд╕реЗ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдХреЛрдб рджреЗрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реВрдВрдЧрд╛ред

рдЕрдЧрд▓рд╛, рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ Predict рдореЗрдВ рдХреНрдпрд╛ рдЫрд┐рдкрд╛ рд╣реИ рдФрд░ рдкреЗрдбрд╝ рдХреА рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХреИрд╕реЗ рд╕рдВрд░рдЪрд┐рдд рд╣реИред

XGBoost рдкреЗрдбрд╝


XGBoost рдореЗрдВ XGBoost рдХреА рдХрдИ рдХрдХреНрд╖рд╛рдПрдВ (OOP рдХреЗ рдЕрд░реНрде рдореЗрдВ) рд╣реИрдВред рд╣рдо RegTree рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗ (рджреЗрдЦреЗрдВ include/xgboost/tree_model.h ), рдЬреЛ рдкреНрд░рд▓реЗрдЦрди рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдореБрдЦреНрдп рд╣реИред рдпрджрд┐ рдЖрдк рдХреЗрд╡рд▓ рдЕрдиреБрдорд╛рдиреЛрдВ рдХреЗ рд▓рд┐рдП рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╡рд┐рд╡рд░рдг рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВ, рддреЛ рдХрдХреНрд╖рд╛ рдХреЗ рд╕рджрд╕реНрдп рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рджрд┐рдЦрддреЗ рд╣реИрдВ:

 class RegTree { // vector of nodes std::vector<Node> nodes_; }; 

GetNext рдирд┐рдпрдо GetNext рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ GetNext рд╣реИред рдЧрдгрдирд╛ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд┐рдП рдмрд┐рдирд╛, рдХреЛрдб рдХреЛ рдереЛрдбрд╝рд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

 // get next position of the tree given current pid int RegTree::GetNext(int pid, float fvalue, bool is_unknown) const { const auto& node = nodes_[pid] float split_value = node.info_.split_cond; if (is_unknown) { return node.DefaultLeft() ? node.cleft_ : node.cright_; } else { if (fvalue < split_value) { return node.cleft_; } else { return node.cright_; } } } 

рдпрд╣рд╛рдБ рд╕реЗ рджреЛ рдмрд╛рддреЗрдВ рдЕрдиреБрд╕рд░рдг рдХрд░рддреА рд╣реИрдВ:

  1. RegTree рдХреЗрд╡рд▓ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ (рдкреНрд░рдХрд╛рд░ float )
  2. рд╕реНрдХрд┐рдк рдХрд┐рдП рдЧрдП рдЪрд╛рд░рд┐рддреНрд░рд┐рдХ рдореВрд▓реНрдп рд╕рдорд░реНрдерд┐рдд рд╣реИрдВ

рдХреЗрдВрджреНрд░ рдмрд┐рдВрджреБ Node рд╡рд░реНрдЧ рд╣реИред рдЗрд╕рдореЗрдВ рдкреЗрдбрд╝ рдХреА рд╕реНрдерд╛рдиреАрдп рд╕рдВрд░рдЪрдирд╛, рдирд┐рд░реНрдгрдп рдирд┐рдпрдо рдФрд░ рд╢реАрдЯ рдХрд╛ рдореВрд▓реНрдп рд╢рд╛рдорд┐рд▓ рд╣реИ:

 class Node { public: // feature index of split condition unsigned SplitIndex() const { return sindex_ & ((1U << 31) - 1U); } // when feature is unknown, whether goes to left child bool DefaultLeft() const { return (sindex_ >> 31) != 0; } // whether current node is leaf node bool IsLeaf() const { return cleft_ == -1; } private: // in leaf node, we have weights, in non-leaf nodes, we have split condition union Info { float leaf_value; float split_cond; } info_; // pointer to left, right int cleft_, cright_; // split feature index, left split or right split depends on the highest bit unsigned sindex_{0}; }; 

рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЛ рдкреНрд░рддрд┐рд╖реНрдард┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

  1. рдЪрд╛рджрд░реЛрдВ рдХреЛ рдиреЛрдбреНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП cleft_ = -1
  2. info_ рдлрд╝реАрд▓реНрдб рдХреЛ union рд░реВрдк union рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЕрд░реНрдерд╛рдд рджреЛ рдкреНрд░рдХрд╛рд░ рдХреЗ рдбреЗрдЯрд╛ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд╕рдорд╛рди) рдиреЛрдб рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдореЗрдореЛрд░реА рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рд╕рд╛рдЭрд╛ рдХрд░рддреЗ рд╣реИрдВ
  3. sindex_ рдореЗрдВ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд┐рдЯ рдЙрд╕ рд╡рд╕реНрддреБ рдХреЗ рд▓рд┐рдП рдЬрд╝рд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЧреБрдг рдорд╛рди рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ

RegTree::Predict рдЙрддреНрддрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА RegTree::Predict рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рдорд╛рд░реНрдЧ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ рджреЛ рдмрд╛рд░ рдЧрд╛рдпрдм рд╣реЛ рдЬрд╛рдПрдЧрд╛:

 float RegTree::Predict(const RegTree::FVec& feat, unsigned root_id) const { int pid = this->GetLeafIndex(feat, root_id); return nodes_[pid].leaf_value; } int RegTree::GetLeafIndex(const RegTree::FVec& feat, unsigned root_id) const { auto pid = static_cast<int>(root_id); while (!nodes_[pid].IsLeaf()) { unsigned split_index = nodes_[pid].SplitIndex(); pid = this->GetNext(pid, feat.Fvalue(split_index), feat.IsMissing(split_index)); } return pid; } 

GetLeafIndex рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ GetLeafIndex рд╣рдо рдкреЗрдбрд╝ рдХреЗ рдиреЛрдбреНрд╕ рдХреЛ рдПрдХ рд▓реВрдк рдореЗрдВ рдиреАрдЪреЗ GetLeafIndex рдЬрдм рддрдХ рд╣рдо рдкрддреНрддреА рдХреЛ рдирд╣реАрдВ рдорд╛рд░рддреЗред

рд▓рд╛рдЗрдЯ рдЬреАрдмреАрдПрдо рдЯреНрд░реАрдЬрд╝


рд▓рд╛рдЗрдЯ рдЬреАрдмреАрдПрдо рдореЗрдВ рдиреЛрдб рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдирд╣реАрдВ рд╣реИред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдЯреНрд░реА Tree рдХреА рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ ( include/LightGBM/tree.h рдлрд╝рд╛рдЗрд▓ рд╢рд╛рдорд┐рд▓ рд╣реИ) рдореЗрдВ рдореВрд▓реНрдпреЛрдВ рдХреЗ рдПрд░реЗ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдЬрд╣рд╛рдВ рдиреЛрдб рд╕рдВрдЦреНрдпрд╛ рдПрдХ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рддреА рд╣реИред рдкрддреНрддрд┐рдпреЛрдВ рдореЗрдВ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕рд░рдгрд┐рдпреЛрдВ рдореЗрдВ рднреА рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

 class Tree { // Number of current leaves int num_leaves_; // A non-leaf node's left child std::vector<int> left_child_; // A non-leaf node's right child std::vector<int> right_child_; // A non-leaf node's split feature, the original index std::vector<int> split_feature_; //A non-leaf node's split threshold in feature value std::vector<double> threshold_; std::vector<int> cat_boundaries_; std::vector<uint32_t> cat_threshold_; // Store the information for categorical feature handle and mising value handle. std::vector<int8_t> decision_type_; // Output of leaves std::vector<double> leaf_value_; }; 

LightGBM рд╢реНрд░реЗрдгреАрдмрджреНрдз рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рд╕рдорд░реНрдерди рдПрдХ рдмрд┐рдЯ рдлрд╝реАрд▓реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рд╕рднреА рдиреЛрдбреНрд╕ рдХреЗ рд▓рд┐рдП cat_threshold_ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реЛрддрд╛ рд╣реИред cat_boundaries_ рдЙрд╕ рдиреЛрдб рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдмрд┐рдЯ рдлрд╝реАрд▓реНрдб рдХреЗ рдХрд┐рд╕ рднрд╛рдЧ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИред рд╢реНрд░реЗрдгреАрдмрджреНрдз рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП threshold_ рдлрд╝реАрд▓реНрдб рдХреЛ int рдореЗрдВ cat_boundaries_ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдмрд┐рдЯ рдХреНрд╖реЗрддреНрд░ рдХреА рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП рдЦреЛрдЬ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП cat_boundaries_ рдореЗрдВ рд╕реВрдЪрдХрд╛рдВрдХ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИред

рдПрдХ рд╕реНрдкрд╖реНрдЯ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрдгрд╛рдпрдХ рдирд┐рдпрдо рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:

 int CategoricalDecision(double fval, int node) const { uint8_t missing_type = GetMissingType(decision_type_[node]); int int_fval = static_cast<int>(fval); if (int_fval < 0) { return right_child_[node];; } else if (std::isnan(fval)) { // NaN is always in the right if (missing_type == 2) { return right_child_[node]; } int_fval = 0; } int cat_idx = static_cast<int>(threshold_[node]); if (FindInBitset(cat_threshold_.data() + cat_boundaries_[cat_idx], cat_boundaries_[cat_idx + 1] - cat_boundaries_[cat_idx], int_fval)) { return left_child_[node]; } return right_child_[node]; } 

рдпрд╣ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐, missing_type рдЖрдзрд╛рд░ рдкрд░ missing_type рдорд╛рди NaN рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкреЗрдбрд╝ рдХреА рджрд╛рдИрдВ рд╢рд╛рдЦрд╛ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдзрд╛рди рдХреЛ рдХрдо рдХрд░рддрд╛ рд╣реИред рдЕрдиреНрдпрдерд╛, NaN рдХреЛ 0. рд╕реЗ рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдмрд┐рдЯ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдорд╛рди рдХреА рдЦреЛрдЬ рдХрд░рдирд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ:

 bool FindInBitset(const uint32_t* bits, int n, int pos) { int i1 = pos / 32; if (i1 >= n) { return false; } int i2 = pos % 32; return (bits[i1] >> i2) & 1; } 

рдпрд╛рдиреА, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╢реНрд░реЗрдгреАрдмрджреНрдз рд╡рд┐рд╢реЗрд╖рддрд╛ int_fval=42 рдЬрд╛рдБрдЪ рдХреА int_fval=42 рд╣реИ рдХрд┐ рдХреНрдпрд╛ рд╕рд░рдгреА рдореЗрдВ 41 рд╡рд╛рдВ (0 рд╕реЗ рдХреНрд░рдорд╛рдВрдХрди) рдмрд┐рдЯ рд╕реЗрдЯ рд╣реИ рдпрд╛ рдирд╣реАрдВред

рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдореЗрдВ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХрдореА рд╣реИ: рдпрджрд┐ рдПрдХ рд╢реНрд░реЗрдгреАрдЧрдд рд╡рд┐рд╢реЗрд╖рддрд╛ рдмрдбрд╝реЗ рдорд╛рди рд▓реЗ рд╕рдХрддреА рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП 100500, рддреЛ рдЗрд╕ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдирд┐рд░реНрдгрдп рдирд┐рдпрдо рдХреЗ рд▓рд┐рдП рдЖрдХрд╛рд░ рдореЗрдВ 12564 рдмрд╛рдЗрдЯреНрд╕ рддрдХ рдПрдХ рдмрд┐рдЯ рдлрд╝реАрд▓реНрдб рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛!

рдЗрд╕рд▓рд┐рдП, рд╢реНрд░реЗрдгреАрдмрджреНрдз рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рд╡рд╛рдВрдЫрдиреАрдп рд╣реИ рддрд╛рдХрд┐ рд╡реЗ 0 рд╕реЗ рдЕрдзрд┐рдХрддрдо рдореВрд▓реНрдп рддрдХ рд▓рдЧрд╛рддрд╛рд░ рдЬрд╛рдПрдВ ред

рдЕрдкрдиреЗ рд╣рд┐рд╕реНрд╕реЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ LightGBM рд╡реНрдпрд╛рдЦреНрдпрд╛рддреНрдордХ рдкрд░рд┐рд╡рд░реНрддрди рдХрд┐рдП рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╕реНрд╡реАрдХрд╛рд░ рдХрд┐рдпрд╛ ред

рднреМрддрд┐рдХ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рдирд╛ XGBoost рд╕реЗ рдмрд╣реБрдд рдЕрд▓рдЧ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдореИрдВ рдЗрд╕реЗ рд╕рдВрдХреНрд╖рд┐рдкреНрддрддрд╛ рдХреЗ рд▓рд┐рдП рдЫреЛрдбрд╝ рджреВрдВрдЧрд╛ред

рдкрддреНрддрд┐рдпрд╛рдВ - рдЧреЛ рдореЗрдВ рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдкреБрд╕реНрддрдХрд╛рд▓рдп


XGBoost рдФрд░ LightGBM рдирд┐рд░реНрдгрдп рдкреЗрдбрд╝реЛрдВ рдкрд░ рдврд╛рд▓ LightGBM рдореЙрдбрд▓ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИрдВред рдмреИрдХрдПрдВрдб рд╕реЗрд╡рд╛ рдореЗрдВ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЬрд╣рд╛рдВ рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╣рд▓ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ:

  1. рдореЙрдбрд▓ рдХрд╛ рдЖрд╡рдзрд┐рдХ рдкреНрд░рд╢рд┐рдХреНрд╖рдг рдСрдлрд╝рд▓рд╛рдЗрди
  2. рдмреИрдХрдПрдВрдб рд╕реЗрд╡рд╛ рдореЗрдВ рдореЙрдбрд▓ рдХрд╛ рд╡рд┐рддрд░рдг
  3. рдкреЛрд▓ рдореЙрдбрд▓ рдСрдирд▓рд╛рдЗрди

рднрд░реА рд╣реБрдИ рдмреИрдХреЗрдВрдб рд╕реЗрд╡рд╛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, Go рдПрдХ рд▓реЛрдХрдкреНрд░рд┐рдп рднрд╛рд╖рд╛ рд╣реИред C API рдФрд░ LightGBM рдорд╛рдзреНрдпрдо рд╕реЗ XGBoost рдпрд╛ LightGBM XGBoost рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИ - рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдЬрдЯрд┐рд▓ рд╣реИ, рд▓рд╛рдкрд░рд╡рд╛рд╣ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдХреЗ рдХрд╛рд░рдг, рдЖрдк SIGTERM рдХреЛ рдкрдХрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рд╕рд┐рд╕реНрдЯрдо рдереНрд░реЗрдбреНрд╕ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛рдПрдВ (рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд╕рд╛рде рдУрдкрдирдПрдордкреА рдмрдирд╛рдо рд░рдирдЯрд╛рдЗрдо рдереНрд░реЗрдбреНрд╕)ред

рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ XGBoost рдпрд╛ LightGBM рдореЗрдВ рдирд┐рд░реНрдорд┐рдд рдореЙрдбрд▓реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╢реБрджреНрдз Go рдкрд░ рдПрдХ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдЗрд╕реЗ leaves рдХрд╣рддреЗ leaves ред

рдкрддреНрддреЗ

рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреА рдореБрдЦреНрдп рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ:

  • LightGBM рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП
    • рдорд╛рдирдХ рдкреНрд░рд╛рд░реВрдк (рдкрд╛рда) рд╕реЗ рдореЙрдбрд▓ рдкрдврд╝рдирд╛
    • рднреМрддрд┐рдХ рдФрд░ рд╢реНрд░реЗрдгреАрдмрджреНрдз рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди
    • рдЧреБрдо рдорд╛рди рд╕рдорд░реНрдерди
    • рд╢реНрд░реЗрдгреАрдмрджреНрдз рдЪрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд╛ рдЕрдиреБрдХреВрд▓рди
    • рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА-рдХреЗрд╡рд▓ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рд╕рд╛рде рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдЕрдиреБрдХреВрд▓рди

  • XGBoost рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП
    • рдорд╛рдирдХ рдкреНрд░рд╛рд░реВрдк (рдмрд╛рдЗрдирд░реА) рд╕реЗ рдореЙрдбрд▓ рдкрдврд╝рдирд╛
    • рдЧреБрдо рдорд╛рди рд╕рдорд░реНрдерди
    • рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдЕрдиреБрдХреВрд▓рди


рдпрд╣рд╛рдВ рдПрдХ рдиреНрдпреВрдирддрдо Go рдХрд╛рд░реНрдпрдХреНрд░рдо рд╣реИ рдЬреЛ рдбрд┐рд╕реНрдХ рд╕реЗ рдПрдХ рдореЙрдбрд▓ рдХреЛ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИ рдФрд░ рдПрдХ рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рджрд┐рдЦрд╛рддрд╛ рд╣реИ:

 package main import ( "bufio" "fmt" "os" "github.com/dmitryikh/leaves" ) func main() { // 1.     path := "lightgbm_model.txt" reader, err := os.Open(path) if err != nil { panic(err) } defer reader.Close() // 2.   LightGBM model, err := leaves.LGEnsembleFromReader(bufio.NewReader(reader)) if err != nil { panic(err) } // 3.  ! fvals := []float64{1.0, 2.0, 3.0} p := model.Predict(fvals, 0) fmt.Printf("Prediction for %v: %f\n", fvals, p) } 

рд▓рд╛рдЗрдмреНрд░реЗрд░реА API рдиреНрдпреВрдирддрдо рд╣реИред XGBoost рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП XGBoost рдмрд╕ рдКрдкрд░ рджрд┐рдП рдЧрдП leaves.XGEnsembleFromReader рдмрдЬрд╛рдп leaves.XGEnsembleFromReader рдХреЙрд▓ рдХрд░реЗрдВред leaves.XGEnsembleFromReader рд╡рд┐рдзрд┐ред рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгрд┐рдпреЛрдВ рдХреЛ PredictDense рдпрд╛ model.PredictCSR рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдкрддреНрддрд┐рдпреЛрдВ рдХреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдЕрдзрд┐рдХ рдЙрдкрдпреЛрдЧ рдкрд░рд┐рджреГрд╢реНрдп рдкрд╛рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред

рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ Go , C++ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдзреАрдореА рдЧрддрд┐ рд╕реЗ рдЪрд▓рддрд╛ рд╣реИ (рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рднрд╛рд░реА рд░рдирдЯрд╛рдЗрдо рдФрд░ рд░рдирдЯрд╛рдЗрдо рдЪреЗрдХ рдХреЗ рдХрд╛рд░рдг), рдХрдИ рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдореВрд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд╕реА рдПрдкреАрдЖрдИ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреБрд▓рдиреАрдп рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдЧрддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рдерд╛ред


рддреБрд▓рдирд╛ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдФрд░ рд╡рд┐рдзрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдЬреАрдердм рдкрд░ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рд╣реИрдВред

рдЬрдбрд╝ рдХреЛ рджреЗрдЦреЗрдВ


рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рд▓реЗрдЦ XGBoost рдФрд░ LightGBM рдореЗрдВ рдкреЗрдбрд╝реЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рджреНрд╡рд╛рд░ рдЦреЛрд▓рддрд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдмреБрдирд┐рдпрд╛рджреА рдирд┐рд░реНрдорд╛рдг рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИрдВ, рдФрд░ рдореИрдВ рдкрд╛рдардХреЛрдВ рдХреЛ рдЦреБрд▓реЗ рд╕реНрд░реЛрдд рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрддреНрд╕рд╛рд╣рд┐рдд рдХрд░рддрд╛ рд╣реВрдВ - рдХреЛрдб рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрдм рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреНрд░рд╢реНрди рд╣реИрдВред

рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдЧреЛ рднрд╛рд╖рд╛ рдореЗрдВ рдЕрдкрдиреА рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВ рдврд╛рд▓ рдмрдврд╝рд╛рдиреЗ рд╡рд╛рд▓реЗ рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд╡рд┐рд╖рдп рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ, рдореИрдВ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдк рдЦреБрдж рдХреЛ рдкрддреНрддрд┐рдпреЛрдВ рдХреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рдХрд░рд╛рдПрдВред leaves рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП leaves рдЖрдк рдореВрд▓ C ++ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЧрддрд┐ рдЦреЛрдП рдмрд┐рдирд╛, рдЕрдкрдиреЗ рдЙрддреНрдкрд╛рджрди рдкрд░рд┐рд╡реЗрд╢ рдореЗрдВ рдорд╢реАрди рд▓рд░реНрдирд┐рдВрдЧ рдореЗрдВ рдЕрдЧреНрд░рдгреА рдмрдврд╝рдд рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХрд╛ рдЖрд╕рд╛рдиреА рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЕ рдЫрд╛!

Source: https://habr.com/ru/post/hi423495/


All Articles