2019國泰大數據競賽前8% 建模與賽後分享

已經結束的比賽看板畫面

今年10月初,我參加了2019年的國泰大數據競賽,在最後取得了8%(19/244)的成績,因為這是自己第一次參加國內的資料科學競賽(一年多以來都只在Kaggle上玩耍XD),也跟個人規劃有關吧?總之就是大三了會多打一點個人賽,畢竟整個大二幾乎都在忙商業競賽,該來平衡一下!

最好的成績是進到16th

後來稍微再看了一下國內的資料科學相關競賽,發現其實還真的挺多,大大小小的比賽都有,這次我參加的是 AI實戰吧 平台與國泰人壽、國立政治大學統計系主辦、趨勢科技贊助的比賽,如果對比賽也有興趣的人,我覺得工研院這部分做得蠻用心的,這裡有一個收集賽事的網站:工研院AIdea人工智慧共創平台 ,裡面彙整了一些近期的比賽,也有AI產學合作的案例可以看,推薦給想關注資料科學在臺灣本土應用的人:)

至於整篇文章的架構如下:

  • 關於比賽
  • 這場比賽的Trick
  • 關於建模,我做了哪些事情
  • 賽後心得

另外同期其實還有玉山人工智慧挑戰賽、SAS舉辦的比賽等等……..賽事環境其實蠻好的!

那麼正文開始。

關於比賽

題目如下,此為競賽網站說明的文字:

在保險業中,每個王牌業務員都有自己的一套銷售手法與良好的客戶關係經營。透過了解客戶需求,為客戶保單健檢,最後客制化出客戶想要保單組合,一步一步都是透過經驗的累積,才能夠行雲流水地成功推銷公司的保單。那麼客戶會願意購買保單,是業務員靠銷售手法創造出來的,還是客戶本身保險需求被挖掘出來的呢?事實上一次成功的保單交易,兩者缺一不可。

本次比賽的主要目的就是:「以現今機器學習的技術,挖掘出保險需求可能較高的客戶,並提供精準的銷售名單給業務員。」讓業務員可以花時間去經營、銷售較容易購買保險的客戶,把時間花在刀口上,去創造客戶對於保單的需求。

ok! 簡單來說就是面向「銷售端」的資料科學應用,我們要產出一個名單,讓業務員精準銷售。

這個題目背後其實非常常見,電商的郵件推送、App內通知、推薦系統等其實就是在「精準銷售」,也就是「花錢、花時間在對的人」上面,進而有效率地增加業務收入。以金融的道理來說,就是提高ROI,讓投資更有效率、鎖定正確的標的(人)來銷售。

那麼第一步,我們切入比賽主要就是先「了解資料」,主辦方提供的資料是經過轉換過後、但是保留原本意思的資料,這意味著我們可以從探索性資料分析的過程得到一些有趣的洞見,因為變數名稱都是有意義的,也對後續的特徵工程有所幫助。

這場比賽的Trick

