機器學習比賽大殺器—-模型融合(stacking & blending)

  • 2019 年 10 月 29 日
  • 筆記

怎樣贏得機器學習比賽:你拿別人的結果和你自己的結果與做集成。

—— Vitaly Kuznetsov NIPS2014。

集成模型是一種能在各種的機器學習任務上提高準確率的強有力技術。在這篇文章中,我會分享我在Kaggle比賽中的集成方法。

在第一部分中,我們會討論從提交文件中建立集成。主要包括:

  • 投票集成
  • 平均
  • 排名平均

第二部分我們會討論 通過 generalization/blending等方法來創建集成。

我會在後續回答為什麼集成能夠減少泛化誤差。最後我會展示不同的集成方法,包括它們的結果以及程式碼以供你自己去嘗試。

對提交文件進行集成

最簡單方便的辦法就是對Kaggle提交的csv文件直接進行集成。你只需要模型在測試集上的預測結果,而不需要重新訓練一個模型。它簡單快速,只需使用已有模型的預測結果,是拼隊的理想選擇。

投票集成(預測結果為類別時)

我們先看一下簡單的投票集成方法。來看看為什麼集成模型能夠減少錯誤率,和為什麼它能在模型間相關度較低時能取得更好的結果。

糾錯碼

在航天任務中,所有的訊號都被正確的傳達是非常重要的。

如果我們有一個二進位字元串形式的訊號,如:

1110110011101111011111011011

如果訊號在傳輸過程中有一位發生了翻轉(第二位),變成了

1010110011101111011111011011

那這可能是致命的。

在糾錯碼中有一個編碼 解決方案。在最簡單的情況下,即糾錯碼是重複碼時:以同樣大小的數據塊多次傳遞訊號,並進行投票(以少數服從多數原則)。

Original signal:1110110011Encoded:10,3 101011001111101100111110110011Decoding:101011001111101100111110110011Majority vote:1110110011

訊號失真很少發生且通常在局部發生,因此,多次投票依然出錯的可能性就更小了。

只要訊號失真不是完全不可預測的(有50%的幾率發生),訊號就能被修復。

一個機器學習的例子

假設我們的測試集有10個樣本,正確的情況應該都是1:

1111111111

我們有3個正確率為70%的二分類器記為A,B,C。你可以將這些分類器視為偽隨機數產生器,以70%的概率產生」1」,30%的概率產生」0」。

下面我們會展示這些偽分類器通過投票集成的方法得到78%的正確率。

涉及到一點數學

我們看到有44%的概率投票可以校正大部分錯誤。大部分投票集成會使最終的準確率變成78%左右(0.3429 + 0.4409 = 0.7838)。

投票個數

跟重複碼相似,隨著編碼重複次數的增加對錯誤的校正能力也會增加,因此集成通常可以通過提高集成成員的個數來提升準確率。

同樣利用上面數學的數學公式:對5個有70%準確率的偽隨機分類器進行投票集成會得到83%的準確率。在大約66%的情況下投票可以校正1或2個錯誤編碼。(0.36015 + 0.3087)

相關性

在我第一次組隊參加2014年KDD杯比賽時,Marios Michailidis (KazAnova)提出了一些奇特的東西,他對我們所有的提交文件計算 皮爾遜相關係數,並且挑選出一些性能較好且相關係數較低的模型。

從這些挑選出來的文件中創建平均集成模型,給我們在排行榜上帶來了巨大的提升,50名的飛躍。不相關的預測結果的集成明顯比相關的集成結果要好,這是為什麼?

為了說明這一點,我們再舉3個簡單的模型。正確的情況仍然是全是1:

Kaggle案例:森林植被類型預測

當評價指標需要有力的預測時,比如多分類問題的準確率,少數服從多數投票法具有重要意義。

森林植被類型預測 比賽https://www.kaggle.com/c/forest-cover-type-prediction

使用 UCI Forest CoverType 數據集。這個數據集有54個屬性,6種分類類型。

https://archive.ics.uci.edu/ml/datasets/Covertype

我們建立一個有500棵樹的隨機森林模型作為 起始模型,然後我們再建立更多的模型,並挑選出最好的一個。在這個問題中,我們選擇的一個ExtraTreesClassifier 模型表現得最好。

加權

接下來,我們討論加權投票。為什麼要加權?通常我們希望模型越好,其權重就越高。所以,在這裡,我們將表現最好的模型的投票看作3票,其它的4個模型只看作1票。

