split_info.hpp 3.33 KB
Newer Older
Guolin Ke's avatar
Guolin Ke committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef LIGHTGBM_TREELEARNER_SPLIT_INFO_HPP_
#define LIGHTGBM_TREELEARNER_SPLIT_INFO_HPP_

#include <LightGBM/meta.h>

#include <cmath>
#include <cstdint>
#include <cstring>

#include <functional>

namespace LightGBM {

/*!
* \brief Used to store some information for gain split point
*/
struct SplitInfo {
public:
  /*! \brief Feature index */
  int feature;
  /*! \brief Split threshold */
Guolin Ke's avatar
Guolin Ke committed
22
23
24
  uint32_t threshold;

  uint32_t default_bin_for_zero;
Guolin Ke's avatar
Guolin Ke committed
25
  /*! \brief Left output after split */
Guolin Ke's avatar
Guolin Ke committed
26
  double left_output;
Guolin Ke's avatar
Guolin Ke committed
27
  /*! \brief Right output after split */
Guolin Ke's avatar
Guolin Ke committed
28
  double right_output;
Guolin Ke's avatar
Guolin Ke committed
29
  /*! \brief Split gain */
Guolin Ke's avatar
Guolin Ke committed
30
  double gain;
Guolin Ke's avatar
Guolin Ke committed
31
32
33
34
35
  /*! \brief Left number of data after split */
  data_size_t left_count;
  /*! \brief Right number of data after split */
  data_size_t right_count;
  /*! \brief Left sum gradient after split */
Guolin Ke's avatar
Guolin Ke committed
36
  double left_sum_gradient;
Guolin Ke's avatar
Guolin Ke committed
37
  /*! \brief Left sum hessian after split */
Guolin Ke's avatar
Guolin Ke committed
38
  double left_sum_hessian;
Guolin Ke's avatar
Guolin Ke committed
39
  /*! \brief Right sum gradient after split */
Guolin Ke's avatar
Guolin Ke committed
40
  double right_sum_gradient;
Guolin Ke's avatar
Guolin Ke committed
41
  /*! \brief Right sum hessian after split */
Guolin Ke's avatar
Guolin Ke committed
42
  double right_sum_hessian;
Guolin Ke's avatar
Guolin Ke committed
43
44

  SplitInfo() {
45
    // initialize with -1 and -inf gain
Guolin Ke's avatar
Guolin Ke committed
46
47
48
49
50
    feature = -1;
    gain = kMinScore;
  }

  inline void Reset() {
51
    // initialize with -1 and -inf gain
Guolin Ke's avatar
Guolin Ke committed
52
53
54
55
56
57
    feature = -1;
    gain = kMinScore;
  }

  inline bool operator > (const SplitInfo &si) const;

Guolin Ke's avatar
Guolin Ke committed
58
59
  inline bool operator == (const SplitInfo &si) const;

Guolin Ke's avatar
Guolin Ke committed
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
  inline static void MaxReducer(const char* src, char* dst, int len) {
    const int type_size = sizeof(SplitInfo);
    int used_size = 0;
    const SplitInfo* p1;
    SplitInfo* p2;
    while (used_size < len) {
      p1 = reinterpret_cast<const SplitInfo*>(src);
      p2 = reinterpret_cast<SplitInfo*>(dst);
      if (*p1 > *p2) {
        // copy
        std::memcpy(dst, src, type_size);
      }
      src += type_size;
      dst += type_size;
      used_size += type_size;
    }
  }
};



inline bool SplitInfo::operator > (const SplitInfo& si) const {
Guolin Ke's avatar
Guolin Ke committed
82
83
  double local_gain = this->gain;
  double other_gain = si.gain;
Guolin Ke's avatar
Guolin Ke committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
  // replace nan with -inf
  if (local_gain == NAN) {
    local_gain = kMinScore;
  }
  // replace nan with -inf
  if (other_gain == NAN) {
    other_gain = kMinScore;
  }
  int local_feature = this->feature;
  int other_feature = si.feature;
  // replace -1 with max int
  if (local_feature == -1) {
    local_feature = INT32_MAX;
  }
  // replace -1 with max int
  if (other_feature == -1) {
    other_feature = INT32_MAX;
  }
  if (local_gain != other_gain) {
    return local_gain > other_gain;
  } else {
    // if same gain, use smaller feature
    return local_feature < other_feature;
  }
}

Guolin Ke's avatar
Guolin Ke committed
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
inline bool SplitInfo::operator == (const SplitInfo& si) const {
  double local_gain = this->gain;
  double other_gain = si.gain;
  // replace nan with -inf
  if (local_gain == NAN) {
    local_gain = kMinScore;
  }
  // replace nan with -inf
  if (other_gain == NAN) {
    other_gain = kMinScore;
  }
  int local_feature = this->feature;
  int other_feature = si.feature;
  // replace -1 with max int
  if (local_feature == -1) {
    local_feature = INT32_MAX;
  }
  // replace -1 with max int
  if (other_feature == -1) {
    other_feature = INT32_MAX;
  }
  if (local_gain != other_gain) {
    return local_gain == other_gain;
  } else {
    // if same gain, use smaller feature
    return local_feature == other_feature;
  }
}

Guolin Ke's avatar
Guolin Ke committed
139
}  // namespace LightGBM
Guolin Ke's avatar
Guolin Ke committed
140
#endif   // LightGBM_TREELEARNER_SPLIT_INFO_HPP_