第一次參加Kaggle拿銀總結

轉自:第一次參加Kaggle拿銀總結python

做者:ScarletPangit

個人比賽代碼已經放到github --> Kaggle-Rental-Listing-Inquireiesgithub

在這篇博客開始以前,我必須感謝導師給我提供服務器資源,@Fenix Lin學長從他自身經驗出發耐心地爲我解答一些困惑,素未謀面的@Wille學長的一篇很是優秀的博文如何在Kaggle 首戰中進入前 10%幫助入門,以及廣大Kaggler的無私分享,我確實在Kaggle舉行的這場Rental Listing Inquiries比賽中收益良多,得到了很多知識。做爲第一次參加比賽,得到了Top 5%的成績已經讓我很是滿意了。算法

這篇文章的目的是介紹本身第一次參加Kaggle的心歷路程,總結遇到的問題和解決思路,爲本身之後參賽作準備。同時這篇文章也能夠做爲一個初學者的入門Kaggle的參考,若是想要在入門kaggle的時候拿到一個好的名次,能夠參考個人一些方法實踐。本文能夠隨意轉載,但務必註明出處和做者, 而且發郵件myscarlet@sina.com通知與我。json

初識Kaggle

什麼是Kaggle

從剛接觸machine learning的時候就有在學長口中、博文中、社區中聽到過它的名字,當初我對它的理解還比較浮淺,只是知道是一個數據比賽的平臺,有不少公開的數據集,好比大二寒假作的第一個ML練手項目就是一個用word2vec進行情感分析的Tutorial級比賽Bag of Words Meets Bags of Popcorn,而且寫了一個Research report。這過程當中只用到了教程和數據集。數組

後來從新接觸Kaggle才發現,它的價值所在是各類高質量的比賽,以及每場比賽下面的社區討論(包括比賽中的分享、答疑,和比賽後的top solution分享),所以若是想要得到關於數據挖掘,機器學習實戰經驗的話,打一場kaggle比賽絕對是一個高回報的工做。服務器

由於仍是學生,不知道kaggle比賽到底是否會爲本身求職工做有舉足輕重的影響,可是單從Kaggle被google收購一點來看,它會在行業內一點點提高影響力的。app

比賽組織

一場比賽一般持續2~3個月,在比賽的簡介中會有規則、評價指標(好比這場比賽爲mlogloss),時間軸等信息。另外還有數據區、Kernel區(一些Kagglers在kaggle上成功運行的ipython notebook或者代碼),Discussion(討論區),LeaderBoard(LB,分爲公開的用戶提交能夠顯示結果的榜單,和非公開的比賽結束後肯定最終排名的榜單),固然還有提交區(通常爲必定格式的csv文件提交)。dom

另外就是獎牌問題,通常來說在1000+量級的比賽中,top 10+ 0.2%爲金牌,5%爲銀牌,10%爲銅牌,這裏有更具體的獎牌發放方式。機器學習

討論區

我的認爲,若是想在入門Kaggle階段就得到一個好的成績的話,關注discussion是很是重要的,會有不少人分享本身的思路、困惑甚至代碼和結果。有時候,一場比賽中比較關鍵的feature可能就是從討論區中得到的,好比Two Sigma Connect: Rental Listing Inquiries這場比賽的最後幾天,我覺得本身特徵提取得已經差很少了,沒有任何idea了的時候,一個來自討論區magic feature從天而降,從而使得榜單大變,一晚上之間個人排名從70多掉到了120多。

數據探索和可視化(EDA)

首先拿到一個比賽題目,你須要下決心是否參加這個比賽,對我我的而言最重要的無非兩點 1. 是否是有rank point,也就是獎牌, 2. 數據集是否令我滿意。 所以對數據的探索首先須要你從Kaggle網站上查看數據的簡介,並把數據下載下來。好比Rental Listing Inquiries包含了80G的圖片數據,和幾份json文件。

咱們將下載下來的train.csv用python pandas 打開,取少許樣本進行觀測

 

 

1

import pandas as pd

2

train = pd.read_json("input/train.json")

3

train.sample(2)

拋開圖片數據不談,咱們能夠看到給定的數據裏包含多種多樣的feature:

  • 數值型feature

    • bathrooms
    • bedrooms
    • price
  • 高勢集類別(High Categorical)型feature

    • building_id
    • display_address
    • manager_id
    • street_address
  • 時間型feature

    • created
    • 地理位置型feature
    • longitude
    • latitude
  • 文本feature

    • description
  • 稀疏特徵集feature

    • features
  • id型feature

    • listing_id
    • index

咱們看到有這麼多不一樣的feature,一看幾乎每一個feature都有深度挖掘的價值,況且還有80G的圖片feature,無疑是讓人興奮的,所以我選擇了這個比賽,由於它的數據集的確讓我舒心。