原因是:當表現較差的模型需要否決表現最好的模型時,唯一的辦法是它們集體同意另一種選擇。我們期望這樣的集成能夠對表現最好的模型進行一些修正,帶來一些小的提高。

表一是5個模型訓練出來的結果,包括結果得分以及加權的得分。

Kaggle案例:CIFAR-10 影像檢測

CIFAR-10是另一個用準確率衡量的多分類kaggle比賽。

這個比賽中,我們隊的隊長Phil Culliton,從dr. Graham那複製了一個好的模型,並第一個發現最好的參數設置。

然後他對大約30個提交文件使用了投票集成的方法(所有的準確率得分在90%以上)。在集成模型中最好的單模型的得分為 0.93170.

對30個模型的投票集成得分為0.94120.大約降低了0.01錯誤率的,使得其識別結果超過人類 estimated human classification accuracy.

程式碼

我們有一個簡單的投票腳本

https://github.com/MLWave/Kaggle-Ensemble-Guide/tree/master/src

kaggle_vote.py

在 MLWave Github repo中找到. 它在kaggle的提交目錄中運行,並負責創建一個新的提交文件。更新:Armando Segnini 已經加上了加權部分的程式碼。

Ensembling.訓練10個神經網路並平均它們的預測結果,這是一個相當簡單的技術,卻有相當大的性能改進。 這裡可能會有疑惑:為什麼平均會有如此大的幫助?這有一個對於平均有效的簡單的原因。假設我們有2個錯誤率70%的分類器,當2者結果一樣時,那就是這個結果;當2者發生分歧時,那麼如果其中一個分類器總是正確的,那麼平均預測結果就會設置更多的權重在那個經常正確的答案上。 這個作用會特彆強,whenever the network is confident when it』s right and unconfident when it』s wrong.——Ilya Sutskever在深度學習的簡單概述中說道。

平均

平均可以很好的解決一系列問題(二分類與回歸問題)與指標(AUC,誤差平方或對數損失)。

與其說平均,不如說採用了多個個體模型預測值的平均。一個在Kaggle中經常聽到的詞是「bagging submissions」。

平均預測常常會降低過擬合。在類與類間,你想要理想的平滑的將其分離,而單一模型的預測在邊界間可能會有一些粗糙。

上面這幅圖片來自這個kaggle比賽:不要過擬合!圖中黑線比綠線有更好的分割,綠色線已經從數據點中學習了一些雜訊。但不用擔心,平均多個不同的綠線應該使我們更接近黑線。

記住,我們的目標不僅是去記住這些訓練數據(這裡有比在隨機森林裡更加有效的方法來存儲數據),而且還要去對我們沒有看到的數據進行良好的泛化。

Kaggle案例: Bag of Words Meets Bags of Popcorn

這是一個電影情感分析競賽,在以前的文章中,我們使用 在線感知機腳本

Online Learning Perceptron

得到了0.952的AUC.

這個感知機是一個線性分類器,在數據線性可分的情況下一定能找到一個分隔。這是一個受人喜歡的性質,但是你要意識到一旦達到這種分隔,分類器就會停止學習。它不一定會是新數據的最好的分隔。

那當我們隨機初始化5個感知機的權重,並通過平均來組合預測會發生什麼?結果是我們在測試集上的結果得到了提升,但這是為什麼呢?

以上結果還能說明,集成能(暫時)使您不必了解特定機器學習演算法的更精細的細節與內部工作原理。如果集成起作用,那很好,如果沒起作用,那並無大礙。

就算你平均10個相同的線性回歸的結果也沒事。Bagging一個糟糕的交叉驗證與過擬合的提交有可能會增加多樣性從而給你帶來一點提高。

程式碼

我們已經在Github上發布了一個 平均腳本,

https://github.com/MLWave/Kaggle-Ensemble-Guide/tree/master/src

kaggle_avg.py

它以.csv文件作為輸入並得到一個平均的提交結果。

更新:Dat Le已經添加了一個 幾何平均的腳本。

kaggle_geomean.py

幾何平均能比普通平均表現的更好。

排名平均

當平均多個來自不同模型的輸出時,會出現一些問題。並不是所有的預測器的結果是完美 校準的, 它們可能會產生過高或過低的預測概率,或者預測在一定的範圍里非常混亂。

在極端情況下,你可能會有一個這樣一個提交:

歷史排名

排名需要一個測試集,所以當你要預測一個新樣本時,你該怎麼辦?你可以與老的測試集一起,重新計算排名,但這會增加你的解決方案的複雜性。