下面就簡單分享一下自己的workflow,身為一個「方法論的愛好者」(X

我有很多workflow,分別針對商業分析、數據分析、偏硬的專案(那種資料欄位本身就很難理解的賽事、分析)又有幾個框架,這次比賽我挑選了其中一個來開局:

領域知識的部分

我自己因為對金融、保險業本身就蠻有興趣的,所以關於Domain knowledge的部分…..有筆記可以看哈哈哈哈,且過去商業競賽時我本身也是與某家保險公司合作,算是有一點點經驗。

我大概先花了四個小時看了一些保險介紹的網站、使用管顧的方法來research,算是知道一些保險商品的設計以及常見的名詞,不過也還沒有深入研究,只不過摸了個大概:

截圖自我的筆記之一小部分,裡面會有一些我從本科其他課程學到的東西XD

我自己不喜歡完全不了解資料就開始做「分析」,即使背景知識並不能完全幫助到比賽,多認識一門學科也是好的,所以到這邊:

我其實只是「真的了解每一個資料欄位都代表什麼含義,並了解相關背景知識」,而這個步驟花了我四個小時左右。

學好資料庫,掌握資料表的概念

ok,接下來就是看資料,由於這次比賽的數據被主辦單位處理過,一些特徵都已經被One hot Encoding了,造成原始資料是一份非常多變數的資料表。那麼我怎麼做呢?

先切!這麼大的資料表,看了應該會頭暈吧?

不只OHE那麼簡單,我稍微看了一下資料,簡單把原始資料又分類為行銷、個人金融、商品等等……….好幾張資料表(這些區塊並非官方分法,而是我歸納變數並且自己命名之,這裡也不便透露主辦方使用了哪些資料),這樣的分法其實是為了建立關聯特徵使用,我自己比較習慣處理個別資料表,最後在合併到一起,除此之外這也是因為比賽畢竟是團隊的事情,在業界執行資料科學專案也是,切開表格後續會比較好分工,比如說分工探索變數、建立特徵等等…….

人工檢視資料表並歸納,可以用心智圖、Evernote輔助,我大概花了20分鐘,這是為了開始分析之後節省更多時間,與調整資料到自己熟悉的形式

我們要Manage 自己操作的data,所以資料庫管理的觀念真的很重要(其實就合併、拆分、取數那些,然後一對多、多對一的觀念要有,這些就蠻夠了,不過我對CV領域不熟,這邊是指格式化資料的資料庫觀念)

接下來,我們就開始看資料,原則上我先做的事情是「build baseline」,因為第一天我就想先衝一波了XD,可以提交就不要浪費主辦方幫你改考卷的機會呀!

所以馬上「什麼特徵都不做、EDA也不做」,直接把資料處理一下,然後丟進XGboost run一下,submit出來看看。選Tree base的model有什麼好處呢?就是我們可以利用變數重要性來縮減要看的變數,聚焦在重要的變數上。

其實這個我蠻常用的,就是如果剛開始變數很多一個個去畫圖、看變數其實很沒效率,這應該是後續優化特徵要做的事情。

也有一個開局策略是「零模型」,畢竟這是一個分類問題,先全部提交0,如果跟baseline表現差不多,那說明資料有很多Noise,我們要嚴格檢視變數。

事情沒那麼順利,關於特徵缺失

資料真的缺失得很嚴重,這邊我是用一個策略來處理,不過其實蠻複雜的,我們這邊就pass不講,我覺得也可以用變數相關性來看,這個蠻有用的,比如說手邊有人口資料,即使我們不知道這筆資料的性別是什麼,如果他的購買記錄中是內衣、女性用品等等….那我們就可以推測這應該是女性,類似的概念,在Python中有個套件是 missingno.可以幫助我們找出類似這種關聯。對,baseline比較困難的地方大概就這邊。

比賽初期,馬上寫一個Baseline,確保提交的格式正確與有可試驗的基礎模型,耗費時間:4小時

所以如果要混分,接下來一個多月就調整baseline的參數就好了XD

那麼從0到建立一個可用的模型並提交成功,我大概花了9個小時左右。(兩個下午)

開心調參(??

不過當然不可能,既然能夠玩到金融業的資料,就要好好享受一下!

所以接下來就來到我最擅長的EDA(探索性資料分析),這邊就簡單分享幾個我覺得「以建模預測為目的」跟「以解釋為目的」的EDA,區別以及要注意的幾個點。

通常,建模任務會比較「需求導向」,我們很功利主義的只去探討跟label「明顯」有關的變數,而且是看得很深入的那種,通常我會著重研究訓練、測試資料集的資料分佈狀況。

假如趨勢一致,但是分佈卻有些微不同,那就很糟糕了,比如下面這張圖(不是比賽的資料,僅是我模擬出來的類似舉例)

假設上面這張Female跟Male是Train、Test data,那你就會發現到雖然X、Y是正向關係,但是但是,Test data的Y在X比較大的時候,幾乎都大於Train data,那就要小心了,通常比賽單位資料都切得不是很優(增加挑戰性?),要馬時間穿越(Time Series的比賽會出現)、要馬分佈出現上面那種情況。

而解釋為目的的EDA通常用在商業分析,這種我們就可以很開心的玩資料,就是反覆提出假說、驗證、再提出假說的過程。

這樣的EDA有助於我們挖掘到市場、消費者行為的蛛絲馬跡,在一些資料科學比賽上儘管依然管用,但是卻不夠有效率,如果時間允許,這樣的EDA方式我覺得是比較健康的,在報告、總結階段也可以說出好的故事。

然而我們平常都有自己的事情要做,像我就是一邊忙兩個社團、修一堆重課(還貪心想拿卷)、考英語檢定、實習工作、準備講課、做管顧 + 系上專題、籌劃工作坊、跟顧好感情方面XD

然後堅持1點前睡、8點起的人(? 所以時間不足也是我覺得這次沒能拿到更前名次的殺手,時間不夠用!即使我對自己時間管理很有自信也一樣Orz

總之在資料科學的分析專案上面,我覺得要很了解自己以及規劃時間,才知道要用哪種策略去分析資料,否則會造成產出效率低、對大量資料暈眩的情況

所以在比賽第三天,我甚至想直接暴力產生feature然後丟進去(速成特徵),這麼做的結果是一個小時左右就生成了500多個features…

對,理所當然的模型就是一個_____,Garbage in garbage out,不過讓我對維度災難的體認更深了, 這邊學到的一課是:自動生成特徵雖然聽起來很夢幻,但也很難駕馭。畢竟資料一大,要跑Auto feature engineering應該會跑個沒日沒夜(而且這種乾脆可以嘗試NN切入),但資料小,生成的那麼多特徵一定會造成維度災難,稀疏到不行,甚至根本沒辦法用。

自動特徵工程可以嘗試,但不用期待。

那我們乖乖去EDA吧

這邊因為我是Tree model開局的, 所以我僅針對重要的特徵歸納、理解,的確有很多有趣的資料,對特徵工程很有幫助,比如說你可以發現地區間的差異很明顯、歸納與推論變數背後的意涵,比如某某通路是否就是在暗指「某險種」呢?險種之間的關聯有什麼?我覺得都是可以去探討一下的。後續的特徵工程我也參考了很多EDA的想法,這邊建議:EDA開一本Jupyter Notebook(如果你是用Python)獨立做,把發現的insight寫到共享記事本裡面(Google docs、Evernote),不過我最近發現某產品超適合做Data Science project management的應用,之後有機會再分享。然後建模是額外寫一個Jupyter,都放在同一個資料夾下面,像是這樣:

這邊因為這個資料夾在我的筆電裡面,所以名稱很亂(只有我看得懂XD),但是團隊共事還是要規範好共享文件名稱,比如說TEAMMEMBER_TIME_ + EDA/Model/Feature/Library 之類的,相信我,這在比賽末期要結尾報告的時候,你會很感謝自己這麼有條不紊。

如果比賽會用到其他資料,我會設計程式碼、資料、Python腳本、baseline、model的文件夾,統一放在以專案名稱為名的檔案夾下面,但是這次比賽相對比較單純,所以沒有這麼做。

不要小看檔案管理,這在統合程式碼與協作、最後報告上面很重要,會比較有效率!

然後呢,有些特徵真的做壞了、Noise非常高,這點在EDA可以發現的,如果沒有相關性強的資料可以推敲,就忍痛刪除吧!下面這張為示意圖並非比賽資料畫出來的結果,然而這場比賽中確實有發生類似的情形:

-100%?

簡單說一下這張圖,我們看到「valid correlation with train trend:-100%」,意思其實就是train、valid data的相關完全相反,什麼意思呢?想像你今天前面有一個選擇題:A、B、C,誰最會吃? 你看了一下資料覺得是B好了,這時候答案公佈是C,於是你修改了自己的認知,調整到符合C情況的人就是會吃,結果明天再問你一模一樣的問題,這次答案變成了A,那「會不會吃,這種情況」,顯然有兩種可能。

第一是「答案錯了」,非A即C,第二種可能是「題目問錯了」,也許有更明顯的問題可以區分出該回答A、B、C哪一個,而不是「誰最會吃」這個問題,重點來了,我怎麼知道呢?這個就是Noise的其中一種,我們應該刪除這種特徵,模型會被教壞、無所適從。

還有一個我覺得對於建模的EDA必做,就是上面提到的「資料分佈」,透過資料分佈,我們可以摸索出資料結構,就方便建立特徵。

比如針對連續變數看到有五個峰值,那麼就可以根據這五個峰值去切出6個群體,這樣就有一個新的變數產生了,而這種特徵往往是很管用的,或者代替連續數值輸入到模型裡面。Python裡面只要使用seaborn的distplot就可以囉,真的非常方便。

關於建模,我做了哪些事情

依然還是特徵工程、EDA、反覆檢查變數與新特徵,這邊有個很重要的道理是:

做出幾個有用特徵不要太得意,因為老實說會讓error analysis變得更複雜

當變數一多,其實就很難管理了,要知道我們寧願做出一個10個變數,準確度90%的模型,也不要1000個變數,準確度92%的模型,即使特徵是有用的,但是共線性的機會提高、越來越難解釋也是一個建模需要考慮的點,勇敢捨棄變數,我覺得這點對後續比賽的成績提升其實是很核心的觀念。

然後我也參考了李宏毅教授的方法,分析不同模型的表現與幫助模型分得更開,類似下圖:

比較不同模型

這在後面的Stacking很有幫助,也要確保模型彼此間的性能是相似的。基本上因為線性模型有設置weight,所以recall會高很多,預測為購買的可能性也比較大一些。

這邊我有試著劃分模型,在Stacking中讓大於某項機率的結果全部由LGBM預測,而小於該閥值的結果全部由Logistic預測,但是效果下降。

可以分析與比較不同的模型的性能,比如下圖是我與隊友做出各個模型之後比較機率的表格:

每一筆都代表預測這個人會不會購買的機率

由於資料是不平衡資料集,所以我也想用Clustering的方法,結合分類模型來做,但是!

放棄TSNE,本來想要利用manifold的方式將資料切得更開,但是跑太久了,不符合經濟效益。還有就是利用train、valid來驗證去除不同feature對模型的影響,基本上noise跟變數的拿捏不好掌控,就要用下面這種trial error的方式。Embedding也是,我的感覺是feature即使微弱,有比沒有好。不過去除最好的情況下,model的分數在LB上上升了0.001。下面是我寫的腳本,可以幫我篩選Noise的接受程度:

分析probability,給模型信心,截止前一個禮拜我花了幾乎半天的時間做Stacking,另外多寫了一個關於機率的非線性轉換函數(這個思路是來自李宏毅老師的課,當模型信心不夠的時候給他一點信心),從34名衝到第19名。隔天繼續做機率分析又從小跌的21名前進到第16名,排名相當於從13%移動到7%。另外logistic表現得recall rate高很多,也導致比較高估的結果。

為什麼不用很潮的神經網路呢?

資料其實不大,果斷放棄NN,因為太難控制了,尤其train、test的資料切得並不是1:1,用NN太容易Overfit,用AutoEncoder的效果也不是很好。說到這個,因為這種資料本身屬於不平衡資料,本來我想用異常檢測的角度去解,所以想到了AutoEncoder,也可能是我對NN理解得不夠深入、或者我猜資料真的不夠大,總之效果很差。

遺憾的地方是,我發現XGBoost的leaf encode其實不錯,我們如果將預測值 * 100分箱取整數應該是一個很好的特徵。可惜比賽很後期才發現(那時候我已經分身乏術XD 太多外務),因此作罷。

最後Public排名24,Private排名19,可見有些前面的隊伍overfit了。

賽後心得

整體而言,我覺得這次比賽學到很多,畢竟就是實際去解一個業界案例,真的非常有趣,時間允許的話我會想多做一點論文的研究、或者試試看一些新想法與實作Paper,可惜都無從驗證了。另外聽學長說今年的比賽電資的參加人數突然變高,之前比較多是統計背景,就我看排行榜,也有看到臺大資工(話說他們隊名很有梗XD)、臺大電機Lab的人馬,其他還有像是北大統計、中央AI Lab的(我從隊名猜的啦)然後政大這邊主要就是統計、資科、資管(我)背景的人會去打。

說說幾個可以改進的點:

  1. 可以提供訓練與mentor

像是SAS好像就有提供工作坊,但是國泰這個好像就是高手過招的感覺,我覺得訓練是還好,但是有個mentor可以指導,或者請教業務知識會學到更多,也會讓模型報告更有看頭。

2. 討論風氣可以再改進

這點跟Kaggle真的差很多,也許是學生比賽吧,大家都各做各的,但是我在Kaggle上光逛論壇就很有收穫,即使沒參加某場比賽、很有興趣的話看看大家的討論也可以得到一些東西,我覺得企業或者學校方面,需要有一個相關經驗的老手先針對賽題難點做個分析、主辦單位設計鼓勵貢獻的機制等等……..這點真的很重要。

3. 其實不用會讀Paper、CV、數學也不用到很「好」,資料處理才是重點

這句話有點極端,但也是事實。我看過太多人就是狂啃數學,但是程式實作能力很差,差到也不知道怎麼修改模型。或者會讀Paper,但卻用不起來,只會概念的接收其實沒什麼意義(要真的動手,不要怕把手弄髒),除非有很強的隊友幫忙實作。資料處理真的很基本,最好要有幾個資料分析的專案經驗、順過幾次workflow會比較得心應手。所以!入門機器學習、深度學習的方式不是讀論文,除非你真的要做research,先從案例入手會比較有感覺。

最後是關於比賽,有什麼準備建議嗎?

嗯…不會寫程式沒關係(不過隊友一定要有人會寫),但看得懂別人的code、或者敢於提出自己的想法、讀一些圖表蠻重要的。因為真的要學生懂商業、數據、演算法又要會寫code、又有經驗,這種人不多,大多還是電機資工的學生比較有優勢,想要競爭的話,先認識自己的強項,彌補弱項我覺得是最重要的。可以學點資料處理的code,才不會對資料感到無力。

最後我想感謝我的隊友,冠廷、秉宏、禹翔,感謝大家一起完成跟論文很像的最後報告、以及我們體驗的整個過程:)

如果有更多問題,再歡迎資料科學比賽、商管同好交流交流!

歡迎想學習Python資料科學、商業分析、金融知識的人一起交流!本部落格的內容全部都是基於「分享」的實作、理論兼顧文章,希望能夠幫助到所有對資料科學領域有興趣的人們,長期關注可按左手邊的Follow!若喜歡我在 Medium 的內容,可以拍個手(Claps)這邊想做個實驗,好讓我知道你/妳喜不喜歡這篇文章:
拍 10 下:簽個到,表示支持(謝謝鼓勵!)
拍 20 下:想要我多寫「商管相關」
拍 30 下:想要我多寫「資科相關」
拍 50 下:我有你這讀者寫這篇也心滿意足了!

敬請期待下一篇!或是您也可以逛逛我的其他資料科學文章:

人工智慧商務系列:

Python資料科學系列:

看我用金融的概念解釋AI:

如果想跟著我實作資料科學,開始寫程式必知必會基礎系列:

--

--

戴士翔 | Dennis Dai
Finformation當資料科學遇上財務金融

外商分析顧問,Ex- Apple Data Scientist,曾在FMCG巨頭/日商管顧/MBB管顧/高成長電商從事商業分析與數位轉型,專注分享管顧、商業、數據分析的思考。分析/演講/合作歡迎來信:dennis.dai.1011@gmail.com