另一定要搞明白的一件事是這場比賽是一個預測比賽仍是分類比賽,咱們能看到最重要預測的是用戶的interest_level,分爲low,medium,high三級,很顯然是個分類問題了。

接下來的是就是對數據進行可視化探索了,我由於是初期參賽的,因此本身作了一份可視化方案,從中能夠發現不少有趣的分佈、outlier等。在這裏推薦三份在比賽中分享出來的比較好的EDA:

提取基礎特徵+模型訓練

有了以前數據探索的基礎,咱們很快能提取到一些基礎的feature,好比數值型feature進行簡單的加減乘除,類別型feature用id順序編碼,稀疏特徵集用one-hot編碼,時間特徵生成年、月、日等。將一些基礎的特徵轉換成相應的輸入input_X矩陣後,再將label也轉換成數值形式:

 

 

1

target_num_map = {'high':0, 'medium':1, 'low':2}

2

3

y = data["interest_level"].apply(lambda x: target_num_map[x])

懂機器學習的人都知道,有了這些(X,y)對,咱們就能夠進行模型訓練了。

咱們用cross-validation(CV)的成績來判斷咱們本地的實驗結果,也就是將(X,y)訓練集拆分紅訓練和驗證集,訓練相應分類器對訓練集擬合,再在驗證集上進行loss的計算來評估模型的好壞。

常見的分類器有Logistic Classifier,SVM, NN softmax,Random Forest等。可是在kaggle上用的比較多的仍是一些封裝好的庫,如sklearn裏的各類分類器,大名鼎鼎的xgboost,最近嶄露頭角的lightgbm等。

早就聽聞xgboost的好用,我就直接在電腦上pip了xgboost,做爲我接下來一兩個月以來的核心分類器。將原先的(X,y)對中的訓練部分輸入xgboost進行fit,而後用驗證部分predict計算mlogloss。

至此爲止,比賽初期的第一個模型就已經訓練好了。

跑出一個能提交的結果

訓練完一個比較好的模型以後,就能夠對測試集進行預測了,首先將訓練集(X,y)對輸入xgboost中從新訓練,而後對測試集也像對訓練集同樣進行特徵處理,預測出來的結果按照比賽指定的格式保存到文件(在這裏仍是建議用pandas),便可提交。

第一次提交意味着你正式進入比賽,提交的結果會在Leader Board上顯示你當前的排名,固然這個排名只起到參考做用,由於你提交上去的大部分結果kaggle都沒有進行評估。

特徵工程(FE)

在一系列的初始操做之後,你就要踏上FE的漫漫長征了。本人斷斷續續在數據清洗、特徵提取上作了約兩個多月,在比賽最後一段時間模型融合完畢後還在繼續地尋找、測試新的特徵。後期評論區中magic feature的出現,讓每一個人的預測結果好了0.01~0.02個點。不得不說,特徵工程纔是Kaggle比賽獲勝的關鍵所在,所以初學者耗費大量精力在這上面是沒錯的。而本博文也是重點想講一下本身發現新特徵的一些心歷路程。

在對一些基礎的特徵進行生成以後,我開始了漫長地測試特徵的長征路,測試的思路我後來發現並非很好,由於是經過新增長一個或幾個feature,若是cv分數上去了,就增長這個feature,若是cv分數沒有上去,就捨棄這個feature,也就是至關於貪心驗證。這樣作的弊處在於,若是以前被捨棄的feature和以後被捨棄的feature聯合在一塊兒纔會有正面影響,就至關於你錯過了兩個比較好的feature。所以特徵的選擇和聯合顯得很是關鍵。

在比賽階段,花費大量力氣去建立一個feature,到頭來卻選擇放棄這個feature的事情很常見,我後期的特徵有不少是新添加的,舊有的一些特徵並無保留。接下來就讓我總結一下這場比賽中有哪些「好」的feature,爲之後的比賽提供靈感和經驗。

  • 數值型feature的簡單加減乘除

這個乍一看彷彿沒有道理可言,可是事實上卻能挖掘出幾個feature之間的內在聯繫,好比這場比賽中提供了bathrooms和bedrooms的數量,以及價格price,合租用戶可能會更關心每一個臥室的價格,即bathrooms / price,也會關心是否是每一個房間都會有一個衛生間bathrooms / price ,這些數值型feature之間經過算數的手段創建了聯繫,從而挖掘出了feature內部的一些價值,分數也就相應地上去了。

  • 高勢集類別(High Categorical)進行經驗貝葉斯轉換成數值feature

