1. 程式人生 > >Kaggle比賽心得

Kaggle比賽心得

正文共5453個字,5張圖,預計閱讀時間14分鐘。

最近參加了兩場Kaggle比賽,收穫頗多,一直想寫篇文章總結一下。接觸Kaggle到現在不到一年,比賽成績一個銀牌(5%)一個銅牌(9%),勉強算入門了,跟大神們還有很大的距離。新學期準備找實習面試,整理一下專案經驗,於是動筆總結總結參加Kaggle比賽的個人心得體會和技巧。

先放一張成績圖和Kaggle個人主頁的連結(https://www.kaggle.com/yiyuanliu)

640?wx_fmt=png&wxfrom=5&wx_lazy=1

成績

我參加的這兩場比賽,一個是Zillow Prize:Zillow公司有一個房價預測演算法Zestimate,根據房產的特徵、歷史成交資料和Zestimate預測值之間的logerror(這裡有點繞),來預測實際成交價和Zestimate預測值之間的logerror。另一個是TensorFlow Speech Recoginition Challenge:識別長度為1秒的英文語音指令,並且分為12個類,包括10個指令(yes, no, up, down, left, right, on, off, stop, go)以及未知(unknown)和靜默(silence)。

這兩個比賽,剛好屬於Kaggle社群中兩個不同類別。Zillow Prize給定了60個房產的特徵,資料量不是特別大並且有明確的特徵,適合xgboost、lgb這樣的樹模型,對機器的要求不高。而語音識別這個比賽則相反,原始資料是wav檔案,實際上相當於對波形圖進行分類,不可能手動選特徵,因此這個比賽適用深度學習的各種模型。並且想要取得好成績,需要使用複雜的模型,CPU就不夠用了,需要一塊不錯的顯示卡(我用的是隊友的GTX 1070ti)。

兩場比賽下來,自己總結了一些kaggle比賽的基本流程:

  1. 特徵工程

  2. 模型選擇

  3. 調參

  4. 模型融合

特徵工程

特徵工程是Kaggle比賽的重中之重,尤其是對於房價預測這類使用樹模型的比賽。模型大同小異,基本是由GBDT模型演化而來,而且主要用XGBoost、LightGBM等幾種開源框架。所以,模型大家都差不多,特徵就是關鍵了。


每個比賽都有獨特的背景,想要發現甚至是自己創造出重要的特徵,往往需要專業的領域知識,比如Zillow這個比賽要預測美國的房價,原始特徵有臥室數量、面積,稅收等等。想要自己通過原始特徵組合,創造出一個“magic feature”就需要了解美國的房地產業。所以,選擇一個自己熟悉領域的比賽,會比較有優勢。


比賽背景千變萬化,從資料科學的角度,還有許多通用的方法來做特徵工程。這裡列舉一些這個比賽裡用到的方法:

1、基礎預處理:對category型別的資料OneHot編碼;數值型別的資料歸一化(但是這裡用到的大多數模型都是基於決策樹的,所以不需要)

2、缺失值處理:實際資料集中有許多資料是缺失的,考慮列出每個特徵的缺失比例,比例過大的直接捨棄,否則想辦法填充。這個比例沒有什麼定式,捨棄特徵會丟掉有用資訊,填充會引入噪聲,具體怎麼操作要看模型實際的表現。填充的話,基礎的是用均值、中位數等填充,更準確的方法是用演算法擬合,還可以直接把缺失視為一種特殊的值(這個比賽中的許多模型就是用-1填充)。

對於樹模型來說,資料缺失並不影響樹的生成,所以xgboost會在生成樹的同時,根據training loss自動學會將遇到缺失值時分裂到左子樹還是右子樹。作者Tianqi Chen的原話:

Internally, XGBoost will automatically learn what is the best direction to go when a value is missing. Equivalently, this can be viewed as automatically "learn" what is the best imputation value for missing values based on reduction on training loss.

3、outlier: 由於各種原因,往往有一些樣本的誤差特別大,把這些樣本加入模型會引入很大的噪聲,就像很多打分的比賽會去掉最高分和最低分之後再取平均值。這個比賽中去掉這樣大誤差的outlier能帶來很大的提升。

下圖是所有樣本的logerror值,可以看到絕大部分都在0附近,去掉兩端logerror急劇上升的樣本,能讓模型更穩定。

640?wx_fmt=png

outsider

3、相關性分析:特徵之間並不是完全獨立的,這時候可以計算correlation coefficient來確定特徵之間的兩兩關係。還可以計算每個特徵和目標值(這裡是logerror)之間的相關性,絕對值越大說明這個特徵的作用越大。

4、模型權重分析:現在大多數模型在訓練完成後都會給出獲取特徵權重的介面,這時的權重是直接反映了一個特徵在這個模型中的作用。這是判斷一個特徵是否有用的重要方法。例如,原始特徵有臥室數量和衛生間數量,我們自己創造了一個特徵房間總數(臥室數量+衛生間數量)。這時可以用這種方法判斷這個新特徵是否有效。

特徵工程在實際應用中非常有挑戰性,還有許多方法,上述只是一些皮毛。Zillow比賽裡我嘗試了許多新特徵,但最終都沒有采用。

而對於語音識別比賽來說,特徵工程就非常有限了。在語音識別領域廣泛使用的特徵是log-mel頻譜和mfcc特徵,沒有必要自己再做特徵工程。而現在火熱的端到端(end-to-end)語音識別優點就是省去特徵提取,直接使用原始波形作為神經網路的輸入。

模型選擇

Kaggle比賽很重要的一點是,不可能只使用一個單一模型。在許多比賽的第一名公佈的方案裡,往往有十幾個甚至幾十個不同的模型。模型融合(ensemble)實在是太重要了,模型融合的方法下文再講,但是在選擇模型的時候就要考慮到如何讓這些模型在融合後效果更好。

不管用什麼方法融合,想要模型融合之後效果好,模型之間要有多樣性。換句話說,模型之間越不相似,模型融合的效果越好。


對於Zillow這樣給定特徵,資料不是影象音訊的比賽,主要選用樹模型。這類Kaggle比賽,首選肯定是XGBoost和LightGBM。這兩個模型都是由梯度提升樹(GBDT)演化而來的。簡而言之,就是通過梯度提升(Gradient Boost)演算法訓練許多決策樹及其對應的權重,然後投票得到最終的結果。詳細的數學證明可以看林軒田老師的臺大機器學習技法課程


xgboost模型在生成決策樹時是level-wise的,即每一層上的所有節點都會一起分裂,通過max_depth來控制樹的高度從而控制模型的擬合程度。lightgbm模型則是leaf-wise的,每一次分裂會從所有葉子節點中找增益最大的節點來分裂,所以主要通過num-leaves來控制模型的擬合程度。


只用這兩個模型顯然不夠,可以調整不同的引數來獲得許多個側重點不同的xgboost(lgb)模型:不同的深度(葉子數)、不同的損失函式等等。另外,在這個比賽裡還用到了CatBoost、sklearn裡的一些模型:隨機森林、ExtraTree等。

對於語音識別這類用深度學習的比賽而言,模型選擇主要在於神經網路的結構和不同的輸入。首先可以嘗試不同種類的網路,比如CNN、LSTM。這裡很難說有什麼通用的技巧,在這個比賽中,CNN的效果較好,我用的所有6個模型都是以CNN為基礎的。主要用到的結構是VGGNet和SE-ResNet。

對於VGGNet,實際上並沒有完全按照論文上的模型,只是參考了思路,整個網路都使用了同樣大小的卷積核尺寸(33)和最大池化尺寸(22)。SE(Sequeeze-and-Excitation)Block是一個挺新的結構,在2017年提出,核心思想是學習特徵權重。主要是通過global average pool以及全連線層來學習feature map的權重,然後作為scale乘到原始feature map上。然後,如下圖所示,將SE Block和ResNet結合。

640?wx_fmt=png

SE-ResNet

在深度學習中,很多時候難以說清為什麼這個網路結構效果好,只能根據結果來證明。這次的語音識別比賽中,一個比較有用的trick是:為了增加模型的多樣性,在每個模型卷積操作完成後分別對feature map用全域性最大池化和全域性平均池化,相當於抓住了不同的特徵,把一個模型變成了兩個。另外,上文提到的三種特徵:原始波形、log-mel頻譜、mfcc特徵分別作為輸入,這樣就形成了六個模型。

640?wx_fmt=png

architecture

調參

調參這事很複雜,有很多經驗、方法,實際的比賽中往往還是需要一些玄學。調參最常用的方法就是GridSearch和RandomSearch。GridSearch是給定每個待調引數的幾個選擇,然後排列組合出所有可能性(就像網格一樣),做Cross Validation,然後挑選出最好的那組引數組合。RandomSerach很類似,只是不直接給定引數的有限個取值可能,而是給出一個引數分佈,從這個分佈中隨機取樣一定個數的取值。


調參的方法理解了,那具體調什麼引數呢?Zillow Prize比賽裡,主要用的模型是XGBoost和LightGBM。下面列出一些主要用到的引數,更多的還是直接看文件。

XGBoost:

  • booster: gblinear/gbtree 基分類器用線性分類器還是決策樹

  • max_depth: 樹最大深度

  • learning_rate:學習率

  • alpha:L1正則化係數

  • lambda:L2正則化係數

  • subsample: 訓練時使用樣本的比例

LightGBM:

  • num_leaves: 葉子節點的個數

  • max_depth:最大深度,控制分裂的深度

  • learning_rate: 學習率

  • objective: 損失函式(mse, huber loss, fair loss等)

  • min_data_in_leaf: 葉子節點必須包含的最少樣本數

  • feature_fraction: 訓練時使用feature的比例

  • bagging_fraction: 訓練時使用樣本的比例

調參的時候需要理解這些引數到底是什麼意思,如果過擬合了應該增大還是減小某個引數,這樣才能有目的而不是盲目地調參。當然,想要找到最佳的引數很多時候需要一些經驗和運氣。也不需要極致追求最佳引數,大多數情況下找到一組相對不錯的引數就可以了,往往還有別的方法來提升總成績。

Zillow Prize比賽中這些單個模型的訓練時間是基本上是分鐘級別的,這樣可以有足夠的時間來進行調參。而語音識別這個比賽裡的模型需要在GPU上訓練,一個模型要訓練幾個小時,其實沒有什麼時間來仔細的調參,更多的是靠經驗來估計。

值得一提的是,語音識別比賽中遇到一個問題,所有模型在訓練集和驗證集上表現都很好,但是在提交的測試集上有15%-20%左右的差距。最後發現是測試集和給出的訓練驗證集樣本分佈不同:這個比賽是12個類的分類問題,最終的驗證集上基本是均勻分佈的,而給出的訓練集和驗證集上,未知(unknown)類樣本明顯多於其他類,而靜默(silence)類則只有6個音訊。最終構建餵給神經網路的batch時,需要重新對訓練集取樣。

對於unknown和silence這兩個特殊類,他們的比例也可以算是超引數,最後根據Kaggle社群裡大神的分享,確定了10%是最佳的。

模型融合

模型融合在Kaggle比賽中非常重要,同時也是一個很大的話題。這裡只記錄一下我應用的兩種比較有效的方式。

1、Averaging

Averaging是最簡單粗暴也是最好理解的模型融合方式,而且效果還挺好的。實際上就是加權平均,小學生也會計算。雖然簡單,但是非常有效。如果模型的多樣性足夠,比如有的模型擅長從稅收角度預測房價,有的模型擅長從房間數量來預測房價,把這些模型平均後,取長補短,就能獲得一個更準確泛化能力更強的模型。

每個模型的權重怎麼算?一般是根據單個模型的表現好壞來決定,可以看測試集上的表現,Kaggle比賽裡可以看LB Score,但是也不能完全看Public LB,這樣就過擬合了。Zillow Prize比賽裡我們的Public LB排到了前2%,但是最終所有測試集公佈後還是回到了5%。

2、Stacking


Stacking應該是目前各類競賽中最好用的模型融合方法了。看下面這張流傳很廣的圖,其實Stacking並不難理解。

640?wx_fmt=png

Stacking

Stacking的核心思想是把第一層模型的結果作為第二層模型的特徵,然後訓練第二層模型得到最終結果。以5-fold stacking為例,將訓練集隨機分成5份,分別用其中4份作訓練,來預測剩下的1份,同時也預測所有的測試集。這樣,一個模型訓練了五次,對訓練集的預測拼起來,正好每一個訓練集的樣本都有一個預測值。對測試集的每個樣本,則有5個預測值,求平均值作為測試集的預測值。這樣,訓練集和測試集都有一個預測值,作為第二層模型的特徵。

另外,在語音識別比賽中還學到了一種類似Stacking的巧妙模型融合方法。CNN模型在所有卷積池化操作完成得到feature後,先不做全連線,把各個模型的feature全部拼接在一起,然後作為一個全連線神經網路的輸入,相當於stacking中的第二層模型。

總結

Kaggle比賽對於關注資料科學的人來說肯定不陌生,參加一次比賽可以在實踐中學習,遠勝於看書看視訊。初學者可以參考這篇文章,用經典的泰坦尼克號之災先練練手。很多知識只有實踐過才能真正理解。Kaggle社群非常活躍,有許多大神會分享自己的思路甚至是程式碼,一起討論一起學習會有巨大的進步。比賽成績很有用,但更重要的是通過比賽學到東西!

原文連結:https://www.jianshu.com/p/47282e2fc5d7

查閱更為簡潔方便的分類文章以及最新的課程、產品資訊,請移步至全新呈現的“LeadAI學院官網”:

www.leadai.org

請關注人工智慧LeadAI公眾號,檢視更多專業文章

640?wx_fmt=jpeg

大家都在看

640.png?