阿里天池大數據競賽心得 : 前50強付出與回報
終於比賽還是結束了,想說研一一半的青春奉獻給了阿里,最後艱難擠進了前五十,一路過來真心不容易,每天早上醒來的第一件事就是查成績,三個月來天天如此,晚上熬夜提交預測,那樣的日子想說愛你不容易。。。回顧一路走來的艱難歷程,回味其中的付出和收穫,謹以此文獻給一路走來一起奮鬥的小夥伴,么么噠···~~~~~
(一)初識阿里大數據比賽
一次偶然的機會,在去實驗室的路上見到了阿里天貓推薦演算法的比賽海報,對近來炒得很火的大數據有很濃的好奇心,點開報名網址,大數據比賽,便踏上了接近四個月的阿里競賽之路。
比賽大概的描述是:第一賽季阿里官方提供少量的某年4-15到8-15這段時間離線的天貓真實行為數據,參賽者利用機器學習的方法,預測8.15-9-15的用戶購買情況,具體評分方式為:根據預測的正確率和召回率計算出調和平均得分來考量參賽者的成績,如下圖所示:
接觸第一賽季的時候,比賽已經進行了半個多月,由於非CS出生,機器學習方面只學習過皮毛,做過一兩個實驗。。。可以說經驗匱乏,草草的和實驗室隊友組隊了(草率的決定讓自己後來說不出的心酸...無力吐槽),第一次胡亂的提交了一次成績,第二天就有了成績啦,看到了成績以及排名,當時還有點小興奮,雖然成績不好,總算有個成績啦。。。
接下來幾天成績都有小幅度上漲,具體的做法是利用學習過的邏輯回歸LR和加一些簡單的統計規則進行推薦,一些簡單的規則有:利用用戶對品牌的點擊、購買、收藏、加入購物車這四種基本操作給品牌打分,將得分較高的品牌推薦給用戶,做了半個多月,成績一路上漲
最後還是穩穩的進入了前500名,得到了接觸第二賽季的機會,賽季結束的時候,官方組織確定了最終的參賽隊伍信息,第一賽季幾乎是一個人戰鬥的我,選擇了重新組隊,和室友新組建了一個2人小隊,擠進第二賽季,當時定下的目標,衝擊一百萬,贏取白富美,出任CEO,走上人生巔峰,小小興奮了一把(~純屬自娛自樂~)
(二)第二賽季「血拚」
休整了幾天之後,阿里開放了第二賽季的天池大數據計算平台ODPS供參賽者使用,對於第一次接觸大數據分析平台的我們來說,真是啥都不會。。。三個月的奮鬥,我們組大概用了純規則、LR、RF、GBRT四種方法,其他的一些SVM、貝葉斯等方法效果甚微,淺嘗輒止。
2.1、SQL純規則
第一時間打開了提供的ODPS用戶手冊,看了簡單的入門之後,就開始弄了,再次從0開始學習,這次提供的用戶操作記錄數比第一賽季高了幾個數量級,達到了5億的規模,直接按照手冊提供的sql語句添加的簡單規則(給用戶推薦熱門的10個商品)進行了一次的提交,結果就有了成績,小激動啊:
接下來的幾天,按照第一賽季的流程,對數據進行預處理,刪除未購買過品牌的用戶記錄(不刪除最近一周才出現的新用戶),刪除未被購買過的品牌記錄,刪除瘋狂點擊但是從不購買的刷鑽用戶記錄等,利用一些簡單規則:定義熱門品牌集合,交互時間記錄統計,活躍用戶集合,最近新出現的品牌集合,周期品牌集合,用戶的品牌忠誠度,用戶對品牌的操作加權打分等規則,每加一條規則,成績都蹭蹭蹭往上漲(畢竟我們的baseline還很低),幸福洋溢的感覺有木有:
提升了幾天,絲毫沒有察覺到規則帶來的局限,依靠純規則推薦,挖掘不出用戶購買行為深層次的關係註定有提升上限,做了接近10天的規則成績漲到3.9左右,不管怎麼添加規則,我們的成績也始終上漲不了了。
2.2、LR模型
考慮轉到LR模型,要想利用模型訓練,首先得在與處理之後的數據之上,劃分好線上和線下數據集,參考阿里討論群和BBS上面的數據集劃分,由於題目是利用4個月交互數據預測第5個月購買,故我們線下也是將已知的四個月數據平均分為5部分,利用前4部分數據預測第5部分購買情況,構建的線下數據集和線上數據集具體為:
2.2.1、線下:
訓練:篩選出4月15號到7月02號的有過交互記錄的,並且在7月03號到7月21號發生購買的用戶品牌對作為正樣本,將4月15號到7月02號剩下的記錄作為負樣本,構建好特徵後,訓練到線下的LR模型;
預測:利用4-15號到7月21號的所有數據,構建好特徵後,帶入線下訓練好的LR模型進行驗證;
2.2.2、線上:
訓練:篩選出4月15號到7月21號的有過交互記錄的,並且在7月22號到8月15號發生購買的用戶品牌對作為正樣本,將4月15號到7月21號剩下的記錄作為負樣本,構建好特徵後,訓練到線上的LR模型;
預測:利用4-15號到8月15號的所有數據,構建好特徵後,帶入線上訓練好的LR模型進行推薦;
數據集劃分好後,我們組花了大量的時間構建特徵,從三個角度出發,用戶品牌交互特徵類,用戶特徵類和品牌特徵類,到第二賽季結束的時候,累計構建了715個特徵(真的是一個比拼特診構建的比賽了),只羅列出我們組最後用上的效果比較好的一組特徵,詳細如下:
2.2.3、用戶品牌交互特徵類
構建用戶與品牌之間交互的統計特徵,體現用戶與品牌之間的交互特性,大致反映出用戶與品牌之間滿足某種映射下會發生購買行為,大概有:
click_count :用戶A對品牌B的總點擊數 buy_count :用戶A對品牌B的總購買數 collect_count :用戶A對品牌B的總收藏數 cart_count :用戶A對品牌B的總加入購物車數 avg_buy_day_count :用戶A對品牌B的各次購買離現在的平均天數 variance_buy_day_count :用戶A對品牌B的各次購買離現在的時間的方差 least_click_day_count :用戶A對品牌B的最近一次點擊離現在的天數 least_buy_day_count :用戶A對品牌B的最近一次購買離現在的天數 least_collect_day_count :用戶A對品牌B的最近一次收藏離現在的天數 least_cart_day_count :用戶A對品牌B的最近一次購物車離現在的天數 click_count_before_firstbuy :用戶A對品牌B的第一次購買前的點擊數 collect_count_before_firstbuy :用戶A對品牌B的第一次購買前的收藏數 cart_count_before_firstbuy :用戶A對品牌B的第一次購買前的購物車數 avg_click_day_interval :用戶A對品牌B的平均點擊天數間隔 avg_buy_day_interval :用戶A對品牌B的平均購買天數間隔 first_operator_day_count :用戶A對品牌B的第一次交互離現在的天數 last_operator_day_count :用戶A對品牌B的最後一次交互離現在的天數 max_operator_Day_count :用戶A對品牌B的交互次數最多那天離現在的天數 user_buy_brand_rate :用戶A對品牌B的購買次數佔用戶A總購買次數的比例 user_click_brand_rate :用戶A對品牌B的點擊次數佔用戶A總點擊次數的比例 click_buy_rate :用戶A對品牌B的點擊購買比 click_2_count :用戶A對品牌B的點擊數的平方 buy_2_count :用戶A對品牌B的購買數的平方 brand_is_bought_rate :用戶A對品牌B的購買次數占品牌B被購買的總次數的比例 brand_is_clicked_rate :用戶A對品牌B的點擊次數占品牌B被點擊的總次數的比例 last_31_day_click_buy_rate :用戶A對品牌B的最近31天的點擊購買比 click_day_count :用戶A對品牌B的點擊總天數 buy_day_count :用戶A對品牌B的購買總天數 buy_last_week_count :用戶A對品牌B購買了多少周 avg_click_rate_before_buy :用戶A對品牌B最後一次購買後的點擊數/用戶A對品牌B每次購買前的平均點擊 avg_collect_rate_before_buy :用戶A對品牌B最後一次購買後的收藏數/用戶A對品牌B每次購買前的平均收藏 click_delete_user_avg_rate :(用戶A對品牌B的點擊數-用戶A對操作過的品牌的平均點擊數)/用戶A對操作過的品牌的平均點擊數 buy_delete_user_avg_rate :(用戶A對品牌B的購買數-用戶A對操作過的品牌的平均購買數)/用戶A對操作過的品牌的平均購買數 collect_delete_user_avg_rate :(用戶A對品牌B的收藏數-品牌B被平均收藏數)/品牌B被平均收藏數 before_0_day_last_5_day_click_count :用戶A對品牌B離現在5天之內的點擊數 before_0_day_last_5_day_buy_count :用戶A對品牌B離現在5天之內的購買數 before_0_day_last_5_day_collect_count :用戶A對品牌B離現在5天之內的收藏數 before_0_day_last_5_day_cart_count :用戶A對品牌B離現在5天之內的加入購物車數 before_0_day_last_10_day_click_count :用戶A對品牌B離現在10天之內的點擊數 before_0_day_last_10_day_buy_count :用戶A對品牌B離現在10天之內的購買數 before_0_day_last_10_day_collect_count :用戶A對品牌B離現在10天之內的收藏數 before_0_day_last_10_day_cart_count :用戶A對品牌B離現在10天之內的加入購物車數 before_10_day_last_10_day_click_count :用戶A對品牌B離現在10天之前的10天之內的點擊數 before_10_day_last_10_day_buy_count :用戶A對品牌B離現在10天之前的10天之內的購買數 before_10_day_last_10_day_collect_count:用戶A對品牌B離現在10天之前的10天之內的收藏數 before_10_day_last_10_day_cart_count :用戶A對品牌B離現在10天之前的10天之內的加入購物車數 before_20_day_last_10_day_click_count :用戶A對品牌B離現在20天之前的10天之內的點擊數 before_20_day_last_10_day_buy_count :用戶A對品牌B離現在20天之前的10天之內的購買數 before_20_day_last_10_day_collect_count:用戶A對品牌B離現在20天之前的10天之內的收藏數 before_20_day_last_10_day_cart_count :用戶A對品牌B離現在20天之前的10天之內的加入購物車數 before_30_day_last_10_day_click_count :用戶A對品牌B離現在30天之前的10天之內的點擊數 before_30_day_last_10_day_buy_count :用戶A對品牌B離現在30天之前的10天之內的購買數 before_30_day_last_10_day_collect_count:用戶A對品牌B離現在30天之前的10天之內的收藏數 before_30_day_last_10_day_cart_count :用戶A對品牌B離現在30天之前的10天之內的加入購物車數 before_0day_last_10_day_click_day_count:用戶A對品牌B離現在10天之內的總點擊天數 before_0day_last_10_day_buy_day_count :用戶A對品牌B離現在10天之內的總購買天數
2.2.4、用戶特徵類
構建體現用戶特性的特徵,盡量挖掘處用戶購物行為習慣,大致有如下特徵:
user_buy_count :用戶A總購買的次數 user_click_count :用戶A總點擊的次數 user_collect_count :用戶A總收藏的次數 user_cart_count :用戶A總購物車的次數 user_click_buy_rate :用戶A總的點擊購買比 user_avg_buy_day_count :用戶A所有購買發生的時間離現在的平均天數 user_least_buy_day_count :用戶A最近一次購買離現在的天數
user_variance_buy_day_count :用戶A所有購買發生的時間離現在的時間方差
user_last_5_day_click_count :用戶A最近5天的點擊總數 user_last_5_day_buy_count :用戶A最近5天的購買總數 user_last_5_day_collect_count :用戶A最近5天的收藏總數 user_last_5_day_cart_count :用戶A最近5天的加入購物車總數 user_click_day_count :用戶A點擊的總天數 user_buy_day_count :用戶A購買的總天數 user_collect_day_count :用戶A收藏的總天數 user_cart_day_count :用戶A加入購物車的總天數 user_buy_brand_count_for_1_week:用戶A只購買1周的商品有多少種user_buy_brand_count_for_2_week:用戶A只購買2周的商品有多少種
user_buy_brand_count_for_3_week:用戶A只購買3周的商品有多少種 user_buy_brand_count_for_4_week:用戶A只購買4周的商品有多少種2.2.5、品牌特徵類
構建體現品牌特性的特徵,盡量挖掘處什麼樣的品牌受用戶追捧,會被用戶購買,大致有如下特徵:
brand_click_count :品牌B被點擊的總次數 brand_buy_count :品牌B被購買的總次數 brand_collect_count :品牌B被收藏的總次數 brand_cart_count :品牌B被加入購物車的總次數 brand_click_buy_rate :品牌B的點擊購買比 brand_last_3_day_click_count :品牌B最近3天之內的點擊總數 brand_last_3_day_buy_count :品牌B最近3天之內的購買總數 brand_last_5_day_click_count :品牌B最近5天之內的點擊總數 brand_last_5_day_buy_count :品牌B最近5天之內的購買總數 brand_last_11_day_click_count :品牌B最近11天之內的點擊總數 brand_last_11_day_buy_count :品牌B最近11天之內的購買總數 brand_least_operator_day_count:品牌B最近一次被操作離現在的天數 brand_first_operator_day_count:品牌B第一次被操作離現在的天數 brand_hot_level :品牌B的熱門度(點擊數*0.1+購買數*5+購物車數+收藏數) user_count_buy_brand_morethan_2week :購買品牌B超過兩周的用戶數 user_count_buy_brand_morethan_3week :購買品牌B超過三周的用戶數 user_count_buy_brand_morethan_4week :購買品牌B超過四周的用戶數 user_count_buy_brand_equal_1week :購買品牌B為1周的用戶數 user_count_buy_brand_equal_2week :購買品牌B為2周的用戶數 user_count_buy_brand_equal_3week :購買品牌B為3周的用戶數 user_count_buy_brand_equal_4week :購買品牌B為4周的用戶數 brand_hot_ave_level :品牌B的熱門度(點擊數*0.1+購買數*5+購物車數+收藏數)/(品牌B第一次被操作和最後一次被操作的時間間隔天數)
2.2.6特徵計算
利用天池平台的分散式計算。我們組寫了三個MapReduce程序,Map階段分別根據userbrandgroup、usergroup、brandgroup進行拆分,Reduce階段分別計算出三類特徵的數值,後面就是簡單的多張特徵表的合併操作,線下的訓練和預測的特徵總表的MR處理是一樣的,只有輸入時間不一樣,如下所示:
<pre name="code" class="sql"><pre name="code" class="sql">//線下訓練特徵總表 create resource jar C:TOOLSmapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:TOOLSmapReduce-getCharacter.jar com.mr.userbrandgroup.MyDriver LR_Offline_Train_Table LR_Offline_Train_Feature_1_Table 04-15 07-02 1; create resource jar C:TOOLSmapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:TOOLSmapReduce-getCharacter.jar com.mr.usergroup.MyDriver LR_Offline_Train_Table LR_Offline_Train_Feature_2_Table 04-15 07-02; create resource jar C:TOOLSmapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:TOOLSmapReduce-getCharacter.jar com.mr.brandgroup.MyDriver LR_Offline_Train_Table LR_Offline_Train_Feature_3_Table 04-15 07-02; //線下預測特徵總表 create resource jar C:TOOLSmapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:TOOLSmapReduce-getCharacter.jar com.mr.userbrandgroup.MyDriver LR_Offline_Validate_Table LR_Offline_Validate_Feature_1_Table 04-15 07-21; create resource jar C:TOOLSmapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:TOOLSmapReduce-getCharacter.jar com.mr.usergroup.MyDriver LR_Offline_Validate_Table LR_Offline_Validate_Feature_2_Table 04-15 07-21; create resource jar C:TOOLSmapReduce-getCharacter.jar -f jar --resources mapReduce-getCharacter.jar --classpath C:TOOLSmapReduce-getCharacter.jar com.mr.brandgroup.MyDriver LR_Offline_Validate_Table LR_Offline_Validate_Feature_3_Table 04-15 07-21;
在進行LR模型的時候,我們根據文本檢索裡面的對數處理準則,對計算到的特徵總表進行了整體對數化處理,之後便是對正負樣本進行單獨抽樣得到一個較小的數據集進行訓練,抽樣總數為330W,抽樣比例為10:1(後面改到8:1有小幅度提高),LR模型由於構建數據集和特徵,熟悉MR,所以上手的時間很長,做了一周左右,提交的成績不好
不斷添加和測試新的特徵,兩三天的時間,成績就有了起色,之前規則的得分上線被LR打破,停滯的F1終於開始漲了,這段時間由於做的有點疲倦,加的特徵不夠多,成績上漲的斷斷續續,F1上漲到接近5的時候又出現了瓶頸,再怎麼添加特徵都不怎麼漲了:
這段時間,LR的瓶頸讓我們放棄了對它的執念,看到競賽群里火熱的討論著RF,我們決定轉投RF。。。
2.3 RF
我們利用LR最好的一組特徵直接轉到RF模型上面來進行訓練預測,得到的線下成績很差,線上的成績也低得嚇人
感覺我們組好悲催,別的組都能直接從LR過渡到RF上面來,我們又要重新測試一下特徵,不能直接轉過來,花了兩天的時間,成績稍微正常了一點,但是離LR最好還是差了一大截啊,懷疑我們的方法哪裡出問題了,這段時間又是考試周臨近,真真的頭疼啊(看到別的組天天都在上升,飢餓遊戲,滋味不好受,還是每天抽出兩三個小時來做比賽)排錯排除了一周左右的時間,成績上漲到和LR差不多的水平了,當時那個開心啊,呵呵,回味無窮。
然後,就正式進入考試周了,比賽的時間壓縮到極致,兩人都忙於複習,比賽做的比較水了,中途不知道哪裡出問題了,提交的成績創歷史之最了。。。商量之後決定,決定暫時不搞了,差不多停了兩周左右
考完試,和隊友也差不多忙完了,每天空閑時間相對多了起來,決定重操舊業,」享受早上起來看成績興奮的那一瞬間「,我們花了兩天時間重新排查了一遍程序,決定暫時先不對數據做預處理,利用選好的特徵,終於得到了超過LR最好得分的成績,一舉破5,停滯的baseline終於開始上漲啦,(果然是預處理影響了我們的模型型。。。當時猜想是數據清洗的過度了,後來也試過刪除一些刷磚用戶,但是效果甚微)基本上方法對了之後,我們就不斷添加新的特徵,這幾天基本實現兩天一個大提升,特徵總數也達到了500多,實際用上的特徵從30多個,到了接近70個了。
我們RF訓練用的方法基本上是界面的方式實現的,成績上漲到5.66這個水平就不太好上升了,試了兩三天效果都不好了,正好碰到群里又在火熱的討論gbrt,對於我們來說又是一個新的模型,我們商量之後,沒有猶豫,立馬決定轉到GBRT,繼續馬拉松。。。
2.4 GBRT
學習了兩天的GBRT界面操作(因為一直沒注意看BBS的更新資料,導致我們知道7月中旬都一直還在用界面訓練預測,耗時耗力。。。),便開始實戰了,果不其然,直接RF最好特徵轉過來,效果又是差的離奇,(奇了怪了,這也太悲催了吧),這兩天和哈工大EvilSmart隊的大帥交流了下GBRT的使用心得,終於還是步入了正軌,成績又開始歡快的漲了,漲了。。。
成績上了5.8之後,上漲的就有點吃力了,不斷添加新的特徵,不斷換數據預處理,經過一周的操作,成績上漲到
還是沒能上5.9,我們這段時間嘗試過RF和GBRT模型融合,添加規則輔助推薦都效果不好,20號左右的時候,終於看到了腳本實現的文檔。。。再也不用手動訓練預測了。。。
2.5最後一周奮戰
24號阿里更新了一批等量的數據,當天晚上,趕在凌晨4點之前,在新數據集上跑完了第一次成績,當晚的成績終於破5.9啦
好景不長,接下來的一天,線下在提升,線上卻下降了,反思線下特徵過擬合了,在討論組裡大家都在議論著提升的問題,我們又重新梳理了特徵,再次添加了一批特徵,驚喜的發現線下提升了0.06達到了5.39,著實興奮了一把,果然,第二天成績怒破6.0,排名穩定在了前50名,激動不已。。。
接下來的幾天,我們繼續線下調試新特徵和試著融合,但是線下效果好,到了線上效果卻低於6.02:
最後一天,我們改變了正負樣本抽樣比例,換到了8:1,線下提升了0.02,線上定格在6.03。
幾個月來就基本沒有1點鐘之前睡過覺的,雖然辛苦,但是還是覺得收穫挺多,感謝阿里提供的這個平台,讓我們對大數據不再一無所知,感謝隊友朱凌雲的陪伴,感謝我們隊伍一路走來幫助過我們的哈工大-王帥同學和姚繼濤同學,感謝USTC的Cara、Closure、陳朝才和陳誠、李悅、以及寧波大學丁石磊同學,以及一些路見不平拔刀相助的壯士,么么噠O(∩_∩)O~
(via:瀚海小松)
微信公眾號:datafa(數據分析聯盟)
微信群:加V 784414374
QQ群:252805327
新書鏈接:
【數據分析俠 《人人都會數據分析》20萬字書籍】http://m.tb.cn/h.AJEkoq 點擊鏈接,再選擇瀏覽器打開;或複製這條信息¥fSnh09F0Vpy¥後打開 手淘
推薦閱讀:
※用數據對女生胸圍來次一本正經的探索吧!
※go語言如何入門,如何提高?
※大數據驅動的人工智慧時代,如何成為2%不被淘汰的人?
※假如海平面上升100米中國會怎麼樣?
※2017年數據分析實踐計劃