0.前言
XGBoost不僅在單機上通過OMP實現高度並行化,還通過MPI接口與近似分位點算法(論文中是weighted quantiles sketch)實現高效的分佈式並行。其中weighted quantiles sketch框架基於
ϵ
-approximate quantile近似分位點算法。不得不說分位點算法在分佈式系統、流式系統中使用是個很天才的想法,很多分佈式算法的基石。早在2001年,M.Greenwald和S. Khanna提出了GK Summay分位點近似算法(ϵ−approximate ϕ−quantile),直到到2007年被Q. Zhang和W. Wang提出的多層level的merge與compress/prune框架進行高度優化,而被稱爲A fast algorithm for approximate quantiles,目前XGBoost框架套用A fast algorithm算法結構。
本文主要介紹GK Summay算法,後續博客會持續更新分佈式GK Summay算法以及A fast algorithm for approximate quantiles算法,最後還會分析XGBoost中使用的weighted quantiles sketch算法,博客內容來源主要是原始論文與Emory大學的流式數據庫的課程內容,本文僅提取出關鍵內容加入筆者的個人理解,有錯誤還望諒解與告知。
1.背景
ϕ−quantile
分位點概念:排序爲
rank=⌊ϕN⌋
的元素,其中
N
爲序列中元素的個數。考慮以下例子數據:
11 , 21 , 24 , 61 , 81 , 39 , 89 , 56 , 12 , 51
查詢
ϕ−quantile
分位點所在數據前,需要對無序數據進行排序:
input:sort:rank:111112112224213612448139539516895675661812819518910
排序後很容得到:
0.5−quantile
對應
rank=5
,值爲39。 此外還有,
0.1−quantile
對應
rank=1
,值爲11。
ϵ−approximate ϕ−quantile
分位點概念:考慮誤差近似,即給定誤差
ϵ
和分位點
ϕ
,只需要給定排序區間
r′∈[(ϕ−ε)N, (ϕ+ε)N]
內任意元素即可。類似地,給定
ε=0.1,ϕ=0.5
,可得rank值在區間
{4,5,6}
。給定區間內任意元素,都滿足排序誤差
ϵN
要求。
爲了滿足對數據近似分位點的頻繁查詢,考慮以下幾種場景:
1. 固定不變的數據集
2. 流式數據,數據長度不斷增加
3. 數據源分佈存儲,但數據長度固定
4. 數據源分佈存儲+流式數據,數據長度不斷增加
對於場景1,可以對數據進行預排序,每次查詢採用二分法精確查找,時間複雜度爲
O(logN)
。考慮排序誤差
ϵN
, 我們可以對數據進行分桶,分桶長度爲
ϵN
來保證誤差,即分
1/ϵ
個桶,時間複雜度降低爲
O(log(1/ϵ))
,簡單的離線排序和分桶都屬於offline算法,無法滿足場景2、3、4場景,這就需要本文介紹online算法來構建查詢summary。
2. GK Summary算法
2.1 GK Summary定義
GK Summary原本是針對流式系統分位點查詢設計的,基於上述場景2。對於
ϵ−approximate
分位點查詢,可以構建查詢summary結構,包含
m
個summary tuple的集合:
{(v1,min1,max1),(v2,min2,max2),...,(vm,minm,maxm)}
定義:
vi
爲命中第
i
個summary的代表值,簡單起見,
vi
定義爲
rank=mini
對應值,summary的
rank
區間爲
[mini,maxi]
。
約束:爲了滿足給定誤差
ϵN
,
maxi−mini≤ϵN
。證明:顯而易見。
流式數據是不斷更新,這種summary結構存在缺點:每次插入中間值,需要更新插入位置後面的summary,更新複雜度高。流式數據插入更新頻率比查詢頻率要更高,必須優先解決數據插入構建summary的複雜度。
對此,Greenwald與Khanna提出對數據插入更新友好的GK Summary結構,相對於存絕對值,GK Summary採用相對值的結構,類似地,包含
m
個summary tuple的集合:
(v0,g0,Δ0),(v1,g1,Δ1),...,(vs−1,gs−1,Δs−1)
定義:
vi
爲命中第
i
個summary的代表值,
rmin(v)
爲
v
所在summary的下界,
rmax(v)
爲
v
所在summary的上界,則
gi
、
Δi
定義如下:
gi={rmin(vi)−rmin(vi−1)1, i>0, i=0
Δi={rmax(vi)−rmin(vi)0, i<s−1, i=s−1
爲了便於理解,
gi
、
Δi
關係如下圖:
邊界條件:
v0
爲數據中最小值,
vs−1
爲數據中最大值。等價於第一種定義的summary,排序相對值轉化爲絕對值,滿足以下性質:
性質1:
rmin(vi)=∑ij=0gi
, 由
gi
定義,可以證明:
rmin(vi)=gi+rmin(vi−1)=gi+gi−1+rmin(vi−2)⋮=gi+gi−1+gi−2...+rmin(v0)
此外,邊界設定
rmin(v0)=g0=1
,得證。
性質2:
rmax(vi)=∑ij=0gi+Δi
, 由性質1與定義
Δi=rmax(vi)−rmin(vi)
可得
性質3:
∑s−1j=0gi=N
, 由性質2與邊界設定
Δs−1=0
可得。
約束:爲了滿足給定誤差
ϵN
,
maxi(gi+Δi)≤2ϵN
。證明如下:
設最大誤差爲
e=maxi(gi+Δi)/2
, 則
∀ gi+Δi≤2e≤2ϵN
1) 首先考慮邊界情況:
r>N−e
, 直接返回
vs−1
,對應
rank=N
,此時誤差爲
N−r<e
2) 一般情況:
r≤N−e
, 找到最小的
j
,使得
rmax(vj)>r+e
,必有
rmax(vj−1)≤r+e
。
∀ gi+Δi≤2e⇒rmin(vj−1)=rmax(vj)−(gi+Δi)>r−e
因此,查詢返回爲
vj−1
, 其代表區間在
[r−e,r+e]
內,滿足誤差
ϵN
要求,得證。更直觀的圖示如下:
Summary查詢過程:上述證明揭示了對於任意分位點
ϕ
,計算出排序位置
r
:1)找到最小
j
,使得
rmax(vj)>r+e
,則返回
vj−1
值,2)如果找不到則返回
vs−1
。
只要流式系統中每個時刻都維持這種summary結構,每次查詢都能滿足精度要求,但是流式數據實時更新,需要解決新增數據的summary更新問題。
2.2 GK Summary插入insert
流式系統數據實時更新,不斷產生新數據,數據量不斷增加,儘管查詢近似度
ϵ
不變,隨着數據量增加,
ϵN
不斷變大。爲了保證誤差,任何時刻都要保證滿足約束
maxi(gi+Δi)≤2ϵN
。首先考慮數據
v
插入情況的summary更新:
1) 最小值邊界情況:
v<v0
,則插入summary爲
(v,1,0)
2) 最大值邊界情況:
v>vs−1
, 則插入summary爲
(v,1,0)
3) 一般情況:
vi−1≤v<vi
,則插入summary爲
(v,1,gi+Δi−1)
證明:對於情況1)與2),顯而易見的。對於情況3):
summary內部tuple按照對應的
v
排序,新增summary是插入到第
i−1
個summary後面,前
i−1
個summary不受影響,對於後面的
i
到
s−1
的summary來說,對應
rank
值均增加,
rmax
與
rmin
均需加1,因此
g
、
Δ
均不需要改變,也就滿足了誤差約束條件。這裏可以看出:與前文提到的summary相比,GK Summary對於新增數據無需更新其他summary。
新增summary必須滿足
g≥1
,
g+Δ≤gi+Δi
,如果不滿足則沒有必要插入,因爲前後2個summary可以覆蓋新增的summary,選擇
g=1
的主要原因是有利於後期summary的delete,後續會談到,設置
Δ=gi+Δi−1
能使得
g+Δ≤2ϵN
,原則上
Δ≤⌊2ϵN⌋−1
任意值即可,後續可以看到新增非邊界的summary tuple的
Δ=⌊2ϵN⌋−1
。
2.3 GK Summary刪除delete與compress
每次數據插入都需要新增summary,summary不能持續增加而不刪除,因此到達一定程度需要對summary進行delete。爲了時刻滿足
maxi(gi+Δi)≤2ϵN
,GK Summary 的delete操作:
如果存在:
gj+...gi+gi+1+Δi+1≤2ϵN
,
則可以用
(vi+1,gj+...+gi+gi+1,Δi+1)
來替代
{(vj,gj,Δj)...(vi,gi,Δi),(vi+1,gi+1,Δi+1)}
換句話說:
1)刪除summary集合:
{(vj,gj,Δj)...(vi,gi,Δi)}
2)更新
(vi+1,gi+1,Δi+1)⇒(vi+1,gj+...+gi+gi+1,Δi+1)
delete操作特性:只改變
vi+1
所在summary的
gi+1
, 並不改變
Δi+1
。也就是說
Δ
越小,在滿足誤差約束下,具有合併更多summary的潛力。
爲了追求效率,根據delete性質,GK提出compress操作,首先說明論文的概念:
1. Fullness: 如果
gi+Δi=⌊2ϵN⌋
,則說明該summary tuple是full的
2. Capacity:由於delete操作
Δ
不變性,因此summary達到full,
g
最終爲
⌊2ϵN⌋
-
Δ
,因此
Δ
決定了summary tuple的capacity。
3. Bands:compress操作主要是減少summary總數,每個summary的元素覆蓋數coverage取決於
g
, 因此需要保持
g
值儘量大,對應
Δ
儘量少,也就是說
Δ
值小的summary應該越多,引入
bands
主要是對
summary
進行分級,對於給定
Δ
與
p=⌊2ϵN⌋
,可以計算
band
值爲:
capactity=p−Δband=⌊log2(capactity)⌋
對於
band=α
,
capactity
區間爲
[2α,2α+1)
,
Δ
對應區間
(p−2α+1,p−2α]
,注意開閉區間。
band
值越大,
Δ
越小,capacity能力越大。考慮合併策略:對於相連
summaryi
,
summaryi+1
合併,合併更新到
band
值較小的
summary
上,由於delete的
Δ
不變性,保留
band
值大的,有更大的
capacity
,後期能夠容納更多的summary。對每個summary都包含
Δ
,可以組織成$bands¥樹結構,如下圖所示:
band
樹結構特性:對於節點
V
,其所有子節點與
V
在
summary
中是連續相連的。
summary
更新過程中如何保證這一性質?
1)每次新數據會插入新
summary
,
Δ=⌊2ϵN⌋−1
, 對應
band=0
,爲最小值,除非單獨節點,否則一定爲右邊節點的子節點。
2)合併策略:對於
summaryi
,
summaryi+1
合併,合併更新到
band
值較小的
summary
上。
因此,上述操作會維持這種
band
樹結構性質。此外,滿足上述條件,論文中給出基於
band
的compress算法:
算法從右往左掃描,其中
g∗
爲當前節點與其所有子節點
g
總和,如果遇到:
BAND(Δi,2ϵn)≤BAND(Δi+1,2ϵn)
且
g∗i+gi+1+Δi+1<2ϵn
, 刪除
i
節點與其子節點對應summary tuple。
2.4 GK Summary算法
此外,需要明確compress操作執行時機:有時候原來的summary是不可合併的,但是隨着數據量
N
增加,
p=2ϵN
相應增大,
band
、
capacity
值是會隨着階段性不斷變大的,而出現可合併的情況. 論文給出數據每增量
1/2ϵ
時,會執行compress操作。因爲這種情況下誤差值絕對值增量爲
2ϵ×1/2ϵ=1
,原本不滿足誤差約束條件的情況會發生改變,否則正常插入數據到summary,算法如下:
論文還證明了以下性質和結論,由於章節內容過多,下面僅放置結論,首先繼續說個概念:
Coverage:每個summary tuple會cover新增數據,對於
summaryi
,cover數據來源:1)直接cover:即單個數據插入生成的summary直接merge到
summaryi
;2)間接cover:即該數據原本被merge到
summaryj
, 而
summaryj
又merge到
sumummaryi
,cover數據來源:1)直接cover:即單個數據插入生成的summary直接merge到
summaryi
;2)間接cover:即該數據原本被merge到
summaryj
, 而
summaryj
又merge到
summaryi