一個解決方案是使用歷史排名。存儲舊的測試集預測及其排名,現在當你預測一個新的測試樣例如「0.35000110」,你去找到最接近的歷史預測並取其歷史排名(在這裡最接近的歷史預測是「0.35000111」其歷史排名為「3」)。

Kaggle使用案例:獲得有價值的顧客挑戰賽

排名平均在基於排名和基於閾值的指標(如AUC)和搜索引擎品質指標(如k平均精度)上表現良好。

這個 挑戰賽的目標 是對一個購物者成為一個重複顧客的概率進行排名。

https://www.kaggle.com/c/acquire-valued-shoppers-challenge

我們隊首先將多個Vowpal Wabbit中的模型與一個R語言的GLMNet模型進行取平均,然後我們使用排名平均來提高完全相同的集成的情況。

我已經在 Avito挑戰賽中寫過排名平均給了我們大幅的提升 。

finnally, when weighted rank averaging the bagged perceptrons from the previous chapter (1x) with the new bag-of-words tutorial (3x) on fastML.com we improve that model』s performance from 0.96328 AUC to 0.96461 AUC.

程式碼

排名平均腳本 已被添加到了MLWave Github repos上。

比賽是一種有效的方式,因為有無數的技術可以在建模問題上使用,但我們不能提前知道哪些將是最有效的。Anthony Goldbloom 在 Data Prediction Competitions — Far More than Just a Bit of Fun上說。

Stacked Generalization & Blending

對預測文件進行平均既簡單又好用,但這並不是頂級kaggle選手使用的唯一方法。stacking與blending也能讓你頗受收益。做好心理準備,接來下將要給你介紹屠龍技。

Netflix

Netdlix公司曾組織並普及了第一次數據科學比賽,在電影推薦挑戰賽中,參賽者們將集成發展成為了一門藝術,可能是太極端了以至於Netfilx公司決定不將獲勝方案應用到產品中。 因為這實施起來太複雜了。

不過,這個比賽湧現了很多論文與新穎的方法:

  • Feature-Weighted Linear Stacking
  • Combining Predictions for Accurate Recommender Systems
  • The BigChaos Solution to the Netflix Prize

這些論文都比較有趣且可以閱讀的,當你想要提高你在Kaggle比賽中的成績時,可以點進去閱讀一下。

這是我工作這麼多年以來,最令人印象深刻的集成和看到的最好的成果,它融合了上百個預測模型來得到最終結果。我們在線下使用了一些新方法重新評估了一番,但是我們測試認為該模型對準確率提升效果似乎並不值得將它引入到生產環境——-Netflix 的工程師說。

Stacked generalization

Wolpert在1992的論文中對stacked generalization進行了介紹,比Breiman的論文 「Bagging Predictors「早了2年。Wolpert的另一成名的機器學習理論是:「沒有免費午餐定理」

stacked generalization背後的基本思想是使用大量基分類器,然後使用另一種分類器來融合它們的預測,旨在降低泛化誤差。

下面來說下2折stacking:

  • 將訓練集分成2部分: train_a 與 train_b
  • 用train_a來擬合一個初級學習器對train_b進行預測
  • 用train_b來擬合約類型的學習器對train_a進行預測
  • 最後用整個訓練集擬合模型,並對測試集進行預測
  • 基於初級學習器的概率輸出,來訓練次級學習器 一個stacker模型通過使用第一階段的預測作為特徵,比相互獨立的訓練模型能夠得到更多的資訊。

我們通常希望在第0層泛化器是全類型的,而不僅僅是彼此的簡單變化(比如我們想要 surface-fitters, Turing-machine builders, statistical extrapolators等等.)這樣,所有可能學習到訓練集規律的方法都會被使用到, 這就是所謂的初級學習器應該「跨越空間」意思的一部分.

[…]stacked generalization是將非線性泛化器組合從而形成新的泛化器的手段,是為了嘗試最好的集成每個初級泛化器。每個學習器資訊越多(在其他學習器上沒有重複),stacked generalization的結果就越好

Wolpert (1992) Stacked Generalization

Blending

Blending 一詞是Netflix的獲勝者們引入的。它與stacked generalization非常像,但更簡單並且資訊泄露風險更小。一些研究者們交換著使用「stacked ensembling」與「blending」這2個詞。

通過Blinding,不需要對訓練集創建折外預測(out-of-fold predictions ),你只需創建一個小的留出集,比如10%的訓練集做為留出。stacker模型只在留出集裡面進行訓練。

Blending的優勢:

  • 比stacking更加簡單
  • 能夠防止資訊泄露:generalizers和stackers使用不同的數據
  • 你不需要跟你的隊友設定一個相同的隨機種子來進行相同的分折 誰都可以將模型放入「blender」中,由blender來決定是否保留這個模型。

