相對於隨機森林使用 bagging 融合完全長成決策樹,梯度提升決策樹使用的 boosting 的改進版本 AdaBoost 技術的廣義版本,也就是說是根據損失函數的梯度方向,所以叫做梯度提升(Gradient Boosting)。
常用的數學符號(Basic Notations)
假設葉子節點的排列順序是從左到右,使用 w m ( k ) w^{(k)}_m w m ( k ) 表示第 k 顆樹的第 t 個葉子節點的值,假如全部的葉子節點個數爲 T T T ,那麼第 k 顆樹的全部葉子節點的向量表示爲:
w ( k ) = ( w 1 ( k ) , w 2 ( k ) , ⋯ , w K ( k ) )
w^{(k)} = (w^{(k)}_1,w^{(k)}_2,\cdots,w^{(k)}_K)
w ( k ) = ( w 1 ( k ) , w 2 ( k ) , ⋯ , w K ( k ) )
爲了推導簡單下文中使用 w w w 代表 w ( k ) w^{(k)} w ( k ) 即最後一顆樹的權重向量 。
同時使用 q ( k ) ( x i ) q^{(k)} ( x_i ) q ( k ) ( x i ) 代表樣本 x i x_i x i 所在葉子節點的位置。爲了推導簡單下文中使用 q ( x i ) q ( x_i ) q ( x i ) 代表 q ( k ) ( x i ) q^{(k)} ( x_i ) q ( k ) ( x i ) 即最後一顆樹的樣本位置。 即 w q ( x i ) w_{q ( x_i )} w q ( x i ) 代表了樣本 x i x_i x i 對應的第 k 顆樹的預測值 f k ( x i ) f _ { k } \left( x _ { i } \right) f k ( x i ) 。
另外使用集合 I t ( k ) I^{(k)} _ { t } I t ( k ) 表示所在第 k 顆樹的第 t 個節點的全部樣本集合。
I t ( k ) = { x i ∣ q ( k ) ( x i ) = t }
I ^{(k)}_ { t } = \left\{ x_i | q^{(k)} \left( { x } _ { i } \right) = { t } \right\}
I t ( k ) = { x i ∣ q ( k ) ( x i ) = t }
爲了推導簡單下文中使用 I j I _ { j } I j 表示 I j ( k ) I ^{(k)}_ { j } I j ( k ) 。即最後一顆樹的樣本分佈集合
正則化學習目標(Regularized Learning Objective)
給定一個有 n 個樣本和 m 個特徵的數據集 D = { ( x i , y i ) } ( ∣ D ∣ = n , x i ∈ R m , y i ∈ R ) \mathcal { D } = \left\{ \left( \mathbf { x } _ { i } , y _ { i } \right) \right\} \left( | \mathcal { D } | = n , \mathbf { x } _ { i } \in \mathbb { R } ^ { m } , y _ { i } \in \mathbb { R } \right) D = { ( x i , y i ) } ( ∣ D ∣ = n , x i ∈ R m , y i ∈ R ) ,假設第 k 棵樹的預測函數(Hypothesis)爲:f k ( x i ) f _ { k } \left( x _ { i } \right) f k ( x i ) ,那麼在XGBoost中,使用 K 棵樹集成模型的的第 i 個樣本的預測值爲 y ^ i \hat { y } _ { i } y ^ i :
y ^ i = ϕ ( x i ) = ∑ k = 1 K f k ( x i ) , f k ∈ F
\hat { y } _ { i } = \phi \left( \mathbf { x } _ { i } \right) = \sum _ { k = 1 } ^ { K } f _ { k } \left( \mathbf { x } _ { i } \right) , \quad f _ { k } \in \mathcal { F }
y ^ i = ϕ ( x i ) = k = 1 ∑ K f k ( x i ) , f k ∈ F
該集成方法以下圖爲例:
可以看出與廣義的 GBDT 不同的地方是其係數是 1 。
可以看出這是一種 Additive Training(疊加式的訓練),因爲其本身也是一種 GBDT,所以其訓練過程也是需要使用前一個 hypothesis 的預測餘數進行下一個 hypothesis 的獲取的。也就是說其每顆樹模型的預測值可以做如下傳遞:
y ^ i ( 0 ) = 0 ← Default case y ^ i ( 1 ) = f 1 ( x j ) = y ^ i 0 + f 1 ( x i ) y ^ i ( 2 ) = f 1 ( x i ) + f 2 ( x 0 ) = y ^ i ( 2 ) + f 2 ( x 2 ) ⋮ y ^ i ( k ) = f 1 ( x 0 ) + f 2 ( x i ) + ⋯ + f k ( x i ) = ∑ j = 1 ( k − 1 ) f j ( x i ) + f k ( x i ) = y ^ i ( k − 1 ) + f k ( x i )
\begin{aligned} \hat { y } _ { i } ^ { ( 0 ) } & = 0 \quad \leftarrow \quad \text { Default case } \\
\hat { y } _ { i } ^ { ( 1 ) } &= f _ { 1 } \left( x _ { j } \right) = \hat { y } _ { i } ^ { 0} + f _ { 1 } \left( x _ { i } \right) \\
\hat { y } _ { i } ^ { ( 2 ) } & = f _ { 1 } \left( x _ { i } \right) + f _ { 2 } \left( x _ { 0 } \right) = \hat { y } _ { i } ^ { ( 2 ) } + f _ { 2 } \left( x _ { 2 } \right) \\ & \, \, \, \vdots \\
\hat { y } _ { i } ^ { ( k ) } &= { f _ { 1 } \left( x _ { 0 } \right) + f _ { 2 } \left( x _ { i } \right) + \cdots + f _ { k } \left( x _ { i } \right) } \\& = { \sum _ { j = 1 } ^ { (k-1)} f _ { j } \left( x _ { i } \right) + f _ { k } \left( x _ { i } \right) } = \hat { y } _ { i } ^ { ( k - 1 ) } + f _ { k } \left( x _ { i } \right)
\end{aligned}
y ^ i ( 0 ) y ^ i ( 1 ) y ^ i ( 2 ) y ^ i ( k ) = 0 ← Default case = f 1 ( x j ) = y ^ i 0 + f 1 ( x i ) = f 1 ( x i ) + f 2 ( x 0 ) = y ^ i ( 2 ) + f 2 ( x 2 ) ⋮ = f 1 ( x 0 ) + f 2 ( x i ) + ⋯ + f k ( x i ) = j = 1 ∑ ( k − 1 ) f j ( x i ) + f k ( x i ) = y ^ i ( k − 1 ) + f k ( x i )
加入正則化項後的目標函數可以寫爲:
L ( ϕ ) = ∑ i = 1 n l ( y i , y ^ i ) ⏟ Loss Function + ∑ k = 1 K Ω ( f k ) ⏟ Penalty/Regularization
\mathcal { L } ( \phi ) =\underbrace { \sum _ { i = 1 } ^ { n } l \left( y _ { i } , \widehat { y } _ { i } \right)}_ \text { Loss Function }+ \underbrace { \sqrt { \sum _ { k = 1 } ^ { K } \Omega \left( f _ { k } \right) } } _ \text{ Penalty/Regularization }
L ( ϕ ) = Loss Function i = 1 ∑ n l ( y i , y i ) + Penalty/Regularization k = 1 ∑ K Ω ( f k )
其中損失函數可以任意選擇,正則化項爲:
Ω ( f k ) = γ T + 1 2 λ ∑ t = 1 T ( w t ) 2
\Omega \left( f _ { k } \right) = \gamma T + \frac{1}{2} \lambda \sum _ { t = 1 } ^ { T } \left(w _ { t} \right) ^ { 2 }
Ω ( f k ) = γ T + 2 1 λ t = 1 ∑ T ( w t ) 2
這裏使用葉子節點的個數和參數的 L2 範數相結合,正則化項的加入是爲了幫助使得最終學習到的權重比較平滑而不會過擬合( The additional regularization term helps to smooth the final learnt weights to avoid over-fitting.)針對決策樹而言,正則化操作一般是控制葉子的節點個數,樹的深度,葉子的節點值。
當然除卻正則化項的加入,也引入了放縮(Shrinkage,對每代生成的樹賦予權重係數 η \eta η ,即 y ^ i t = y ^ i ( t − 1 ) + η f t ( x i ) \hat { \boldsymbol { y } } _ { i } ^ { t } = \hat { \boldsymbol { y } } _ { i } ^ { ( t - 1 ) } + \eta \boldsymbol { f } _ { t } \left( \boldsymbol { x } _ { i } \right) y ^ i t = y ^ i ( t − 1 ) + η f t ( x i ) )和列子集採樣(Column Subsampling,隨機選擇選取 d ′ d^{\prime} d ′ 個特徵,其中 d ′ ≤ d d^{\prime} \leq d d ′ ≤ d ,即使用一部分特徵訓練)技術來防止過擬合,
梯度提升樹(Gradient Tree Boosting)
根據疊加式訓練的特點目標函數可以改寫爲:
L ( k ) = ∑ i = 1 n l ( y i , y ^ i ( k − 1 ) + f t ( x i ) ) + Ω ( f t ) = ∑ i = 1 n l ( y i , y ^ i ( k − 1 ) + f k ( x i ) ) + ∑ j = 1 k − 1 Ω ( f j ) + Ω ( f k )
\begin{aligned} \mathcal { L } ^ { ( k ) } &= \sum _ { i = 1 } ^ { n } l \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } + f _ { t } \left( \mathbf { x } _ { i } \right) \right) + \Omega \left( f _ { t } \right) \\ &= \sum _ { i = 1 } ^ { n } l \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } + f _ { k } \left( \mathbf x _ { i } \right)\right) + \sum _ { j = 1 } ^ { k - 1 } \Omega \left( f _ { j } \right) + \Omega \left( f _ { k } \right) \end{aligned}
L ( k ) = i = 1 ∑ n l ( y i , y ^ i ( k − 1 ) + f t ( x i ) ) + Ω ( f t ) = i = 1 ∑ n l ( y i , y ^ i ( k − 1 ) + f k ( x i ) ) + j = 1 ∑ k − 1 Ω ( f j ) + Ω ( f k )
其中由於 ∑ j = 1 k − 1 Ω ( f j ) \sum _ { j = 1 } ^ { k - 1 } \Omega \left( f _ { j } \right) ∑ j = 1 k − 1 Ω ( f j ) 是常值,所以該最優化問題可以寫爲:
minimize ∑ i = 1 n l ( y i , y ^ i ( k − 1 ) + f k ( x i ) ) + Ω ( f k )
\operatorname{minimize } \sum _ { i = 1 } ^ { n } l \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } + f _ { k } \left( \mathbf x _ { i } \right)\right) + \Omega \left( f _ { k } \right)
m i n i m i z e i = 1 ∑ n l ( y i , y ^ i ( k − 1 ) + f k ( x i ) ) + Ω ( f k )
知識回顧
泰勒級數
f ( x + Δ x ) = f ( x ) + f ′ ( x ) ( Δ x ) + f ′ ′ ( x ) 2 ! ( Δ x ) 2 + ⋯ + f ( n ) ( x ) n ! ( Δ x ) n + ⋯ = ∑ n = 0 ∞ f ( n ) ( x ) n ! ( Δ x ) n
\begin{aligned}
& f(x+\Delta x) \\= &f \left( x \right) + f ^ { \prime } \left( x \right) \left( \Delta x \right) + \frac { f ^ { \prime \prime } \left( x \right) } { 2 ! } \left( \Delta x \right) ^ { 2 } + \cdots + \frac { f ^ { ( n ) } \left( x \right) } { n ! } \left( \Delta x \right) ^ { n } + \cdots \\=&\sum _ { n = 0 } ^ { \infty } \frac { f ^ { ( n ) } \left( x \right) } { n ! } \left( \Delta x \right) ^ { n }
\end{aligned}
= = f ( x + Δ x ) f ( x ) + f ′ ( x ) ( Δ x ) + 2 ! f ′ ′ ( x ) ( Δ x ) 2 + ⋯ + n ! f ( n ) ( x ) ( Δ x ) n + ⋯ n = 0 ∑ ∞ n ! f ( n ) ( x ) ( Δ x ) n
爲了方便求解,對目標函數進行二階泰勒展開(將常數項抽取出來),對比與泰勒展開式,這裏將常數 y ^ i ( k − 1 ) \hat { y } _ { i } ^ { ( k - 1 ) } y ^ i ( k − 1 ) 視作 x x x ,將 f k ( x i ) f _ { k } \left( \mathbf x _ { i } \right) f k ( x i ) 視作 Δ x \Delta x Δ x :
f ( x + Δ x ) = l ( y i , y ^ i ( k − 1 ) ⏟ x + f k ( x i ) ⏟ Δ x )
f ( x + \Delta x ) = l \left( y _ { i } , \underbrace{ \hat { y } _ { i } ^ { ( k - 1 ) } }_{x}+ \underbrace{ f _ { k } \left( \mathbf x _ { i } \right)}_{\Delta x} \right)
f ( x + Δ x ) = l ⎝ ⎛ y i , x y ^ i ( k − 1 ) + Δ x f k ( x i ) ⎠ ⎞
目標函數的二階泰勒展開爲:
∑ i = 1 n l ( y i , y ^ i ( k − 1 ) + f k ( x i ) ) + Ω ( f k ) = ∑ i = 1 n [ l ( y i , y ^ i ( k − 1 ) ) + l ′ ( y i , y ^ i ( k − 1 ) ) f k ( x i ) + 1 2 l ′ ′ ( y i , y ^ i ( k − 1 ) ) f k 2 ( x i ) ] + Ω ( f k ) = ∑ i = 1 n [ l ( y i , y ^ i ( k − 1 ) ) + g i f k ( x i ) + 1 2 h i f k 2 ( x i ) ] + Ω ( f k ) ⇐ l ′ ( y i , y ^ i ( k − 1 ) ) , l ′ ′ ( y i , y ^ i ( k − 1 ) ) → g i , h i
\begin{aligned}
& \sum _ { i = 1 } ^ { n } l \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } + f _ { k } \left( \mathbf x _ { i } \right)\right) + \Omega \left( f _ { k } \right) \\
= & \sum _ { i = 1 } ^ { n } \left[ l \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } \right) + l^{\prime} \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } \right) f _ { k } \left( \mathbf x _ { i } \right) + \frac{1}{2} l^{\prime\prime} \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } \right) f^{2} _ { k } \left( \mathbf x _ { i } \right) \right]+ \Omega \left( f _ { k } \right)\\
= & \sum _ { i = 1 } ^ { n } \left[ l \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } \right) + g_i f _ { k } \left( \mathbf x _ { i } \right) + \frac{1}{2} h_i f^{2} _ { k } \left( \mathbf x _ { i } \right) \right]+ \Omega \left( f _ { k } \right) \Leftarrow l^{\prime} \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } \right),l^{\prime\prime} \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } \right) \rightarrow g_i,h_i\\
\end{aligned}
= = i = 1 ∑ n l ( y i , y ^ i ( k − 1 ) + f k ( x i ) ) + Ω ( f k ) i = 1 ∑ n [ l ( y i , y ^ i ( k − 1 ) ) + l ′ ( y i , y ^ i ( k − 1 ) ) f k ( x i ) + 2 1 l ′ ′ ( y i , y ^ i ( k − 1 ) ) f k 2 ( x i ) ] + Ω ( f k ) i = 1 ∑ n [ l ( y i , y ^ i ( k − 1 ) ) + g i f k ( x i ) + 2 1 h i f k 2 ( x i ) ] + Ω ( f k ) ⇐ l ′ ( y i , y ^ i ( k − 1 ) ) , l ′ ′ ( y i , y ^ i ( k − 1 ) ) → g i , h i
那麼在訓練第 k 個基模型時,l ( y i , y ^ i ( k − 1 ) ) , g i , h i l \left( y _ { i } , \hat { y } _ { i } ^ { ( k - 1 ) } \right) ,g_i,h_i l ( y i , y ^ i ( k − 1 ) ) , g i , h i 是已知的,可以視爲常值。
那麼該最優化問題可以進一步改寫爲:
minimize ∑ i = 1 n [ g i f k ( x i ) + 1 2 h i f k 2 ( x i ) ] + Ω ( f k )
\operatorname{minimize } \sum _ { i = 1 } ^ { n } \left[g_i f _ { k } \left( \mathbf x _ { i } \right) + \frac{1}{2} h_i f^{2} _ { k } \left( \mathbf x _ { i } \right) \right]+ \Omega \left( f _ { k } \right)
m i n i m i z e i = 1 ∑ n [ g i f k ( x i ) + 2 1 h i f k 2 ( x i ) ] + Ω ( f k )
那麼參數化後的新目標函數可以寫爲:
∑ i = 1 n [ g i f k ( x i ) + 1 2 h i f k 2 ( x i ) ] + Ω ( f k ) = ∑ i = 1 n [ g i w q ( x i ) + 1 2 h i w q ( x i ) 2 ] + γ T + 1 2 λ ∑ t = 1 T ( w t ) 2 = ∑ t = 1 T [ ∑ i ∈ I t g i ⏟ constant G t w t + 1 2 ( ∑ i ∈ I t h i ⏟ constant H t + λ ) w t 2 ] + γ T
\begin{aligned}
& \sum _ { i = 1 } ^ { n } \left[ g_i f _ { k } \left( \mathbf x _ { i } \right) + \frac{1}{2} h_i f^{2} _ { k } \left( \mathbf x _ { i } \right) \right]+ \Omega \left( f _ { k } \right) \\
= & \sum _ { i = 1 } ^ { n } \left[ g_i w_{q ( \mathbf x_i )} + \frac{1}{2} h_i {w^{2}_{q ( \mathbf x_i )}} \right]+ \gamma T + \frac{1}{2} \lambda \sum _ { t = 1 } ^ { T } \left(w _ { t} \right) ^ { 2 } \\
= & \sum _ { t = 1 } ^ { T } \left[ \underbrace{\sum _ { i \in I _ { t } } g_i }_{\text{constant } G_t } w_{t} + \frac{1}{2} (\underbrace{\sum _ { i \in I _ { t } } h_i }_{\text{constant } H_t } + \lambda ){w^{2}_{t}}\right]+ \gamma T \\
\end{aligned}
= = i = 1 ∑ n [ g i f k ( x i ) + 2 1 h i f k 2 ( x i ) ] + Ω ( f k ) i = 1 ∑ n [ g i w q ( x i ) + 2 1 h i w q ( x i ) 2 ] + γ T + 2 1 λ t = 1 ∑ T ( w t ) 2 t = 1 ∑ T ⎣ ⎢ ⎢ ⎢ ⎢ ⎡ constant G t i ∈ I t ∑ g i w t + 2 1 ( constant H t i ∈ I t ∑ h i + λ ) w t 2 ⎦ ⎥ ⎥ ⎥ ⎥ ⎤ + γ T
那麼在中括號中,由於 G t , H t G_t,H_t G t , H t 是常值,所以是一個關於 w t w_t w t 二次函數求最優解問題。
知識回顧:
一個典型的二次函數:
y = a x 2 + b x + c ( a ≠ 0 )
y = a x ^ { 2 } + b x + c \quad ( a \neq 0 )
y = a x 2 + b x + c ( a = 0 )
其最小值點爲
( − b 2 a , 4 a c − b 2 4 a )
\left( - \frac { b } { 2 a } , \frac { 4 a c - b ^ { 2 } } { 4 a } \right)
( − 2 a b , 4 a 4 a c − b 2 )
所以當樹的結構固定,也就是說 q ( x ) q(\mathbf x) q ( x ) 固定的話,在中括號中的最佳 w t ∗ w^*_t w t ∗ 爲:
− G t H t + λ
-\frac{G_t}{H_t + \lambda}
− H t + λ G t
括號中的最佳解(最小值)爲:
− G t 2 2 ( H t + λ )
-\frac{G_t^2}{ 2(H_t + \lambda)}
− 2 ( H t + λ ) G t 2
所以當前樹結構下的最佳的目標函數值 L ∗ \mathcal { L } ^ * L ∗ 爲:
− 1 2 ∑ t = 1 T G t 2 H t + λ + γ T
-\frac{1}{2} \sum _ { t = 1 } ^ { T } \frac{G_t^2}{ H_t + \lambda} + \gamma T
− 2 1 t = 1 ∑ T H t + λ G t 2 + γ T
以下圖爲例計算目標函數函數值:
尋找分割算法(Split Finding Algorithm)
精確貪心算法表明,對於連續特徵,計算上要求枚舉所有可能的分割。爲了有效地實現這一點,算法必須首先根據特徵值對數據進行排序,然後訪問排序後的數據,以實現最佳分割點的獲取。(因爲排序之後數據集的分割會高效很多,可以直接在原內存上直接讀取使用)
分割點估計算法(Approximate Algorithm for Split Finding)
既然可以計算出最佳的目標值,那麼假設當前節點的樣本集爲 I = I L ∪ I R I = I _ { L } \cup I _ { R } I = I L ∪ I R ,其中I L , I R I _ { L } , I _ { R } I L , I R 分別爲分割後左子樹和右子樹分別分的樣本集,那麼分割後的損失(目標)函數將減少:
L split = 1 2 [ G L 2 H L + λ + G R 2 H R + λ − ( G L + G R ) 2 H L + H R + λ ] − γ
\mathcal { L } _\text{split} = \frac { 1 } { 2 } \left[ \frac { G _ { L } ^ { 2 } } { H _ { L + \lambda } } + \frac { G _ { R } ^ { 2 } } { H _ { R } + \lambda } - \frac { \left( G_L + G _ { R } \right) ^ { 2 } } { H _ { L } + H _ { R } + \lambda } \right] - \gamma
L split = 2 1 [ H L + λ G L 2 + H R + λ G R 2 − H L + H R + λ ( G L + G R ) 2 ] − γ
那麼精準的貪心分割算法 則是窮舉全部的特徵,並選取 L split \mathcal { L } _\text{split} L split 最大的特徵作爲分割依據。具體實現如下:
Input: I , instance set of current node Input: d , feature dimension gain ← 0 G ← ∑ i ∈ I g i , H ← ∑ i ∈ I h i for k = 1 to m do G L ← 0 , H L ← 0 for j in sorted ( I by x j k ) d o G L ← G L + g j , H L ← H L + h j G R ← G − G L , H R ← H − H L end Output: Split with max score
\begin{array} { l } \text {Input: } I , \text { instance set of current node } \\ \text {Input: } d \text { , feature dimension } \\ \text {gain } \leftarrow 0 \\ G \leftarrow \sum _ { i \in I } g _ { i } , H \leftarrow \sum _ { i \in I } h _ { i } \\ \text {for } k = 1 \text { to } m \text { do } \\ \qquad \begin{array} { l } G _ { L } \leftarrow 0 , H _ { L } \leftarrow 0 \\ \text {for } j \text { in sorted } \left( I \text{ by }\mathbf { x } _ { j k } \right) \mathbf { d o } \\ \qquad G _ { L } \leftarrow G _ { L } + g _ { j } , H _ { L } \leftarrow H _ { L } + h _ { j } \\ \qquad G _ { R } \leftarrow G - G _ { L } , H _ { R } \leftarrow H - H _ { L } \\ \text {end } \end{array} \\ \text{Output: Split with max score} \end{array}
Input: I , instance set of current node Input: d , feature dimension gain ← 0 G ← ∑ i ∈ I g i , H ← ∑ i ∈ I h i for k = 1 to m do G L ← 0 , H L ← 0 for j in sorted ( I by x j k ) d o G L ← G L + g j , H L ← H L + h j G R ← G − G L , H R ← H − H L end Output: Split with max score
爲了提高效率,現在只針對候選集進行最佳分割點的獲取,而不是窮舉全部的樣本獲取最佳分割點,這就是本文中提出的估計分割算法 。具體實現如下:
for k = 1 to m do Propose S k = { s k 1 , s k 2 , ⋯ s k l } by percentiles on feature k . Proposal can be done per tree (global), or per split(local). end for k = 1 to m do G k v ← = ∑ j ∈ { j ∣ s k , v ≥ x j k > s k , v − 1 } g j H k v ← = ∑ j ∈ { j ∣ s k , v ≥ x j k > s k , v − 1 } h j end // Follow same step as in previous section to find max score only among proposed splits. for k = 1 to m do G L ← 0 , H L ← 0 for v = 1 to l do G L ← G L + G k v , H L ← H L + H k v G R ← G − G L , H R ← H − H L end
\begin{array} { l } \text { for } k = 1 \text { to } m \text { do } \\ \qquad \text { Propose } S _ { k } = \left\{ s _ { k 1 } , s _ { k 2 } , \cdots s _ { k l } \right\} \text { by percentiles on feature } k \text { . } \\ \qquad \text { Proposal can be done per tree (global), or per split(local). } \\ \text { end } \\ \text { for } k = 1 \text { to } m \text { do } \\ \qquad \begin{array} { l } G _ { k v } \leftarrow = \sum _ { j \in \left\{ j | s _ { k , v } \geq \mathbf { x } _ { j k } > s _ { k , v - 1 } \right\} } g _ { j } \\ H _ { k v } \leftarrow = \sum _ { j \in \left\{ j | s _ { k , v } \geq \mathbf { x } _ { j k } > s _ { k , v - 1 } \right\} } h _ { j }
\end{array} \\ \text{ end} \\ \text{ // Follow same step as in previous section to find max score only among proposed splits.}\\
\text {for } k = 1 \text { to } m \text { do }\\
\qquad \begin{array} { l } G _ { L } \leftarrow 0 , H _ { L } \leftarrow 0 \\ \text { for } v = 1 \text { to } l \text { do } \\ \qquad G _ { L } \leftarrow G _ { L } +G _ { k v } , H _ { L } \leftarrow H _ { L } + H _ { k v } \\ \qquad G _ { R } \leftarrow G - G _ { L } , H _ { R } \leftarrow H - H _ { L } \\ \text {end } \end{array} \end{array}
for k = 1 to m do Propose S k = { s k 1 , s k 2 , ⋯ s k l } by percentiles on feature k . Proposal can be done per tree (global), or per split(local). end for k = 1 to m do G k v ← = ∑ j ∈ { j ∣ s k , v ≥ x j k > s k , v − 1 } g j H k v ← = ∑ j ∈ { j ∣ s k , v ≥ x j k > s k , v − 1 } h j end // Follow same step as in previous section to find max score only among proposed splits. for k = 1 to m do G L ← 0 , H L ← 0 for v = 1 to l do G L ← G L + G k v , H L ← H L + H k v G R ← G − G L , H R ← H − H L end
簡單的說,就是根據特徵 k k k 的分佈來確定 l l l 個候選切分點 { s k 1 , s k 2 , ⋯ s k l } \left\{ s _ { k 1 } , s _ { k 2 } , \cdots s _ { k l } \right\} { s k 1 , s k 2 , ⋯ s k l } ,然後根據這些候選切分點把相應的樣本放入對應的桶 G k v , H k v G _ { k v },H _ { k v } G k v , H k v 中,對每個桶的 G k v , H k v G _ { k v },H _ { k v } G k v , H k v 進行累加。最後在候選切分點集合上貪心查找。該過程
同時爲了保證均勻分佈,常常使用加權分位數來選擇分割點以改善此需求。首先看一下獲取方法:
令 D k = { ( x 1 k , h 1 ) , ( x 2 k , h 2 ) ⋯ ( x n k , h n ) } \mathcal { D } _ { k } = \left\{ \left( \mathbf x _ { 1 k } , h _ { 1 } \right) , \left(\mathbf x _ { 2 k } , h _ { 2 } \right) \cdots \left(\mathbf x _ { n k } , h _ { n } \right) \right\} D k = { ( x 1 k , h 1 ) , ( x 2 k , h 2 ) ⋯ ( x n k , h n ) } ,這裏提出一種排序函數 r k : R → [ 0 , + ∞ ) r _ { k } : \mathbb { R } \rightarrow [ 0 , + \infty ) r k : R → [ 0 , + ∞ ) ,具體實現爲:
r k ( z ) = 1 ∑ ( x , h ) ∈ D k h ∑ ( x , h ) ∈ D k , x < z h
r _ { k } ( z ) = \frac { 1 } { \sum _ { ( x , h ) \in \mathcal { D } _ { k } } h } \sum _ { ( x , h ) \in \mathcal { D } _ { k } , x < z } h
r k ( z ) = ∑ ( x , h ) ∈ D k h 1 ( x , h ) ∈ D k , x < z ∑ h
這代表了第 k 個特徵值小於 z z z 的比例。目標是找到候選分割點 { s k 1 , s k 2 , ⋯ s k l } \left\{ s _ { k 1 } , s _ { k 2 } , \cdots s _ { k l } \right\} { s k 1 , s k 2 , ⋯ s k l } 使得:
∣ r k ( s k , j ) − r k ( s k , j + 1 ) ∣ < ϵ , s k 1 = min i x i k , s k l = max i x i k
\left| r _ { k } \left( s _ { k , j } \right) - r _ { k } \left( s _ { k , j + 1 } \right) \right| < \epsilon , \quad s _ { k 1 } = \min _ { i } \mathbf { x } _ { i k } , s _ { k l } = \max _ { i } \mathbf { x } _ { i k }
∣ r k ( s k , j ) − r k ( s k , j + 1 ) ∣ < ϵ , s k 1 = i min x i k , s k l = i max x i k
其中 ϵ \epsilon ϵ 是一個估計係數,其表示候選樣本點只有原來的 1 / ϵ 1/\epsilon 1 / ϵ 。
爲什麼使用 h h h 作爲排序依據,將下式重寫:
L ~ ( k ) = ∑ i = 1 n [ g i f k ( x i ) + 1 2 h i f k 2 ( x i ) ] + Ω ( f k )
\tilde { \mathcal { L } } ^ { ( k ) } = \sum _ { i = 1 } ^ { n } \left[ g _ { i } f _ { k } \left( \mathbf { x } _ { i } \right) + \frac { 1 } { 2 } h _ { i } f _ { k } ^ { 2 } \left( \mathbf { x } _ { i } \right) \right] + \Omega \left( f _ { k } \right)
L ~ ( k ) = i = 1 ∑ n [ g i f k ( x i ) + 2 1 h i f k 2 ( x i ) ] + Ω ( f k )
即:
L ~ ( k ) = ∑ i = 1 n 1 2 h i ( f t ( x i ) − g i / h i ) 2 + Ω ( f t ) + constant
\tilde { \mathcal { L } } ^ { ( k ) } = \sum _ { i = 1 } ^ { n } \frac { 1 } { 2 } h _ { i } \left( f _ { t } \left( \mathbf { x } _ { i } \right) - g _ { i } / h _ { i } \right) ^ { 2 } + \Omega \left( f _ { t } \right) + \text { constant }
L ~ ( k ) = i = 1 ∑ n 2 1 h i ( f t ( x i ) − g i / h i ) 2 + Ω ( f t ) + constant
該公式中由於 g i , h i g _ { i } , h _ { i } g i , h i 均爲常值,最小化該損失函數實際上就是在使用 f t ( x i ) f _ { t } \left( \mathbf { x } _ { i } \right) f t ( x i ) 擬合 g i / h i g _ { i } / h _ { i } g i / h i 。而括號外的 h i h _ { i } h i 將作爲樣本 i 的權重值用於計算損失值。權重越大意味該樣本點的預測值越不確定。 所以近似分位圖在選分位點時考慮了二階導也就是權重,因此這權重大的部分就會被切分的粒度更細,也就是說權重越大采樣到的概率越高。
缺失值處理(Sparsity-aware Split Finding)
這裏處理缺失值使用的方法是訓練出默認的分支是左子樹還是右子樹。
具體的算法實現如下:
Input: I , instance set of current node Input: I k = { i ∈ I ∣ x i k ≠ missing } Input: d , feature dimension Also applies to the approximate setting, only collect statistics of non-missing entries into buckets gain ← 0 G ← ∑ i ∈ I , g i , H ← ∑ i ∈ I h i for k = 1 to m do // enumerate missing value goto right G L ← 0 , H L ← 0 for j in sorted ( I k , ascent order b y x j k ) do G L ← G L + g j , H L ← H L + h j G R ← G − G L , H R ← H − H L score ← max ( score , G L 2 H L + λ + G R 2 H R + λ − G 2 H + λ ) end // enumerate missing value goto left G R ← 0 , H R ← 0 for j in sorted ( I k , descent order b y x j k ) do G R ← G R + g j , H R ← H R + h j G L ← G − G R , H L ← H − H R score ← max ( score , G L 2 H L + λ + G R 2 H R + λ − G 2 H + λ ) end Output split and default directions with max gain
\begin{array} { l }
\text {Input: } I , \text { instance set of current node } \\
\text {Input: } I _ { k } = \left\{ i \in I | x _ { i k } \neq \text { missing } \right\} \\ \text {Input: } d , \text { feature dimension } \\
\text {Also applies to the approximate setting, only collect statistics of non-missing entries into buckets } \\
\operatorname { gain } \leftarrow 0 \\ G \leftarrow \sum _ { i \in I } , g _ { i } , H \leftarrow \sum _ { i \in I } h _ { i } \\ \text {for } k = 1 \text { to } m \text { do } \\ \qquad \begin{array} { l } \text {// enumerate missing value goto right } \\ G _ { L } \leftarrow 0 , H _ { L } \leftarrow 0 \\ \text {for } j \text { in sorted } \left( I _ { k } , \text { ascent order } b y \mathbf { x } _ { j k } \right) \text { do } \\
\qquad G _ { L } \leftarrow G _ { L } + g _ { j } , H _ { L } \leftarrow H _ { L } + h _ { j } \\
\qquad G _ { R } \leftarrow G - G _ { L } , H _ { R } \leftarrow H - H _ { L } \\ \qquad \text {score } \leftarrow \max \left( \text { score } , \frac { G _ { L } ^ { 2 } } { H _ { L } + \lambda } + \frac { G _ { R } ^ { 2 } } { H _ { R } + \lambda } - \frac { G ^ { 2 } } { H + \lambda } \right) \\ \text {end } \\ \text {// enumerate missing value goto left } \\ G _ { R } \leftarrow 0 , H _ { R } \leftarrow 0 \\
\text {for } j \text { in sorted } \left( I _ { k } , \text { descent order } b y \mathbf { x } _ { j k } \right) \text { do } \\
\qquad G _ { R } \leftarrow G _ { R } + g _ { j } , H _ { R } \leftarrow H _ { R } + h _ { j } \\
\qquad G _ { L } \leftarrow G - G _ { R } , H _ { L } \leftarrow H - H _ { R } \\
\qquad \text {score } \leftarrow \max \left( \text { score } , \frac { G _ { L } ^ { 2 } } { H _ { L } + \lambda } + \frac { G _ { R } ^ { 2 } } { H _ { R } + \lambda } - \frac { G ^ { 2 } } { H + \lambda } \right) \\\text {end } \\ \text {Output split and default directions with max gain } \end{array} \end{array}
Input: I , instance set of current node Input: I k = { i ∈ I ∣ x i k = missing } Input: d , feature dimension Also applies to the approximate setting, only collect statistics of non-missing entries into buckets g a i n ← 0 G ← ∑ i ∈ I , g i , H ← ∑ i ∈ I h i for k = 1 to m do // enumerate missing value goto right G L ← 0 , H L ← 0 for j in sorted ( I k , ascent order b y x j k ) do G L ← G L + g j , H L ← H L + h j G R ← G − G L , H R ← H − H L score ← max ( score , H L + λ G L 2 + H R + λ G R 2 − H + λ G 2 ) end // enumerate missing value goto left G R ← 0 , H R ← 0 for j in sorted ( I k , descent order b y x j k ) do G R ← G R + g j , H R ← H R + h j G L ← G − G R , H L ← H − H R score ← max ( score , H L + λ G L 2 + H R + λ G R 2 − H + λ G 2 ) end Output split and default directions with max gain
基本的實現方式就是將不缺失該特徵的樣本,只向左子樹樣本集(或右子樹樣本集)添加,那麼缺失該特徵的樣本將會直接分配在右子樹樣本集(或左子樹樣本集),並且窮舉全部可能,這樣便可以求出哪種默認操作(向左子樹樣本集還是右子樹樣本集添加)更好一些。
並行學習(Column Block for Parallel Learning)
樹學習最耗時的部分是將數據排序。爲了降低排序的成本,建議將數據存儲在內存單元中,作者將其稱爲塊(block)。每個塊中的數據以壓縮列(compressed column,CSC)格式存儲,每列按相應的特徵值排序。這個輸入數據佈局只需要在訓練之前計算一次,並且可以在以後的迭代中重用。下圖便是這種塊實現和使用流程:
可見其在存儲特徵值的同時也將特徵值指向的梯度(或二階梯度)值進行了存儲。這使得並行計算全部特徵的損失函數值成爲了可能。
緩存優化(Cache-aware Access)
使用Block結構的一個缺點是取梯度(或二階梯度)值的時候,是通過索引來獲取的,而這些梯度的獲取順序是按照特徵的大小順序的。雖然時間複雜度爲 O ( 1 ) O(1) O ( 1 ) ,但這將導致梯度的獲取是非連續的內存訪問,可能使得CPU緩存命中率低,從而影響算法效率。
因此,在精準貪心算法中, 提出使用緩存預取算法。具體來說,對每個線程分配一個連續的緩存,按照特徵值的排列順序,以小批量的方式依次讀取梯度信息並存入該連續緩存中,這樣只需要一次非連續讀取。該方式在訓練樣本數大的時候可以有效減小運算開銷。
參考論文:XGBoost: A Scalable Tree Boosting System