算法強化 —— XGBoost(三)

缺失值處理

真實場景中,有很多可能導致產生稀疏。如:數據缺失、某個特徵上出現很多0項、人工進行one-hot編碼導致大量的0
理論上,數據缺失和數值0的含義是不同的,數值0是有效的
實際上,數值0的處理方式類似缺失值的處理方式,都視爲稀疏特徵
在xgboost中,數值0的處理方式和缺失值的處理方式是同一的。這只是一個計算上的優化,用於加速稀疏特徵的處理速度
對於稀疏特徵,只需要對有效值進行處理,無效值則採用默認的分裂方向。
注意每個結點的默認分裂方向可能不同。

XGBoost中實現的方式

在xgboost算法的實現中,允許對數值0進行不同的處理。可以將數值0視作缺失值,也可以將其視作有效值。
如果數值0是有真實意義的,則建議將其視作有效值。

缺失值處理算法

輸入:數據集D=(x1,y1~),(x2,y2~),...,(xN,yN~)D = {(\overrightarrow{x_1},\tilde{y_1}),(\overrightarrow{x_2},\tilde{y_2}),...,(\overrightarrow{x_N},\tilde{y_N})},其中樣本xi=(xi,1,xi,2,...,xi,n)T\overrightarrow{x_i} = (x_{i,1},x_{i,2},...,x_{i,n})^T
屬於當前葉節點的樣本的下標集合I\mathbb{I}
屬於當前葉節點,且第k維特徵有效的樣本的下標集合Ik=iIxk,imissing\mathbb{I}_k = {i \in \mathbb{I} | x_{k,i} \not= missing}
輸出:當前葉節點最佳分裂點

算法

初始化:score0,GiIgi,HiIhiscore \leftarrow 0, G \leftarrow \sum_{i \in \mathbb{I}}g_i,H \leftarrow \sum_{i \in \mathbb{I}}h_i
遍歷各維度:k = 1,…,n

先從左邊開始遍歷
初始化 GL0,HL0G_L \leftarrow 0,H_L \leftarrow 0
遍歷各拆分點:沿着第k維,將當前有效的葉節點的樣本從小到大排序,相當於所有無效特徵值的樣本放在最右側,因此可以保證無效的特徵值都在右子樹。
然後用j順序遍歷排序後的樣本下標:
GLGL+gj,HLHL+hjGRGGL,HRHHL\begin{aligned} &\mathbf{G}_{L} \leftarrow \mathbf{G}_{L}+g_{j}, \quad \mathbf{H}_{L} \leftarrow \mathbf{H}_{L}+h_{j}\\ &\mathbf{G}_{R} \leftarrow \mathbf{G}-\mathbf{G}_{L}, \quad \mathbf{H}_{R} \leftarrow \mathbf{H}-\mathbf{H}_{L} \end{aligned}
scoremax(score,GL2HL+λ+GR2HR+λG2H+λ)\text {score} \leftarrow \max \left(\text {score}, \frac{\mathbf{G}_{L}^{2}}{\mathbf{H}_{L}+\lambda}+\frac{\mathbf{G}_{R}^{2}}{\mathbf{H}_{R}+\lambda}-\frac{\mathbf{G}^{2}}{\mathbf{H}+\lambda}\right)

再從右邊開始遍歷
初始化GR0,HR0G_R \leftarrow 0,H_R \leftarrow 0
遍歷各拆分點:沿着第k維,將當前有效的葉節點的樣本從大到小排序,相當於所有無效特徵值的樣本放在最左側,因此可以保證無效的特徵值都在左子樹。
然後用j順序遍歷排序後的樣本下標:
GRGR+gj,HRHR+hjGLGGL,HLHHR\begin{aligned} &\mathbf{G}_{R} \leftarrow \mathbf{G}_{R}+g_{j}, \quad \mathbf{H}_{R} \leftarrow \mathbf{H}_{R}+h_{j}\\ &\mathbf{G}_{L} \leftarrow \mathbf{G}-\mathbf{G}_{L}, \quad \mathbf{H}_{L} \leftarrow \mathbf{H}-\mathbf{H}_{R} \end{aligned}
scoremax(score,GL2HL+λ+GR2HR+λG2H+λ)\text {score} \leftarrow \max \left(\text {score}, \frac{\mathbf{G}_{L}^{2}}{\mathbf{H}_{L}+\lambda}+\frac{\mathbf{G}_{R}^{2}}{\mathbf{H}_{R}+\lambda}-\frac{\mathbf{G}^{2}}{\mathbf{H}+\lambda}\right)
選取最大的score對應的維度和拆分點作爲最優拆分點

其他優化

預排序

xgboost提出column block 數據結構來降低排序時間
每一個block代表一個屬性,樣本在該block中按照它在該屬性的值排好序
這些block只需要在程序開始的時候計算一次,後續排序只需要線性掃描這些block即可
由於屬性之間是獨立的,因此在每個維度尋找劃分點可以並行計算
block可以僅存放樣本的索引,而不是樣本本身,這樣節省了大量的存儲空間

緩存命中率的優化

Cache-aware預取

由於在column block中,樣本的順序會被打亂,這會使得從導數數組中獲取gig_i時的緩存命中率較低。
因此xgboost提出了cache-aware預取算法,用於提升緩存命中率
xgboost會以minibatch的方式累加數據,然後在後臺開啓一個線程來加載需要用到的導數gig_i
這裏有個這種,minibatch太大,則會引起cache miss;太小,則並行程度較低

out of score 大數據集

xgboost利用硬盤來處理超過內存容量的大數據。其中使用了下列技術
使用block 壓縮技術來環節內存和硬盤的數據交換IO:數據按列壓縮,並且在硬盤到內存的傳輸過程中被自動解壓縮
數據隨機分片到多個硬盤,每個硬盤對應一個預取線程,從而加大"內存-硬盤"交換數據的吞吐量

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章