缺點:

  • 只使用了整體中數據一部分
  • 最終的模型有可能對留出集過擬合
  • stacking使用交叉驗證比使用單一留出集更加穩健 (在更多的折上進行計算)。

至於性能,兩種技術的得到的結果差不多,取決於你的個人喜好以及你更傾向於哪種技能。就我自己而言,我更喜歡stacking。

如果你不能做選擇的話,你可以同時選擇這2種,使用stacked泛化器創建stacked集成和折外預測。然後使用留出集在第三層進一步結合這些stacked模型。

Stacking with logistic regression

使用邏輯斯諦回歸做融合是一個非常經典的stacking方法。我找到一個腳本很好的幫助我理解了這一方法。

當創建一個用於預測的測試集時,你可以一次性完成該操作,或者利用折外估計的模型(out-of-fold predictors)完成。當然為了減少模型和程式碼的複雜性,我更傾向於一次性完成。

kaggle案例:「Papirusy z Edhellond」

在這個比賽中,我使用上面的blend.py腳本,結合了8個模型(不同評價指標的ET RF GMB),然後使用邏輯斯諦回歸給了我第2名的成績。

Kaggle案例: KDD-cup 2014

使用這個腳本,我將Yan XU的AUC評分從0.605提高到了0.625。

Stacking with non-linear algorithms

目前流行用於Stacking的非線性演算法有GBM,KNN,NN,RF和ET。

非線性的Stacking在多分類任務中,使用原始特徵就能產生令人驚訝的提升。顯然,在第一階段中的預測提供了非常豐富的資訊並得到了最高的特徵重要性。非線性演算法有效地找到了原始特徵與元模型特徵之間的關係。

Kaggle案例: TUT Headpose Estimation Challenge

在TUT Headpose Estimation比賽中,可以當做是一個多分類,多標籤的問題。

對於每一個標籤,將分別訓練一個獨立的集成模型。

接下來的表格顯示了每個獨立模型的得分表現,以及當他們使用extremely randomized trees來做stacking時提高的得分。

我們看到使用了stack後,誤差減少了將近30%

有興趣的可以在Computer Vision for Head Pose Estimation: Review of a Competition看到這一結果的論文。

程式碼

你可以在 out-of-fold probability predictions的MLWave Github repo中找到一個函數去使用out-of-fold probability predictions。你也可以使用numpy horizontal stacking (hstack)去創建融合數據。

Feature weighted linear stacking

t線性加權stacking就是,先將提取後的特徵用各個模型進行預測,然後使用一個線性的模型去學習出哪個個模型對於某些樣本來說是最優的,通過將各個模型的預測結果加權求和完成。使用線性的演算法可以非常簡單快捷地去驗證你的模型,因為你可以清楚地看到每個模型所分配的權重。

Vowpal Wabbit對於線性加權stacking提出了一種創新性的用法。比如我們有以下訓練集,它有兩個特徵空間,一個是f,一個是s:

1 |f f_1:0.55 f_2:0.78 f_3:7.9 |s RF:0.95 ET:0.97 GBM:0.92

我們可以通過-q fs來構造二次方的特徵,它是 s-特徵空間f-特徵空間的交互項。在f-特徵空間中的特徵可以是原始的特徵,也可以是例子中的元特徵。

Quadratic linear stacking of models

這方法並沒有名字,所以我給他造了一個。這方法跟線性stacking非常像,但它在線性的基礎上,額外構造了一系列模型之間預測結果的組合。這一方法在許多次實驗中都對評分有很大的提高。最值得提到的是在DrivenData上的比賽: Modeling Women』s Healthcare Decision competition

我們同樣使用之前提到的VW訓練集:

1 |f f_1:0.55 f_2:0.78 f_3:7.9 |s RF:0.95 ET:0.97 GBM:0.92

我們可以使用-q ss 訓練從而創建出s-特徵空間中模型預測之間的二階特徵交互項(如RF*GBM)。

它與線性加權stacking可以非常簡單地結合起來,比如說先算f和s的交互項,再加上s和s的交互項:-q fs -q ss

So now you have a case where many base models should be created. You don』t know apriori which of these models are going to be helpful in the final meta model. In the case of two stage models, it is highly likely weak base models are preferred. So why tune these base models very much at all? Perhaps tuning here is just obtaining model diversity. But at the end of the day you don』t know which base models will be helpful. And the final stage will likely be linear (which requires no tuning, or perhaps a single parameter to give some sparsity). Mike KimTuning doesn』t matter. Why are you doing it?

