日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【Datawhale|天池】心跳信号分类预测 (4) - 模型 之 XGBoost

發布時間:2023/12/20 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Datawhale|天池】心跳信号分类预测 (4) - 模型 之 XGBoost 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文主要分享自己總結的關于 xgboost 的筆記。

基礎知識

  • 基學習器 CART
    Regression:L(yi,y^i)=(yi?f(xi))2Classification:Gini(D)=∑k=1Kpk(1?pk)=1?∑k=1Kpk2Regression: L(y_i, \hat y_i) = (y_i - f(x_i))^2 \\ Classification: Gini(D) = \sum_{k=1}^K p_k(1-p_k) = 1 - \sum_{k=1}^K p_k^2 Regression:L(yi?,y^?i?)=(yi??f(xi?))2Classification:Gini(D)=k=1K?pk?(1?pk?)=1?k=1K?pk2?
    回歸單樣本的損失函數,和分類時在數據集D上的基尼指數。f 表示樹,f(x) 則是 x 對應的葉子節點的值。

    對于分類問題,在 CART 分割時,我們按照 Gini 指數最小來確定分割點的位置。即:
    cutpoint(A)=argminv∈AV∑i=12∣Di∣∣D∣Gini(Di)bestA,best_v=argminA∈features[argminv∈AV∑i=12∣Di∣∣D∣Gini(Di)]cutpoint(A) = arg \; min_{v \in A_V} \; \sum_{i=1}^2 \frac {|D_i|}{|D|} Gini(D_i) \\ bestA, best\_v = arg \; min_{A \in features} [ arg \; min_{v \in A_V} \; \sum_{i=1}^2 \frac {|D_i|}{|D|} Gini(D_i) ] cutpoint(A)=argminvAV??i=12?DDi??Gini(Di?)bestA,best_v=argminAfeatures?[argminvAV??i=12?DDi??Gini(Di?)]

  • XGBoost 的目標函數:

    Obj=∑i=1nL(yi,y^i)+∑k=1KΩ(fk)whereL(yi,y^i)=(yi?f(xi))2Ω(f)=γT+12λ∣∣ω∣∣2=γT+12λ∑j=1T∣∣ωj∣∣2Obj = \sum_{i=1}^nL(y_i, \hat y_i) + \sum_{k=1}^K \Omega (f_k) \\ where \quad L(y_i, \hat y_i) = (y_i - f(x_i))^2 \\ \Omega (f) = \gamma T + \frac12 \lambda ||\omega||^2 = \gamma T + \frac12 \lambda \sum_{j=1}^T ||\omega_j||^2 Obj=i=1n?L(yi?,y^?i?)+k=1K?Ω(fk?)whereL(yi?,y^?i?)=(yi??f(xi?))2Ω(f)=γT+21?λω2=γT+21?λj=1T?ωj?2
    假設有 n 個樣本,K 棵樹。目標函數由兩部分構成,第一部分用來衡量預測分數和真實分數的差距,另一部分則是正則化項。正則化項同樣包含兩部分,T 表示葉子結點的個數,w 表示葉子節點的分數。γ\gammaγ 可以控制葉子結點的個數,λ 可以控制葉子節點的分數不會過大,防止過擬合。

  • 自問自答

    常用的參數都有哪些?

    一開始,當然是要先設置 booster,一版直接默認用 gbtree 就可以了,另外還有兩個常用的全局設置項是 nthread、verbosity。

    接下來,幾個常用的能影響到模型擬合能力的參數是:

    • num_boost_round(n_estimators)
    • max_depth(樹的深度)
    • eta(learning_rate)

    然后,有兩個正則化、類似于用來控制預剪枝的參數是:

    • gamma(分裂時目標函數增益的閾值)
    • min_child_weight(分裂時孩子權重之和的閾值)

    另外幾個用于控制正則項的參數是:

    • lambda(這是葉子節點 L2 正則項的系數)
    • alpha(這是葉子節點 L1 正則項的系數)
    • subsample(訓練數據"被隨機采樣用來訓練"的比例)
    • colsample_bytree(訓練數據的所有特征"被隨機選擇用來訓練一棵樹"的比例)

    對于數據不平衡問題,可能還用到的重要參數是:

    • scale_pos_weight(一般設置成正例和負例樣本數量的比值)
    • max_delta_step

    如何通過優化目標函數值來計算葉子節點權重?

    Obj=∑i=1nL(yi,y^i)+∑k=1KΩ(fk)whereL(yi,y^i)=(yi?f(xi))2Ω(f)=γT+12λ∣∣ω∣∣2=γT+12λ∑j=1Twj2Obj = \sum_{i=1}^nL(y_i, \hat y_i) + \sum_{k=1}^K \Omega (f_k) \\ where \quad L(y_i, \hat y_i) = (y_i - f(x_i))^2 \\ \Omega (f) = \gamma T + \frac12 \lambda ||\omega||^2 = \gamma T + \frac12 \lambda \sum_{j=1}^T w_j^2 Obj=i=1n?L(yi?,y^?i?)+k=1K?Ω(fk?)whereL(yi?,y^?i?)=(yi??f(xi?))2Ω(f)=γT+21?λω2=γT+21?λj=1T?wj2?
    那么,假設樹的結構已經確定,每個葉子節點對應于一部分樣本,即可以將決策樹表示為一個映射 q:Rd→{1,2,...,T}q : R^d \to \{1, 2, ..., T\}q:Rd{1,2,...,T} ,每個 d 維的樣本 xix_ixi? 可以映射到決策樹 T 個葉子節點中的一個,要如何計算對應的葉子節點權重和相應的目標函數值呢?

    一種簡單粗暴的方法是,對于分類問題,將葉子節點的值設置為該節點樣本集中樣本數量最多類別;對于回歸問題,則設置為標簽值的平均。但是,這就完全忽略目標函數的存在了,我們的目標是要最小化目標函數。

    以下對目標函數進行一些化簡:

    假設現在學習到了第 t 棵樹,記為 ft(x)f_t(x)ft?(x) ,那么 y^t=y^t?1+ft(x)\hat y^t = \hat y^{t-1} + f_t(x)y^?t=y^?t?1+ft?(x) 。我們的目標是使得 y^t\hat y^ty^?t 盡量等于 yyy ,即 $ \hat y^{t-1} + f_t(x)$ 盡量趨近于 yyy ,也就是讓 ft(x)f_t(x)ft?(x) 趨近于 y?y^t?1y - \hat y^{t-1}y?y^?t?1 ,換言之, y?y^t?1y - \hat y^{t-1}y?y^?t?1 就是當前這棵樹的擬合目標,或者說樣本的標簽值(說起來,這和 GBDT 其實是一樣的,只是這里目標函數不同,導致最后擬合出來的葉子節點的權重會有所不同)。代入目標函數中:
    Obj(t)=∑i=1nL(yi,y^it?1+ft(xi))+Ω(ft)Obj^{(t)} = \sum_{i=1}^n L(y_i, \hat y_i^{t-1} + f_t(x_i)) + \Omega(f_t) Obj(t)=i=1n?L(yi?,y^?it?1?+ft?(xi?))+Ω(ft?)
    我們知道有泰勒公式二階展開:
    f(x+Δx)=f(x)+f′(x)?Δx+12f′′(x)?(Δx)2f(x + \Delta x) = f(x) + f'(x)·\Delta x + \frac 12 f''(x)·(\Delta x)^2 f(x+Δx)=f(x)+f(x)?Δx+21?f(x)?(Δx)2
    yit?1y_i^{t-1}yit?1? 看作上式中的 x,ft(x)f_t(x)ft?(x) 看作上式中的 Δx\Delta xΔxL(yi,y^it?1)L(y_i, \hat y_i^{t-1})L(yi?,y^?it?1?) 看作上式的 f(x)f(x)f(x) 。那么目標函數可以改寫成:
    Obj(t)≈∑i=1n[L(yi,y^it?1)+gift(xi)+12hift2(xi)]+Ω(ft)Obj^{(t)} \approx \sum_{i=1}^{n} [L(y_i, \hat y_i^{t-1}) + g_i f_t(x_i) + \frac 12 h_i f_t^2 (x_i)] + \Omega (f_t) Obj(t)i=1n?[L(yi?,y^?it?1?)+gi?ft?(xi?)+21?hi?ft2?(xi?)]+Ω(ft?)
    這里的 gi,hig_i, h_igi?hi? 分別是 L(yi,y^it?1)L(y_i, \hat y_i^{t-1})L(yi?,y^?it?1?) 關于 y^it?1\hat y_i^{t-1}y^?it?1? 的一階導和二階導。若以 平方誤差 作為損失函數,即 L(yi,y^it?1)=(yi?y^it?1)2L(y_i, \hat y_i^{t-1}) = (y_i - \hat y_i^{t-1})^2L(yi?,y^?it?1?)=(yi??y^?it?1?)2 ,那么有 gi=2(y^it?1?yi)g_i = 2(\hat y_i^{t-1} - y_i)gi?=2(y^?it?1??yi?) , hi=2h_i = 2hi?=2

    由于 L(yi,y^it?1)L(y_i, \hat y_i^{t-1})L(yi?,y^?it?1?) 是常數項不影響我們把目標函數最小化,所以上式可以簡寫成:
    Obj(t)≈∑i=1n[gift(xi)+12hift2(xi)]+Ω(ft)Obj^{(t)} \approx \sum_{i=1}^{n} [g_i f_t(x_i) + \frac 12 h_i f_t^2 (x_i)] + \Omega (f_t) Obj(t)i=1n?[gi?ft?(xi?)+21?hi?ft2?(xi?)]+Ω(ft?)
    假設樹的結構已經確定,對目標函數進一步化簡:

    設每個葉子節點的權重為 wj,j∈1,2,...,Tw_j, j \in {1, 2, ..., T}wj?,j1,2,...,T ,那么可以將決策樹表示成 wq(x)w_{q(x)}wq(x)? ,即每個樣本會映射到第 q(x) 個葉子節點對應的權值。假設 Ij={i∣q(xi)=j}I_j = \{i|q(x_i) = j\}Ij?={iq(xi?)=j} 為第 j 個葉子節點的樣本集合,則目標函數可進一步化為:
    Obj(t)≈∑i=1n[gift(xi)+12hift2(xi)]+Ω(ft)=∑i=1n[giwq(xi)+12hiwq(xi)2]+γT+12λ∑j=1Twj2=∑j=1T[∑i∈Ijgiwj+12∑i∈Ijhiwj2+12λwj2]+γT=∑j=1T[(∑i∈Ijgi)wj+12(∑i∈Ijhi+λ)wj2]+γTObj^{(t)} \approx \sum_{i=1}^{n} [g_i f_t(x_i) + \frac 12 h_i f_t^2 (x_i)] + \Omega (f_t) \\ = \sum_{i=1}^n [g_i w_{q(x_i)} + \frac 12 h_i w_{q(x_i)}^2] + \gamma T + \frac12 \lambda \sum_{j=1}^T w_j^2 \\ = \sum_{j=1}^T [\sum_{i \in I_j} g_i w_j + \frac 12 \sum_{i \in I_j} h_i w_j^2 + \frac 12 \lambda w_j^2] + \gamma T \\ = \sum_{j=1}^T [(\sum_{i \in I_j} g_i) w_j + \frac 12 (\sum_{i \in I_j} h_i + \lambda) w_j^2] + \gamma T Obj(t)i=1n?[gi?ft?(xi?)+21?hi?ft2?(xi?)]+Ω(ft?)=i=1n?[gi?wq(xi?)?+21?hi?wq(xi?)2?]+γT+21?λj=1T?wj2?=j=1T?[iIj??gi?wj?+21?iIj??hi?wj2?+21?λwj2?]+γT=j=1T?[(iIj??gi?)wj?+21?(iIj??hi?+λ)wj2?]+γT
    我們之前樣本的集合,現在都改寫成葉子結點的集合,由于一個葉子結點有多個樣本存在,因此才有了 ∑i∈Ijgi\sum_{i \in I_j} g_iiIj??gi?∑i∈Ijhi\sum_{i \in I_j} h_iiIj??hi? 這兩項,把這兩項簡寫為 Gj,HjG_j, H_jGj?,Hj?,于是上式變成:
    Obj(t)=∑j=1T[Gjwj+12(Hj+λ)wj2]+γTObj^{(t)} = \sum_{j=1}^T [G_j w_j + \frac 12 (H_j + \lambda) w_j^2] + \gamma T Obj(t)=j=1T?[Gj?wj?+21?(Hj?+λ)wj2?]+γT
    假設樹的結構已經確定,通過最小化目標函數,求解葉子節點權重:

    在當前假設下,上式中只有 www 是變量,這是一個凸函數,為了使其取得最小值,只需要令目標函數一階導為 0,便可求得:
    w^j=?GjHj+λ\hat w_j = - \frac {G_j}{H_j + \lambda} w^j?=?Hj?+λGj??
    通過求得的葉子節點權重,計算目標函數值:
    Obj(t)=?12∑j=1TGj2Hj+λ+γTObj^{(t)} = - \frac 12 \sum_{j=1}^T \frac {G_j^2}{H_j + \lambda} + \gamma T Obj(t)=?21?j=1T?Hj?+λGj2??+γT

    學習的過程是怎么進行的?

    先從總體上進行描述:

  • 學習的過程就是每次擬合一棵樹,直到滿足停止條件
  • 擬合之前,先計算出每個樣本的一階導(前 t-1 棵樹預測值和真實標簽值的絕對差值)和二階導(固定值:2)
  • 用貪心策略生成一棵樹
  • 為每個葉子節點計算權值
  • 把新增的決策樹加入,這里有個學習率參數,實際上,在這里學習率的作用更多的是控制過擬合。
  • 生成一棵樹的具體過程是這樣的:

  • 從樹的深度為 0 開始,遍歷每個特征的每個分割點,尋找到目標函數增益最大的分割點
  • 針對每個特征,把屬于該節點的訓練樣本按特征值升序排列,通過線性掃描的方式來決定該特征的最佳分裂點,并記錄下該特征的最大收益(采用最佳分裂點的目標函數增益)
  • 選擇收益最大的特征作為分裂特征,該特征的最佳分裂點作為分裂位置
  • 如果收益大于 gamma,且滿足 min_child_weight,那么由該節點生長出兩個新的節點,每個新節點關聯對應的樣本集
  • 不斷重復以上兩個步驟,直到達到樹的最大深度or沒有滿足條件的分割點
  • 這其實是一種貪心策略,因為我們在分割的每一步都盡量使收益最大,即每一步都得到局部最優解,但無法保證一整棵樹的收益最大。

    本質是梯度提升樹,和 GBDT 有什么區別?

    我們說 GBDT,一般指的是基于 殘差(y-f(x)) 的梯度提升樹,實際上,如果以誤差的平方作為損失函數,那么殘差其實就是損失函數關于 f(x) 的負梯度,所以擬合殘差就相當于擬合了負梯度(這其實和神經網絡中通過梯度下降來訓練參數類似),這就是為什么稱之為梯度提升樹。

    xgboost 的在 GBDT 的基礎上主要改進了兩點,其實從 目標函數 中都可以看出來。

  • 對于 GBDT,相當于對目標函數中的 損失函數 這一項進行了 一階泰勒展開,而 XGBoost 用到了二階展開,更為精確一點;
  • xgboost 將葉子節點的權重的 L2 范數作為正則項,并直接添加到了目標函數中。
  • 都說 xgboost 效果好,為什么好?

    從偏差-方差的角度來理解:

  • 由于決策樹本身的靈活性,加上通過 Boosting 的方法,可以通過不斷地迭代學習降低偏差;
  • 除了直接在目標函數添加了正則項,還有很多其他措施來減小模型的方差:
  • 比如 subsample,在每一輪只使用一部分隨機采樣的樣本,通過這種隨機性來降低前后學習得到的基學習器的依賴(或者說相關性),其實就是在 Boosting 過程中摻入 Bagging 的思想,用以降低模型的方差。
  • colsample_bytree 也是類似,只不過這里隨機采樣的不是樣本,而是隨機選擇一部分特征進行訓練。
  • 訓練速度快,為什么快?

  • 特征間并行:在進行節點的分裂時,需要尋找每個特征的最佳分裂點及其分裂增益,最終選增益最大的那個特征去做分裂,那么不同特征的增益計算就可以并行計算。
  • 決策樹的學習最耗時的一個步驟之一就是對特征的值進行排序(因為要確定最佳分割點),xgboost 的做法是在訓練之前,預先對數據進行排序,然后保存為block結構,后面的迭代中重復地使用這個結構,大大減小計算量。這個block結構也使得并行成為了可能,在進行節點的分裂時,需要計算每個特征的增益,最終選增益最大的那個特征去做分裂,那么各個特征的增益計算就可以開多線程進行。
  • 近似直方圖算法。樹節點在進行分裂時,我們需要計算每個特征的每個分割點對應的增益,即用貪心法枚舉所有可能的分割點。當數據無法一次載入內存或者在分布式情況下,貪心算法效率就會變得很低,所以xgboost還提出了一種可并行的近似直方圖算法,用于高效地生成候選的分割點。
  • 另外,對于訓練數據特別稀疏的情況,稀疏感知的分位點尋找算法也能加速訓練。

  • 論文閱讀筆記

    2. 提升樹 TREE BOOSTING IN A NUTSHELL

    2.1 正則項 Regularized Learning Objective

    本節提出了目標函數。其中的正則化項可以防止過擬合。

    2.2 泰勒二階展開 Gradient Tree Boosting

    對目標函數二階泰勒展開。通過最小化目標函數,可以得到葉子節點的權值、以及目標函數值。

    分裂前后目標函數值的增益也很容易計算。

    2.3 學習率和特征采樣(Shrinkage and Column Subsampling)

    Shrinkage:

    類似于隨機梯度下降優化算法中的學習率,Shrinkage 具體做法是對每一輪生成的樹的葉子節點權重乘上一個系數 η\etaη (即希臘字母eta),這就是為什么 XGBoost 包中學習率參數名稱為 eta。

    Column Subsampling:

    和隨機森林里使用的特征采樣類似,這是一個 bagging 思想的應用,而且也是第一次被使用在 Tree Boosting 里。效果甚至比傳統的 row sub-sampling(樣本采樣)好。而且,特征采樣還能加速訓練。

    3. 分裂點尋找算法 SPLIT FINDING ALGORITHMS

    3.1 精確貪婪算法(Exact Greedy Algorithm)

    每一輪boost,生成一棵樹。由于枚舉所有可能的樹結構是NP-hard問題,不可能完成,所以實際做法是,在每次進行節點分裂的時候,以最大化分裂增益(loss reduction)的方式來進行節點的分裂。這是一種貪婪的策略。

    事先對訓練樣本按照特征值排序,可以加速訓練。

    每一層,對于某一個特征,基于特征列 Block 結構,并行進行所有葉子節點的分裂點尋找。并行的過程,我現在的理解是這樣的:

    對于某個線程,在順序遍歷某排好序的特征列時,對于每一個特征值,我們都能知道它對應的哪個樣本(記為第i個)、哪個葉子節點(記為第 j 個),也因此就能取得該樣本的梯度 gi,hig_i, h_igi?,hi?并根據 j 計算出 GjL,HjLG_{jL}, H_{jL}GjL?,HjL?GjR,HjRG_{jR}, H_{jR}GjR?,HjR?。遍歷一趟下來,所有葉子節點在該特征上的最大增益就都出來了。

    我之前卡在了這里:就是遍歷時,對于每一個特征值,都要計算一遍所有葉子節點的分裂增益,開銷應該很大。現在才搞懂,其實只需要計算該特征所在的葉子節點的分裂增益就可以了。這里說的“對于每一個特征值”,指的是每個分裂點前面緊挨著的那個特征值。

    你想,對于某個 leaf node ,你只記錄了該節點中包含了哪些樣本(索引),你怎么取得這個節點中這些樣本的該特征的排序值呢?反正我想了好久就是想不通有啥高效的辦法。在這里卡了好久。

    所以,其實相當于沒有遍歷葉子節點這一說,只是,在遍歷特征的所有分裂點的過程中,隱式地完成了對所有葉子節點的遍歷。這也是為什么 xgb 總是滿二叉樹。

    參考:XGBoost原理及并行實現 中的 “method 3” 部分。

    3.2 近似算法(Approximate Algorithm)

    當數據無法一起加載進內存,或者在分布式環境下,精確貪婪算法效率很低。即便正常情況下,有些連續值特征的取值個數可能非常多,這樣計算起來開銷很大,而且還容易過擬合。所以可以使用分桶的方式,把特征的取值分割成確定數量的部分。即,我們對每個特征都 propose 對應的候選分裂點們(由加權分位點算法生成,每次生成一系列候選分裂點稱作一次proposal),可用于每棵樹(global),或者每次分裂(local)。分桶后,需要匯總每個桶內的 gig_igi?hih_ihi? (難道這就是論文中的“construct approximate histograms of gradient statistics”?)。

    全局(global):在樹構建之前,確定所有特征的候選分裂點,然后在樹的所有層次 split finding 時都使用相同的proposals(即候選分裂點)。這種方法需要較少的proposal steps,但需要更多的候選分裂點(才能達到和local版本相同的效果),因為在每次分裂后,候選點們并沒有被提純。

    局部(local):re-propose after each split. 這樣的好處是,每次分裂后,樣本減少,純度更高,相當于對候選分裂點進行了提純(refine),所以需要的候選分裂點可以較少。潛在地,也更適合于構建深層的樹。

    XGBoost支持在單機環境下高效地使用精確貪婪算法,或者在任何環境下使用局部或全局的近似算法。

    3.3 加權分位點算法(weighted quantile sketch)

    以第 k 個特征為例,對于每一個樣本,由前面的 t-1 棵樹可以得到其二階導 h,以此作為該樣本的權重。n 個樣本的集合記為: Dk={(x1k,h1),(x2k,h2),...,(xnk,hn)}D_k = \{(x_{1k}, h_1), (x_{2k}, h_2), ..., (x_{nk}, h_n)\}Dk?={(x1k?,h1?),(x2k?,h2?),...,(xnk?,hn?)}

    對樣本按照特征值升序排列,那么對于一個值 z,可以得到樣本值小于 z 的樣本權重之和 占 所有樣本權重之和 的比例:
    rk(z)=1∑(x,h)∈Dkh?∑(x,h)∈Dk,x<zhr_k(z) = \dfrac 1{\sum_{(x,h) \in D_k} h} \cdot \sum_{(x,h)\in D_k, x < z} h rk?(z)=(x,h)Dk??h1??(x,h)Dk?,x<z?h
    我們的目標是從該特征的這些取值中找到候選分裂點 {sk1,sk2,...,skl}\{s_{k1}, s_{k2}, ..., s_{kl}\}{sk1?,sk2?,...,skl?} ,滿足:

    這里 ?\epsilon? 是一個近似系數。直覺上可知,大約有 1/?1 / \epsilon1/? 個候選分裂點。

    若使用均方誤差作為損失函數,那么實際上所有樣本的 h 值都為 2。對于所有樣本權重相等的情況,一個已知的分位點算法 quantile sketch 可以解決該問題。

    XGBoost支持對樣本設置權重,這樣一來樣本的二階導 h 也應當乘以相應的權重,這就導致每個樣本的權重可以各不相同。本文提出的加權分位點算法可以解決該問題。

    3.4 稀疏感知的分裂點尋找(Sparsity-aware Split Finding)

    數據稀疏可能由幾個原因造成:

    • 數據值缺失
    • 統計值經常為 0
    • 人為的特征工程(比如 one-hot)

    當樣本的某個數據值缺失時,該樣本會被分到默認的分支(獲得最大增益的方向)。

    具體的算法思路如下:

    對于每個特征:假設將缺失值分到右分支的情況下,遍歷所有特征值不缺失的特征值,尋找最佳分裂點再假設將缺失值分到左分支的情況下,遍歷所有特征值不缺失的特征值,尋找最佳分裂點得到增益最大的分裂點,同時,該最大增益是在哪種假設情況下得到的,哪種假設就作為缺失值的默認分支

    需要注意的是,該算法將 non-presence 視作缺失值處理,并按照學得的方向進行分支。

    我所理解的 non-presence 是類似于 one-hot 之后的 0 值,不知道對不對?

    作者在一個由于 one-hot 導致數據極其稀疏的數據集 Allstate-10K 上進行測試,該稀疏感知算法能比原始算法提升 50 倍的速度。

    所以,我的理解是,稀疏感知算法既有效處理了缺失值,又加速了訓練。

    4. 系統設計 SYSTEM DESIGN

    4.1 Column Block for Parallel Learning

    訓練樹的時候,最消耗時間的部分是,對數據進行排序。本文提出一種方法,將數據保存在內存單元里,保存的結構被稱為 block。

    每一個 block 存儲一列特征,在 block 中,特征值已經排好序,并且記錄了每個特征值對應的樣本索引(這樣可以節省大量的存儲空間)。block 的數據格式是 壓縮的列(CSC格式)。Block 中特征之所以記錄了指向樣本的索引,是為了能根據特征的值來取梯度。

    輸入數據的排序只在訓練開始前計算一次,之后每次迭代都可以復用。

    4.2 Cache-aware Access

    使用Block結構的一個缺點是取梯度的時候,是通過索引來獲取的,而這些梯度的獲取順序是按照特征的大小順序的。這將導致非連續的內存訪問,可能使得CPU cache緩存命中率低,從而影響算法效率。

    因此,對于exact greedy算法中, 使用緩存預取(cache-aware prefetching)。具體來說,對每個線程分配一個連續的buffer,讀取梯度信息并存入Buffer中(這樣就實現了非連續到連續的轉化),然后再統計梯度信息。

    對于大規模數據,效果十分明顯,大約快了一倍。

    在 approximate 算法中,對Block的大小進行了合理的設置。定義Block的大小為Block中最多的樣本數。設置合適的大小是很重要的,設置過大則容易導致命中率低,過小則容易導致并行化效率不高。經過實驗,發現2^16比較好。

    4.3 Blocks for Out-of-core Computation

    當數據量太大不能全部放入主內存的時候,為了使得out-of-core計算成為可能,將數據劃分為多個Block并存放在磁盤上。計算的時候,使用獨立的線程預先將Block放入主內存,因此可以在計算的同時讀取磁盤。

    但是由于磁盤IO速度太慢,通常跟不上計算的速度。因此,需要提升磁盤IO的吞吐量。Xgboost采用了2個策略:

    • Block壓縮(Block Compression):將Block按列壓縮(LZ4壓縮算法?),讀取的時候用另外的線程解壓。對于行索引,只保存第一個索引值,然后只保存該數據與第一個索引值之差(offset),一共用16個bits來保存
      offset,因此,一個block一般有2的16次方個樣本。

    • Block拆分(Block Sharding):將數據劃分到不同磁盤上,為每個磁盤分配一個預取(pre-fetcher)線程,并將數據提取到內存緩沖區中。然后,訓練線程交替地從每個緩沖區讀取數據。這有助于在多個磁盤可用時增加磁盤讀取的吞吐量。

    總結

    以上是生活随笔為你收集整理的【Datawhale|天池】心跳信号分类预测 (4) - 模型 之 XGBoost的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。