2018騰訊廣告算法大賽總結

        這是本人寫的第一篇博客,小白一枚,如有錯誤的地方,歡迎大佬們批評指教。

        首先這次的競賽讓人受益匪淺,那龐大的數據量,讓人感嘆這是一場有錢人的遊戲。感謝學校的服務器,幾乎沒休止的轉了一個多月,哈哈哈。

        雖然最後成績不咋地,但是這次成長還是很大的,特此總結以下經驗。

問題描述

        這次比賽的任務是尋找相似人羣,其實就可以看成是CTR問題。

關注官方競賽羣

        一般只要是比較正式的比賽都會有官方的交流羣,大家在這裏交流,同時這裏也是你成長的關鍵地方,如果比賽的等級夠高的話,會有一堆大佬,在羣裏給小白指點,但是同時也要擦亮眼睛,因爲有個別的人,會給小白錯誤的指導,所以最好找那種比較知名的大佬,有些大佬很熱情,但是有的就比較冷淡了。而且不要問一些很low的問題。。。最重要的是每年都會有baseline代碼,你如果錯過了,你在起跑線上就已經輸了。。。

充分利用github

        像這樣每年都會舉辦的比賽,每年github都上會出現一堆源碼,也許每年給的數據特徵以及數據量都不一樣,但是有些強特是公用的。而且對於一些典型的問題,比如CTR預估,已經有一些典型的模型,和其他人寫好的源碼,你不用就浪費了。

數據處理與特徵工程

        首先這種類型的競賽,數據就是根本,應該充分了解你的數據,才能無往不利。如何瞭解你的數據呢?plot,plot,plot,重要的事說3遍。對於ctr的數據,都有一個特點就是長尾數據。至於什麼是長尾數據,請自行百度。對於這種類型的數據,我主要對其進行的操作是,對尾部的數據數據設置成一個新的類別,至於尾部數據的閾值,可以plot之後自己調一下。通過這種方式我們組造了一個強特,有一個appInstall字段,這個字段代表的是60幾天的安裝的app,我們對這個字段進行了統計,統計了每個用戶在這幾天裏app安裝的數量,然後發現這是長尾數據,也就是大多數是這幾天裏沒有安裝app的,部分是安裝了特別多app的,這部分結合實際的話,其實是安裝app來刷單賺錢的人,對這部分人進行單獨的分類處理效果不錯,在初賽這個特徵提升了2個千分點。還有就是正負樣本的比例問題,對於此類問題,因模型而異,對於lgb模型的話,如果正負樣本差的很多的話,可以採取少採一些樣本的方式比較多的類型的樣本,比如ctr中正樣本極少,所以我們就抽了90%的負樣本和全量的正樣本訓練,訓練我們的lgb模型,效果也是在初賽提升了2個千分點。但是對於ffm這樣的流式訓練的模型的話,不建議這麼做,這樣做會降低模型的效果。至於其他的強特,都是從github源碼中挖掘出來的。

模型的選擇與調參

        初賽的數據量1000萬條數據,在未處理的情況下是4個多G的數據。複賽的數據翻了5倍,大約5000萬條數據,在未處理的情況下是20G。

        初賽我們使用的模型是lgb和FFM模型。複賽的話,用的是DeepFFM,Deepmvm,lgb等等。