Stacking 分類和回歸

Stacking可以允許你使用分類器來完成回歸問題,反之亦然。比如說,在一個二分類問題中,有人可能會嘗試使用線性分位回歸 來完成分類任務。一個好的stacker應該可以從預測中提取出你想要的資訊,儘管回歸通常並不是一個好的分類器。

而使用一個分類器做回歸就有點棘手。你先離散化:將y均勻地分為幾個的類別。那麼一個要求你預測工資的回歸問題就可以轉換為這樣的一個多分類的問題:

  • 所有低於20k的為類別1
  • 所有20k到40k之間的為類別2
  • 所有大於40k的為類別3

使用分類器預測出來的概率可以幫助回歸函數取得更好的預測效果。

Stacking無監督特徵學習

沒有任何人說過我們使用stacking的時候一定要是有監督的。事實上你可以使用stacking技術來處理無監督學習的問題。

k-means聚類是最為流行的無監督演算法。Sofia-ML實現了一個快速的在線k-means演算法適用於這裡。

其他有意思的方法是 t-SNE:通過把數據降維2到3維,然後將它放到非性融合器來融合。使用留出集的方法感覺上是最安全的選擇。可以看看由 Mike Kim提出的解決方案,他使用了t-SNE向量,然後結合了xgboost: 0.41599 via t-SNE meta-bagging

Piotr給出的 t-SNE在分類任務中的可視化表現

Online Stacking

我花了大量時間去研究一個叫online stacking的想法:首先從一個哈希二值映射中創建一個小型的隨機樹。如果樹預測正確則增加其收益,反之減少其收益。然後我們將收益最大的樹,和收益最小樹的預測作為特徵。

它確實有效,然而只限於人造的數據,它確實可以把異或問題(XOR-problem)學習出來。但是它沒有在任何真實數據集上成功過,相信我,我已經試過了。所以,從此之後,對於只使用人造數據去驗證它們的新演算法的論文,我都會持懷疑的態度。

一個相似的想法在一篇論文中是有效的: random bit regression。在這裡,從特徵中構造了多個隨機的線性函數,最好的函數是由很強的正則項中產生的。這個方法我曾經在一些數據集上成功過。這會是我將來發表的主題。

一個(半)online stacking更加具體的例子是廣告點擊預測問題。模型會在用戶近期行為的數據中預測更准,也就是當數據集具有時間效應的時候,你可以使用Vowpal Wabbit去訓練整個數據集,並使用一個更加複雜的工具比如說xgboost去訓練最後幾天的數據。你只需將xgboost的結果與樣本進行堆疊(stack),並讓Vowpal Wabbit盡其所能:優化損失函數。

The natural world is complex, so it figures that ensembling different models can capture more of this complexity. Ben Hamner 『Machine learning best practices we』ve learned from hundreds of competitions』 (video)

一切皆為超參數(hyper-parameter)

當我們使用stacking/blending/meta-modeling時,一個良好的想法就是所有的行為都是融合模型的參數。

比如說:

  • 不標準化數據
  • 使用z標準化
  • 使用0-1標準化

這些都是可以去調從而提高集成的效果。同樣的,使用多少個基模型的數量也是可以去調整優化的。特徵選擇(前70%)或數據填補(缺失填補)也是一系列的參數。

使用隨機網格搜索就是一個比較好的調參方法,它在調整這些參數的時候確實是有起到作用的。

模型選擇

你還可以通過組合多個集成模型來繼續優化你評分。

  • 這有一個特別的方法:使用平均,投票,或秩平均等方法來手動選擇表現好的集成模型。
  • 貪婪前向模型選擇 (Caruana et al.)。先使用一個或幾個好的模型作為基集成模型。然後不斷地增加使得評分提升最大的模型。當然你也可以在期間允許把模型放回去,這樣的話一個模型可能會被選擇很多次。
  • 使用遺傳演算法來做選擇,用交叉驗證得分作為適應度評分函數。可以看 inversion『s solution 的解決方案:『Strategy for top 25 position『.
  • 受Caruana的啟發,我使用一個完全隨機的方法:通過隨機選擇集成(無放回),創建一個100或其他個數的集成。然後選擇其中評分最高的模型。

自動化操作

當我在 Otto product classification比賽中,使用了stacking策略,我很快的得到了前十的成績。我通過不斷的添加越來越多的基分類器,和bagging多個stack集成我的分數得到不斷的提高。

