1 基本概念
- 集成學習的主要思路是先通過一定的規則生成多個學習器,再采用某種集成策略進行組合,最后綜合判斷輸出最終結果。一般而言,通常所說的集成學習中的多個學習器都是同質的"弱學習器"。基於該弱學習器,通過樣本集擾動、輸入特征擾動、輸出表示擾動、算法參數擾動等方式生成多個學習器,進行集成后獲得一個精度較好的"強學習器"。
- 目前集成學習算法大多源於bagging、boosting、stacking三種思想。
2 bagging
-
一種提高分類模型的方法。
- (1) 從訓練集\(S\)中有放回的隨機選取數據集\(M\)\((∣M∣ < ∣S∣)\);
- (2) 生成一個分類模型\(C\);
- (3) 重復以上步驟\(m\)次,得到\(m\)個分類模型\(C_1,C_2,...,C_m\);
- (4)對於分類問題,每一個模型投票決定,少數服從多數原則;
- (5)對於回歸問題,取平均值。
-
注意:這種抽樣的方式會導致有的樣本取不到,大約有\(\lim_{n \to \infty}(1-\frac{1}{n})^n\) = \(36.8%\)的樣本取不到,這部分可用來做測試集。
-
優點: 通過減少方差來提高預測結果。
-
缺點: 失去了模型的簡單性。
2.1 Random Forest
-
是一種基於樹模型的bagging算法改進的模型。假定數據集中有\(M\)個特征和 \(N\)個觀測值。每一個樹有放回的隨機抽出\(N\)個觀測值\(m\)(\(m=M\)或者\(m=logM\))個特征。把每一個單一決策樹的結果綜合起來。
-
優點:
- (1) 減少了模型方差,提高了預測准確性。
- (2) 不需要給樹做剪枝。
- (3) 在大規模數據集,尤其是特征較多的情況下,依然可以保持高效率。
- (4) 不用做特征選擇,並且可以給出特征變量重要性的排序估計。
-
缺點:
- (1) 隨機森林已經被證明在某些噪音較大的分類或回歸問題上會過擬合
- (2) 對於有不同取值的屬性的數據,取值划分較多的屬性會對隨機森林產生更大的影響,所以隨機森林在這種數據上產出的屬性權值是不可信的。
3 boosting
- 每一輪根據上一輪的分類結果動態調整每個樣本在分類器中的權重,訓練得到k個弱分類器,他們都有各自的權重,通過加權組合的方式得到最終的分類結果(綜合所有的基模型預測結果)。主要算法有AdaBoost/GBDT/Xgboost/LightGBM。
3.1 Adboost
- 給定數據集\(S\),它包含\(n\)個元組\((X_1,y_1),(X_2,y_2),...,(X_n,y_n)(X_1,y_1), (X_2,y_2), ..., (X_n,y_n)\),其中\(y_i\)是數據對象\(X_i\)的類標號。
- (1) 開始時,Adaboost對每個訓練元組賦予相等的權重\(1/n\)。組合分類器包含\(T\)個基本分類器。
- (2) 針對第\(t\)個分類器\(M_t\):
- 首先,從S中的元組進行抽樣,形成大小為\(n\)的訓練集\(S_t\),此處抽樣方式為有放回的抽樣,抽樣過程中,每個元組被選中的機會由它的權重決定;
- 然后,根據\(S_t\)導出(訓練出)分類器\(M_t\),使用\(S_t\)檢驗分類器\(M_t\)的分類誤差,並計算該分類器的“表決權”的權重;
- 最后,訓練元組的權重根據分類器\(M_t\)的分類情況調整。
- 如果元組被錯誤分類,則它的權重增加。
- 如果元組被正確分類,則它的權重減少。
- 元組的權重反映元組被分類的困難程度——權重越高,被錯誤分類的可能性越高。然后,使用這些權重,為下一輪分類器(下一個分類器)產生訓練樣本。
- 其基本的思想是,當建立分類器時,希望它更關注上一輪分類器(上一個分類器)錯誤分類的元組。整個分類過程中,某些分類器對某些“困難”元組的分類效果可能比其他分類器好。這樣,建立了一個互補的分類器系列。
- 用於二分類或多分類的應用場景。
- 優點
- (1) 很好的利用了弱分類器進行級聯。
- (2)可以將不同的分類算法作為弱分類器。
- (3)AdaBoost具有很高的精度。
- (4) 相對於bagging算法和Random Forest算法,AdaBoost充分考慮的每個分類器的權重。
- 缺點:
- (1) AdaBoost迭代次數也就是弱分類器數目不太好設定,可以使用交叉驗證來進行確定。
- (2) 數據不平衡導致分類精度下降。
- (3) 訓練比較耗時,每次重新選擇當前分類器最好切分點。
3.2 GBDT
-
采用決策樹作為弱分類器的Gradient Boosting算法被稱為GBDT,有時又被稱為MART(Multiple Additive Regression Tree)。GBDT中使用的決策樹通常為CART。
-
用一個很簡單的例子來解釋一下GBDT訓練的過程,如圖下圖所示。模型的任務是預測一個人的年齡,訓練集只有A、B、C、D 4個人,他們的年齡分別是14、16、24、26,特征包括了 "月購物金額"、"上網時長"、"上網歷史" 等。
-
下面開始訓練第一棵樹:
- 訓練的過程跟傳統決策樹相同,簡單起見,我們只進行一次分枝。訓練好第一棵樹后,求得每個樣本預測值與真實值之間的殘差。
- 可以看到,A、B、C、D的殘差分別是−1、1、−1、1。
- 這時我們就用每個樣本的殘差訓練下一棵樹,直到殘差收斂到某個閾值以下,或者樹的總數達到某個上限為止。
-
由於GBDT是利用殘差訓練的,在預測的過程中,我們也需要把所有樹的預測值加起來,得到最終的預測結果。
-
優點:
- (1)預測階段的計算速度快,樹與樹之間可並行化計算。
- (2)在分布稠密的數據集上,泛化能力和表達能力都很好,這使得GBDT在Kaggle的眾多競賽中,經常名列榜首。
- (3)采用決策樹作為弱分類器使得GBDT模型具有較好的解釋性和魯棒性,能夠自動發現特征間的高階關系,並且也不需要對數據進行特殊的預處理如歸一化等。
-
缺點:
- (1)GBDT在高維稀疏的數據集上,表現不如支持向量機或者神經網絡。
- (2)GBDT在處理文本分類特征問題上,相對其他模型的優勢不如它在處理數值特征時明顯。
- (3)訓練過程需要串行訓練,只能在決策樹內部采用一些局部並行的手段提高訓練速度。
3.3 Xgboost
- XGBoost是陳天奇等人開發的一個開源機器學習項目,高效地實現了GBDT算法並進行了算法和工程上的許多改進。
- 目標函數:
- 優點:
- (1)計算效率高,使用了二階導。
- (2)有正則化,減少過擬合。
- (3)列特征抽樣減少過擬合,同時有利於並行計算。
- 缺點:
- (1)每次迭代時都要遍歷整個數據集。
- (2)內存占用大。
3.4 GBDT與XGboost聯系與區別
- (1) GBDT是機器學習算法,XGBoost是該算法的工程實現。
- (2) 在使用CART作為基分類器時,XGBoost顯式地加入了正則項來控制模型的復雜度,有利於防止過擬合,從而提高模型的泛化能力。
- (3) GBDT在模型訓練時只使用了代價函數的一階導數信息,XGBoost對代價函數進行二階泰勒展開,可以同時使用一階和二階導數。
- (4) 傳統的GBDT采用CART作為基分類器,XGBoost支持多種類型的基分類器,比如線性分類器。
- (5) 傳統的GBDT在每輪迭代時使用全部的數據,XGBoost則采用了與隨機森林相似的策略,支持對數據進行采樣。
- (6) 傳統的GBDT沒有設計對缺失值進行處理,XGBoost能夠自動學習出缺失值的處理策略。
3.5 LightGBM
- LightGBM也是一種基於決策樹的梯度提升算法,相比XGboost有做了許多改進。
在樹分裂計算分裂特征的增益時,xgboost 采用了預排序的方法來處理節點分裂,這樣計算的分裂點比較精確。但是,也造成了很大的時間開銷。為了解決這個問題,Lightgbm 選擇了基於 histogram 的決策樹算法。相比於pre-sorted算法,histogram在內存消耗和計算代價上都有不少優勢。 - Histogram算法簡單來說,就是先對特征值進行裝箱處理,形成一個一個的bins。在Lightgbm中默認的#bins為256(1個字節的能表示的長度,可以設置)。具體如下:
- (1) 把連續的浮點特征值離散化成N個整數,構造一個寬度為N的直方圖;對於分類特征,則是每一種取值放入一個bin,且當取值的個數大於max_bin數時,會忽略那些很少出現的category值。
- (2) 遍歷數據時,根據離散化后的值作為索引在直方圖中累積統計量。
- (3) 一次遍歷后,直方圖累積了需要的統計量,然后根據直方圖的離散值,遍歷尋找最優的分割點。
- Level-wise 和 Leaf-wise
- 相對於xgboost的level—wise的生長策略,lightgbm使用了leaf-wise樹生長策略。由於level-wise在分裂時,部分增益小的樹也得到了增長,雖然容易控制誤差,但是分裂有時是不合理的,而lightgbm使用level-wise,只在增益大的樹上分裂生長,甚至對Feature f如果分裂無收益,那么后續也將不會對f計算。體現在參數上,xgboost使用max_depth,而lightgbm使用num_leaves控制過擬合。
- Level-wise過一次數據可以同時分裂同一層的葉子,容易進行多線程優化,也好控制模型復雜度,不容易過擬合。但實際上Level-wise是一種低效的算法,因為它不加區分的對待同一層的葉子,帶來了很多沒必要的開銷,因為實際上很多葉子的分裂增益較低,沒必要進行搜索和分裂。
- Leaf-wise則是一種更為高效的策略,每次從當前所有葉子中,找到分裂增益最大的一個葉子,然后分裂,如此循環。因此同Level-wise相比,在分裂次數相同的情況下,Leaf-wise可以降低更多的誤差,得到更好的精度。Leaf-wise的缺點是可能會長出比較深的決策樹,產生過擬合。因此LightGBM在Leaf-wise之上增加了一個最大深度的限制,在保證高效率的同時防止過擬合。
3.6 Xgboost與LightGBM對比
3.6.1 切分算法(切分點的選取)
- 占用的內存更低,只保存特征離散化后的值,而這個值一般用8位整型存儲就足夠了,內存消耗可以降低為原來的1/8。
- 降低了計算的代價:預排序算法每遍歷一個特征值就需要計算一次分裂的增益,而直方圖算法只需要計算k次(k可以認為是常數),時間復雜度從O(#data#feature)優化到O(k#features)。(相當於LightGBM犧牲了一部分切分的精確性來提高切分的效率,實際應用中效果還不錯)
- 空間消耗大,需要保存數據的特征值以及特征排序的結果(比如排序后的索引,為了后續快速計算分割點),需要消耗兩倍於訓練數據的內存
- 時間上也有較大開銷,遍歷每個分割點時都需要進行分裂增益的計算,消耗代價大
- 對cache優化不友好,在預排序后,特征對梯度的訪問是一種隨機訪問,並且不同的特征訪問的順序不一樣,無法對cache進行優化。同時,在每一層長樹的時候,需要隨機訪問一個行索引到葉子索引的數組,並且不同特征訪問的順序也不一樣,也會造成較大的cache miss。
- XGBoost使用的是pre-sorted算法(對所有特征都按照特征的數值進行預排序,基本思想是對所有特征都按照特征的數值進行預排序;然后在遍歷分割點的時候用O(#data)的代價找到一個特征上的最好分割點最后,找到一個特征的分割點后,將數據分裂成左右子節點。優點是能夠更精確的找到數據分隔點;但這種做法有以下缺點
- LightGBM使用的是histogram算法,基本思想是先把連續的浮點特征值離散化成k個整數,同時構造一個寬度為k的直方圖。在遍歷數據的時候,根據離散化后的值作為索引在直方圖中累積統計量,當遍歷一次數據后,直方圖累積了需要的統計量,然后根據直方圖的離散值,遍歷尋找最優的分割點;優點在於
3.6.2 決策樹生長策略
- XGBoost采用的是帶深度限制的level-wise生長策略,Level-wise過一次數據可以能夠同時分裂同一層的葉子,容易進行多線程優化,不容易過擬合;但不加區分的對待同一層的葉子,帶來了很多沒必要的開銷(因為實際上很多葉子的分裂增益較低,沒必要進行搜索和分裂)
- LightGBM采用leaf-wise生長策略,每次從當前所有葉子中找到分裂增益最大(一般也是數據量最大)的一個葉子,然后分裂,如此循環;但會生長出比較深的決策樹,產生過擬合(因此 LightGBM 在leaf-wise之上增加了一個最大深度的限制,在保證高效率的同時防止過擬合)。
- Histogram做差加速。一個容易觀察到的現象:一個葉子的直方圖可以由它的父親節點的直方圖與它兄弟的直方圖做差得到。通常構造直方圖,需要遍歷該葉子上的所有數據,但直方圖做差僅需遍歷直方圖的k個桶。利用這個方法,LightGBM可以在構造一個葉子的直方圖后,可以用非常微小的代價得到它兄弟葉子的直方圖,在速度上可以提升一倍。
- 直接支持類別特征:LightGBM優化了對類別特征的支持,可以直接輸入類別特征,不需要額外的0/1展開。並在決策樹算法上增加了類別特征的決策規則。
3.6.3 分布式訓練方法上(並行優化)
- 在特征並行算法中,通過在本地保存全部數據避免對數據切分結果的通信;
- 在數據並行中使用分散規約(Reducescatter)把直方圖合並的任務分攤到不同的機器,降低通信和計算,並利用直方圖做差,進一步減少了一半的通信量。基於投票的數據並行(ParallelVoting)則進一步優化數據並行中的通信代價,使通信代價變成常數級別。
- 特征並行的主要思想是在不同機器在不同的特征集合上分別尋找最優的分割點,然后在機器間同步最優的分割點。
- 數據並行則是讓不同的機器先在本地構造直方圖,然后進行全局的合並,最后在合並的直方圖上面尋找最優分割點。
- Cache命中率優化
- 基於直方圖的稀疏特征優化
- DART(Dropout + GBDT)
- GOSS(Gradient-based One-Side Sampling):一種新的Bagging(row subsample)方法,前若干輪(1.0f /gbdtconfig->learning_rate)不Bagging;之后Bagging時, 采樣一定比例g(梯度)大的樣本。
4 stacking
-
stacking的思想是將每個基模型的輸出組合起來作為一個特征向量,重新進行訓練。可以理解為:將訓練好的所有基模型對整個訓練集進行預測,第j個基模型對第i個訓練樣本的預測值將作為新的訓練集中第i個樣本的第j個特征值,最后基於新的訓練集進行訓練。同理,預測的過程也要先經過所有基模型的預測形成新的測試集,最后再對測試集進行預測。
-
具體算法如下(為方便理解我舉例說明):
- (1) 訓練集大小\(400\times10\),400個樣本,每個樣本10個特征,(如果算上target有11列)。測試集大小為\(120\times10\)。
- (2) 首先對訓練集4折划分:\(S_1\),\(S_2\),\(S_3\),\(S_4\),每個\(S_i\)的大小都收是\(100\times10\)。模型\(M_1\)第一次用\(S_1\),\(S_2\),\(S_3\)訓練,用\(S_4\)預測得到預測結果\(100\times1\)。重復訓練步驟,直到每一個\(S_i\)都有對應的預測結果\(100\times1\)。合並所有預測結果得到\(P_1\)\(400\times1\)。用\(M_1\)預測得到原始測試集的預測結果\(T_1\)\(120\times1\)。
- (3) 模型\(M_2\)用4折叫交叉得到訓練集的預測結果:\(P_2\)\(400\times1\);得到測試集的預測結果:\(T_2\)\(120\times1\)。
- (4) 模型\(M_3\)用4折叫交叉得到訓練集的預測結果:\(P_3\)\(400\times1\);得到測試集的預測結果:\(T_3\)\(120\times1\)。
- (5) 綜合(2)(3)(4)底層模型得到的訓練集的預測結果\(P_1\)、\(P_2\)、\(P_3\),得到上層模型的訓練集\(P_{train}\)\(400\times3\);得到上層模型的測試集\(T_{test}\)\(120\times3\)。
- (6) 用(5)得到的訓練集和測試集進行上層模型的訓練。
-
優點:學習了底層模型之間的關系
-
缺點:對於數據量要求比較大,因為要平衡第一層和第二層