lightGBM

        剛剛開賽幾天後,就有一個0.73的baseline上線,這個baseline非常的暴力,因爲給的特徵都是類別型的所以他對所有的特徵都進行了onehot之後進行,對於數據量特別大的情況下,一定要記得onehot之後一定要用sparse矩陣,要不然肯定爆內存,這個0.73的baseline,峯值用了服務器大約40G的內存。當然這是因爲沒有做內存優化的原因。其實當你數據量很大,但是手頭計算資源匱乏的時候,內存優化是不可缺少的一部分工作。至於調參工作,在數據量很大的時候有兩個方法,一個是按比例抽樣出小的數據集用以調參gradsearchCV是一個選擇,git上也有別人寫好的調參輪子,但是這個時候有可能會使你調出來的參數離最優參數很遠。還有一種方法就是控制變量法,其參數不變,每次只調一個參數,這個方法比較慢,但是能取得比較接近最優參數的結果。還有至於爲什麼要選擇lgb而不是xgb,其實很簡單,數據量太大,lgb的內存優化,能讓我們的服務器能夠承受得住。在lgb與xgb相同的參數時,lgb模型40G足夠,但是xgb模型64G也不夠。同時速度也是一個方面,lgb的話,據說速度比xgb快10倍。但是lgb的GPU加速部分,我嘗試了一下,其實基本速度沒什麼提升,顯存的佔用也是很低。複賽的時候,由於數據量大大增加,所以我們將數據分成5分,分別訓練一個模型之後,進行融合。隨後進行了內存的優化,可以分兩份,各訓練一個模型然後融合,模型的效果又有提升。

FFM

        臺大的一個隊伍開源的模型,git上有開源的源碼,其中libffm拋棄了一次項,速度快,make一下就可以用,由於是流式訓練,所以8g的筆記本都可以跑起來。模型的效果也是相當可觀的,與lgb的表現相近,但是還是與lgb差一點。這個模型的調參的話是相當重要的,最開始沒調參的時候,模型的線上效果才0.6,調完參數之後0.741,最好用上面的控制變量法調參。要是想用gradsearchCV調參的話,你可以用python重寫ffm,並且按照sklearn的標準編寫函數。順帶一提北京大學信息科學技術學院開發的xlearn,支持ffm,並且沒有拋棄一次項。

DeepFFM

        一到複賽,打比賽的方式就變了,可以說和初賽完全不一樣,首先是複賽的數據是初賽的5倍,這麼龐大的數據量,一次性全加載到內存是不現實的。所以最好利用python的yield,訓練一部分數據,加載一部分數據。當然這隻適用於流式訓練的模型。lgb的話,處理方法上文已經說過,不再贅述。至於什麼是DeepFFM請自行百度。接下來我說一下在編寫神經網絡時的一些心得,我主要用的框架是pytorch以及tensorflow,怎麼說呢?兩個框架各有利弊,首先說一下pytorch吧,這個框架極易上手,編程模式也是命令式編程,但是有益處當然也有很多的坑,其中我在這次比賽中遇到的坑就是pytorch裏最好不要用python的for循環,用也最多隻用一層,不然速度能慢死你,能用向量化優化的地方儘量優化一下,還可以用矩陣乘法來代替for循環,這種方式是最快的。pytorch還有一點好的地方就是你可以很輕鬆的配置多GPU並行加速訓練。接下來是tensorflow,這個框架就是申明式編程,一種你不熟悉的編程方式,有的時候很彆扭,但是很多優化的地方你都不需要做,直接調用api即可。但是tensorflow還有一個磨人的地方就是,你要是想多GPU並行運算的話,需要自己去寫,並不能直接像pytorch那樣,千萬別以爲tensorflow佔用了你所有的GPU資源,顯存也佔滿了,他就是在充分利用資源。這只不過是tensorflow的貪心特性,默認佔用所有可用的最好的計算資源,當然可以配置取消這種特性。

        還有最重要的一點:在這種數據量超大的情況下,在編寫神經網絡的時候,一定要弄一個小的線下訓練集,這樣方便調試bug,開發速度也快,切記切記!!!

模型融合

        這次的競賽我並沒有用stacking和blending這兩種常見的模型融合方法,感興趣的自行百度。我是直接用的結果取平均的方式,加權的方式我也試過,但是效果不如直接取平均好。還有就是融合的模型之間在原理上相差越多,融合的效果就越好,簡單的理解就是過擬合的部位不一樣,一取平均就減緩了過擬合的狀況。

總結

        參加競賽一定要一心一意扎進去,全心全意投入去做,纔會有提升,切忌心浮氣躁,最好不要雙開,除非你是大牛。希望你永遠保持着,大智若愚,求知若飢的心態。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章