當我達到了7個基模型,用了6個stacker,一陣恐懼和憂鬱的感覺向我襲來。我是否能夠把所有這些都重現?這些複雜而又笨重的模型讓我偏離了快速而又簡單的機器學習的初衷。

我在後續的比賽中,都將時間花在了建造一個自動化stacking的方法。我們去訓練那些具有純隨機參數的純隨機演算法的基模型。我們寫了一個與Scikit-learn的Api協同工作的封裝器去負責訓練分類模型VW, Sofia-ML, RGF, MLP and XGBoost。

並行自動stacker的草稿

使用自動化stacking可以讓你輕鬆的打敗那些對該問題設計特定演算法的領域專家,各個模型的訓練都是可以分散式和並行化的。

你也可以在這裡看到自動化融合的程式碼:MLWave Github repo: 「Hodor-autoML「.

在Otto product 分類比賽中,第1名和第2名融合了超過1000個不同的模型 可以在這裡看到更多: first place 和 second place。

我們為什麼要使用如此複雜的集成方法?

使用stacking,組合1000多個模型,計算幾十個小時這也太瘋狂了吧。這..確實是的。但是,這些怪物般的集成方法同樣有著它的用處:

  • 它可以使你贏得kaggle比賽
  • 它可以幫你打敗當前學術界性能最好的演算法
  • You can then compare your new-and-improved benchmark with the performance of a simpler, more production-friendly model
  • 總有一天,雖然現在的電腦和雲端還是很弱。你將做好準備
  • 我們有可能將集成的知識遷移到到簡單的分類器上(Hinton』s Dark Knowledge, Caruana』sModel Compression)
  • 不是所有基模型都要按時完成的。因為在集成方法中,即使損失一兩個模型也是可以接受的。
  • 自動化的大型集成策略可以通過添加正則項有效的對抗過擬合,而且並不需要太多的調參和特徵選擇。所以從原則上講,stacking非常適合於那些「懶人」
  • 這是目前提升機器學習效果最好的方法,或者說是最效率的方法human ensemble learning
  • 每1%精度的提升,或許就可以使得你的投資減少大量的損失。更嚴肅的說:在醫療行業中,每1%的提升,你就能多拯救幾個生命。

這一論文的程式碼在:https://github.com/MLWave/Kaggle-Ensemble-Guide上

https://blog.csdn.net/a358463121/article/details/53054686#t18

參考文獻鏈接


英文版本 http://mlwave.com/kaggle-ensembling-guide/

這個是上面英文翻譯過來的漢語翻譯版本 kaggle比賽集成指南 http://m.blog.csdn.net/article/details?id=53054686


搜狗比賽第五名的stacking思路 http://prozhuchen.com/2016/12/28/CCF%E5%A4%A7%E8%B5%9B%E6%90%9C%E7%8B%97%E7%94%A8%E6%88%B7%E7%94%BB%E5%83%8F%E6%80%BB%E7%BB%93/


kaggle官方部落格 stacking融合 http://blog.kaggle.com/2016/12/27/a-kagglers-guide-to-model-stacking-in-practice/

漢語版翻譯如下

Kaggler的「實踐中模型堆疊指南」


介紹 堆疊(也稱為元組合)是用於組合來自多個預測模型的資訊以生成新模型的模型組合技術。通常,堆疊模型(也稱為二級模型)因為它的平滑性和突出每個基本模型在其中執行得最好的能力,並且抹黑其執行不佳的每個基本模型,所以將優於每個單個模型。因此,當基本模型顯著不同時,堆疊是最有效的。關於在實踐中怎樣的堆疊是最常用的,這裡我提供一個簡單的例子和指導。

本教程最初發布在Ben的部落格GormAnalysis上。

https://github.com/ben519/MLPB/tree/master/Problems/Classify%20Dart%20Throwers

請隨意借鑒本文中使用的來自機器學習問題參考書的相關程式碼和數據集。


另外的python 版本的blending

https://github.com/emanuele/kaggle_pbr


動機 假設有四個人在板子上投了187個飛鏢。對於其中的150個飛鏢,我們可以看到每個是誰投擲的以及飛鏢落在了哪。而其餘的,我們只能看到飛鏢落在了哪裡。我們的任務就基於它們的著陸點來猜測誰投擲的每個未標記的飛鏢。