什麼是High Categorical的特徵呢?一個簡單的例子就是郵編,有100個城市就會有好幾百個郵編,有些房子坐落在同一個郵編下面。很顯然隨着郵編的數量增多,若是用簡單的one-hot編碼顯然效果不太好,所以有人就用一些統計學思想(經驗貝葉斯)將這些類別數據進行一個map,獲得的結果是數值數據。在這場比賽中有人分享了一篇paper裏面就提到了具體的算法。詳細就不仔細講了,用了這個encoding以後,的確效果提高了不少。那麼這場比賽中哪些數據能夠進行這樣的encoding呢,只要知足下面幾點:1. 會重複,2. 根據相同的值分組會分出超過必定數量(好比100)的組。也就是說building_id, manager_id, street_address, display_address都能進行這樣的encoding,而取捨就由最後的實驗來決定了。

  • 時間特徵

針對於時間數據來說,提取年、月、日、星期等可能仍是不夠的,有另一些points能夠去思考,用戶的興趣跟發佈時間的久遠是否有關係?能夠構造以下的feature來進行測試:

 

 

1

data["latest"] = (data["created"]- data["created"].min())

2

3

data["passed"] = (data["created"].max()- data["created"])

能夠看到latest指的是從有數據開始到該房建立爲止一共過去了多少時間,而passed則是該房記錄建立爲止到最後有記錄的時候一共過去了多少時間。

另外針對於時間特徵還能夠用可視化的方式來與其餘特徵創建聯繫,好比咱們觀察listing_id與時間變化到底有怎樣的聯繫,可以繪製出以下的圖來:

可能簡單的相除就能得到很好的結果

  • 地理位置特徵

想到地理位置,就會想到聚類,一個簡單的方式將每一個房子劃分到同一塊區域中去;除了聚類之外,算出幾個中心點座標,計算曼哈頓距離或者歐式距離可能都會有神奇的效果。

  • 文本特徵

實話說本身是看中此次比賽中有文本數據才參加的,所以在文本挖掘中作了很大的努力,好比提取關鍵詞、情感分析、word embedding聚類之類都嘗試過,但效果都不是很好, 對於文本的特徵的建議仍是去找出一些除了停用詞之外的高頻詞彙,尋找與這個房屋分類問題的具體聯繫。

  • 圖片特徵

除了最後爆料出來的magic feature(後文會提到)之外,我只用了一個房子有幾個照片這個信息。討論區中都說對於圖片特徵用CNN提取、簡單特徵提取之類的效果都不是很好。

  • 稀疏特徵集

其實就至關於一系列標籤,不一樣標籤的個數也是挺多的,本次比賽我只是簡單地採用了counterEncoding的方式進行one-hot編碼。值得一提的是,有些標籤是能夠合併的,好比cat allowed 和 dog allowed能夠合併成爲 pet allowed,我在這場比賽中手工地合併了一些feature數據,最終結果略微有所提高。

  • 特徵重要程度(feature importance)

在樹結構的分類器好比randomforest、xgboost中最後可以對每一個特徵在分類上面的重要程度進行一個評估。這時候若是已經選定了一些feature進行訓練了以後,查看feature importance的反饋是很是重要的,好比本場比賽制勝的關鍵是運用manager_id這個feature,而它的feature importance反饋結果也是很是高。經過對重要特徵的從新再提取特徵,可以發現不少有意思的新特徵,這纔是用FE打好一場比賽的關鍵所在。

下面列出了一些比賽結束後獲勝者分享的idea,這大概是我這場比賽中獲益最大的一塊地方了。

  • Top #1 solution @plantsgo