K最近鄰(基本模型1) 讓我們使用K最近鄰模型來嘗試解決這個分類問題。為了選擇K的最佳值,我們將使用5重交叉驗證結合網格搜索,其中K =(1,2,… 30)。在偽程式碼中: 1.將訓練數據分成五個大小相等的數據集。調用這些交叉測試。 2.對於K = 1,2,… 10 1.對於每個交叉測試 1.組合其他四個交叉用作訓練交叉 2.在訓練交叉上使用K最近鄰模型(使用K的當前值) 3.對交叉測試進行預測,並測量所得預測的準確率 2.從五個交叉測試預測中計算平均準確率 3.保持K值具有最好的平均CV準確率 使用我們的虛構數據,我們發現K = 1具有最佳的CV性能(67%的準確性)。使用K = 1,我們現在訓練整個訓練數據集的模型,並對測試數據集進行預測。 最終,這將給我們約70%的分類精度。

支援向量機(基本型2) 現在讓我們再次使用支援向量機解決這個問題。此外,我們將添加一個DistFromCenter功能,用於測量每個點距板中心的距離,以幫助使數據線性可分。 使用R的LiblineaR包,我們得到兩個超參數來調優: 類型 1.L2-正則化L2丟失支援向量分類(雙重) 2.L2正則化L2丟失支援向量分類(原始) 3.L2-正則化L1損失支援向量分類(雙重) 4.Crammer和Singer的支援向量分類 5.L1正則化L2丟失支援向量分類 成本 正則化常數的倒數 我們將測試的參數組合網格是5個列出的SVM類型的笛卡爾乘積,成本值為(.01,.1,10,100,1000,2000)。 那是


使用與我們的K最近鄰模型相同的CV +網格搜索方法,這裡我們找到最好的超參數為type = 4,cost = 1000。再次,我們使用這些參數訓練的模型,並對測試數據集進行預測。這將在測試數據集上給我們約61%的CV分類精度和78%的分類準確性。

堆疊(元組合)

讓我們來看看每個模型分為Bob,Sue,Mark或Kate的板區域。

不出所料,SVM在分類Bob的投擲和Sue的投擲方面做得很好,但是在分類Kate的投擲和Mark的投擲方面做得不好。對於最近鄰模型,情況正好相反。 提示:堆疊這些模型可能會卓有成效。 一共有幾個思考如何實現堆疊的派別。在我們的示例問題中我是根據自己的喜好來應用的: 1.將訓練數據分成五個交叉測試

2.創建一個名為「train_meta」的數據集,其具有與訓練數據集相同的行ID和交叉ID、空列M1和M2。 類似地,創建一個名為「test_meta」的數據集,其具有與測試數據集相同的行ID、空列M1和M2

3.對於每個交叉測試 {Fold1,Fold2,… Fold5} 3.1組合其他四個交叉用作訓練交叉

3.2對於每個基本模型 M1:K-最近鄰(k = 1) M2:支援向量機(type = 4,cost = 1000) 3.2.1將基本模型交叉訓練,並在交叉測試進行預測。 將這些預測存儲在train_meta中以用作堆疊模型的特徵 train_meta與M1和M2填補fold1

4.將每個基本模型擬合到完整訓練數據集,並對測試數據集進行預測。 將這些預測存儲在test_meta內

5.使用M1和M2作為特徵,將新模型S(即,堆疊模型)適配到train_meta,可選地,包括來自原始訓練數據集或特徵工程的其他特徵。 S:邏輯回歸(來自LiblineaR包,類型= 6,成本= 100)。 適配train_meta 6.使用堆疊模型S對test_meta進行最終預測 test_meta與堆疊模型預測

主要觀點是,我們使用基礎模型的預測作為堆疊模型的特徵(即元特徵)。 因此,堆疊模型能夠辨別哪個模型表現良好,哪個模型表現不佳。還要注意的是,train_meta的行i中的元特徵不依賴於行i中的目標值,因為它們是在使用基本模型擬合過程中排除target_i的資訊中產生的。

或者,我們可以在測試數據集適合每個交叉測試之後立即使用每個基本模型進行預測。 在我們的例子中,這將產生五個K-最近鄰模型和五個SVM模型的測試集預測。然後,我們將平均每個模型的預測以生成我們的M1和M2元特徵。 這樣做的一個好處是,它比第一種方法耗時少(因為我們不必在整個訓練數據集上重新訓練每個模型)。 它也有助於我們的訓練元特徵和測試元特徵遵循類似的分布。然而,測試元M1和M2在第一種方法中可能更準確,因為每個基礎模型在全訓練數據集上訓練(相對於訓練數據集的80%,在第二方法中為5次)。

堆棧模型超參數調優 那麼,如何調整堆疊模型的超參數? 關於基本模型,就像我們以前做的,我們可以使用交叉驗證+網格搜索調整他們的超參數。 我們使用什麼交叉並不重要,但使用我們用於堆疊的相同交叉通常很方便。調整堆疊模型的超參數是讓事情變得有趣的地方。在實踐中,大多數人(包括我自己)只需使用交叉驗證+網格搜索,使用相同的精確CV交叉用於生成元特徵。 這種方法有一個微妙的缺陷 – 你能找到它嗎?

事實上,在我們的堆疊CV過程中有一點點數據泄漏。 想想堆疊模型的第一輪交叉驗證。我們將模型S擬合為{fold2,fold3,fold4,fold5},對fold1進行預測並評估效果。但是{fold2,fold3,fold4,fold5}中的元功能取決於fold1中的目標值。因此,我們試圖預測的目標值本身就嵌入到我們用來擬合我們模型的特徵中。這是泄漏,在理論上S可以從元特徵推導出關於目標值的資訊,其方式將使其過擬合訓練數據,而不能很好地推廣到袋外樣本。 然而,你必須努力工作來想出一個這種泄漏足夠大、導致堆疊模型過度擬合的例子。 在實踐中,每個人都忽略了這個理論上的漏洞(坦白地說,我認為大多數人不知道它甚至存在!)

堆疊模型選擇和特性 你如何知道選擇何種型號作為堆疊器以及元特徵要包括哪些功能? 在我看來,這更像是一門藝術而不是一門科學。 你最好的辦法是嘗試不同的東西,熟悉什麼是有效的,什麼不是。另一個問題是,除了元特徵,你應該為堆疊模型包括什麼其他功能(如果有)?這也是一種藝術。看看我們的例子,很明顯,DistFromCenter在確定哪個模型將會很好地發揮作用。KNN似乎在分類投擲於中心附近的飛鏢上做得更好,SVM模型在分類遠離中心的飛鏢上表現得更好。 讓我們來看看使用邏輯回歸來堆疊我們的模型。 我們將使用基本模型預測作為元特徵,並使用DistFromCenter作為附加功能。

果然,堆疊模型的性能優於兩種基本模型 – 75%CV精度和86%測試精度。 就像我們對基本模型一樣,現在讓我們來看看它的覆蓋訓練數據的分類區域。

這裡的好處是,邏輯回歸堆疊模型捕獲每個基本模型的最好的方面,這就是為什麼它的執行優於任何孤立的基本模型。

實踐中的堆疊 為了包裝,讓我們來談談如何、何時、以及為什麼在現實世界中使用堆疊。 就個人而言,我大多在Kaggle的機器學習競賽中使用堆疊。一般來說,堆疊產生小的收益與大量增加的複雜性不值得為大多數企業使用。 但堆疊幾乎總是富有成果,所以它幾乎總是用於頂部Kaggle解決方案。 事實上,當你有一隊人試圖在一個模型上合作時,堆疊對Kaggle真的很有效。採用一組單獨的交叉,然後每個團隊成員使用那些交叉建立他們自己的模型。 然後每個模型可以使用單個堆疊腳本組合。這是極好的,因為它防止團隊成員踩在彼此的腳趾,尷尬地試圖將他們的想法拼接到相同的程式碼庫。

最後一位。 假設我們有具有(用戶,產品)對的數據集,並且我們想要預測用戶在購買給定產品的情況下,他/她與該產品一起展示廣告的幾率。一個有效的功能可能是,使用培訓數據,有多少百分比的產品廣告給用戶,而他實際上在過去就已經購買?因此,對於訓練數據中的樣本(user1,productA),我們要解決一個像UserPurchasePercentage這樣的功能,但是我們必須小心,不要在數據中引入泄漏。 我們按照接下來這樣做:

1.將訓練數據拆分成交叉 2.對於每個交叉測試 1.標識交叉測試中的唯一一組用戶 2.使用剩餘的交叉計算UserPurchasePercentage(每個用戶購買的廣告產品的百分比)

3.通過(fold id,用戶id)將UserPurchasePercentage映射回培訓數據 現在我們可以使用UserPurchasePercentage作為我們的梯度提升模型(或任何我們想要的模型)的一個特性。我們剛剛做的是有效地建立一個預測模型,基於user_i在過去購買的廣告產品的百分比,預測他將購買product_x的概率,並使用這些預測作為我們的真實模型的元特徵。這是一個微妙而有效並且我經常在實踐和Kaggle實現的有效的堆疊形式 – 。

https://blog.csdn.net/a358463121/article/details/53054686#t18

https://blog.csdn.net/u014356002/article/details/54376138