主要是針對manager_id生成了很是多的feature。如根據不一樣時間出現的manager_id判斷一個manager是否活躍(manager與time進行group,manager掌管有幾個不一樣的房子(manager與building_id進行group)、平均天天處理多少房子(比值)、活動範圍(同個manager掌管的房子的最大最小經緯度group),經理的開價程度(選擇bedroom和bathroom做爲房子型號指標,把相同房型的均價來衡量經理對於全部房子的開價程度),對經緯度進行聚類再計算每一個區域中有多少個manager競爭、一個manager同時經營幾個區域、在同個區域中manager的開價水平等。從Top 1選手分享的代碼來看,其對於manager的各類處理的確是讓人大開眼界。

從更爲經驗老道的選手給出了一些特徵提取建議。其中有一類被做者稱爲"Likelihood Features",他對High Cardinal Categorical的特徵用了一些額外的條件機率來計算其似然值,如p(y|manager_id, bathrooms)等,而且進行了點積操做來計算出一個合適的encoding值(相似於先前討論區中出現的manager_skills,同時爲了防止過擬合對這些似然估計出來的feature建立了2層嵌套。另外還有一種對我啓發比較大的feature是對description出現頻率最高的15k單詞進行一個one-hot深度xgboost訓練,將這個訓練出來模型的預測結果做爲description的encoding。

  • Top #3 solution @Little Boat

其FE的第一部分給出了group的一套方案,相似於我本身FE中的group方法。第二部分使用了magic feature相關的feature,方法與第一部分相似

 

  • Top #9 solution @James Trotman

沒有細說,可是列出了一個feature name的詳單,但願之後沒有idea的時候能從中找到一些insight

  • Top #11 solution @KazAnova

KazAnova無疑是這場比賽中的明星選手,他分享了對初學者模型融合比較關鍵的Stack-Net,以及對最後榜單變更起到決定性做用的magic feature。幾乎全部在榜上的Kagglers都要向他致敬。同時在FE這一塊,他注意到了數據集中存在不少相似的數據(僅僅在價格上有區別),所以他創建了不一樣的group,並在這些group間建立了不少aggregated features,好比最高的price,平均price等

  • Top #12 solution @b.e.s

用到了基於高勢集類別數據的group的一些統計量。

  • Top #13 solution @qianqian

也是用了不少基於manager_id group的統計feature。

模型調參(Grid Search)

模型調參的話,可以在FE完以後爲你提高0.001~0.002分數,所以如何爲咱們的分類器,好比xgboost選擇好正確的參數是很是關鍵的。

比較經常使用的是進行Grid Search,從你的輸入組合中暴力地搜索cv結果最優的組合。我通常會設定一個learning rate,而後嘗試不一樣的參數組合,取最優值,由於訓search的代價比較高,最好選擇必定範圍,好比你事先cv的時候知道estimater會在700~1000的範圍內,那就不要search這個範圍之外的值了。

模型融合

若是你沒有idea了的話,就模型融合吧!模型融合是可以快速提升比賽成績的捷徑,如今的比賽幾乎沒有人不用到這個技巧,一般獲勝者會對不少不少模型進行融合,而且會選擇不一樣的模型融合的方式。這裏有一篇很是好的模型融合解析博文,相信每一個看過它的人都會對模型融合有一個清楚的瞭解

本次比賽中我使用了兩種模型融合方式,一種是Averaging,一種是Stacking。

先來講說Stacking,由於這場比賽一名貢獻比較大的選手分享了一個叫StackNet的庫,做爲新手我就直接用了。首先我用個人xgboost cv集交叉預測出結果做爲feature的一部分放到train data中,再對test data進行預測的結果做爲feature的一部分放到test data中,再在第二層上選擇了Logistic Classifer,GradientBoostingClassifer,AdaBoostClassifer,NNSoft-maxClassfier,RandomForestClassifer等進行交叉預測,第三層選取了一個randomForest做爲最後的結果訓練和預測。Stacking主要增多了模型的diversity,使個人成績上升了至少0.003的量級。

而後是Averaging,以前提到過Stacking須要交叉預測,我就選取了10組隨機種子分別對訓練集進行10-kfold交叉預測取平均,以及每一個flod訓練預測的時候我都對個人xgboost選取5個隨機種子取平均。也就是說,在第一層Stacking的CV集交叉預測時我總共訓練了500個模型進行平均。分數的提高大約在0.002左右。

直到比賽結束看了排名靠前的選手的模型融合後,才發現本身對於模型融合只是作了一點微小的工做,提高空間還很是大。詳情能夠看FE部分分享的solution連接。

Tricks

在這場比賽中有一名在一開始的兩個月一直遙遙領先的選手爆出這個比賽有個magic feature,你們陷入了瘋狂找這個feature的過程當中,直到那位分享了StackNet的選手分享出了這個magic feature:80G圖片數據每一個文件夾的建立時間,因而榜單大變,我一覺醒來後發現本身掉了不少就發現到了不對勁,便迅速加入到這個magic feature瘋狂屠榜的大軍中,從這裏能夠看見,一個信息量巨大的feature若是被發現的話,對比賽成績會帶來多麼大的影響。

有一些group的feature可以起到很是重要的做用,詳細見我比賽後發表的一個小樣例discussion topic。可是必定要防止過擬合。

總結

這篇博文還有一些關鍵的點沒有涉及到,好比數據的清洗,有些數據在記錄中彷佛是不一樣的,可是意思是同樣的,就應該歸位同一個類別,還有就是清除一些outlier等。

對這個比賽的top solution總結得仍是沒到位,基本沒有coding實現他們的idea過。因爲課程壓力比較大,等到時候空了的時候再好好整理。

另外還有就是須要鍥而不捨地打這個比賽,由於你覺得你idea都沒有了,模型調參、融合完畢了的時候,可能你們都找出了另外一個"magic feature",輕鬆地把你擠出獎牌的範圍內了。

最後,Kaggle is fun!

相關文章
相關標籤/搜索